cl: instr llgo.index/advance

This commit is contained in:
xushiwei
2024-05-07 16:05:18 +08:00
parent 942b1f5159
commit 5a5d86ccc3
7 changed files with 84 additions and 6 deletions

2
c/c.go
View File

@@ -41,7 +41,7 @@ type integer interface {
func Str(string) *Char
//go:linkname Advance llgo.advance
func Advance(ptr Pointer, offset int) Pointer
func Advance[PtrT any](ptr PtrT, offset int) PtrT { return ptr }
// llgo:link Index llgo.index
func Index[T any, I integer](ptr *T, offset I) T { return *ptr }

11
cl/_testlibc/argv/in.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import (
"github.com/goplus/llgo/c"
)
func main() {
for i := c.Int(0); i < c.Argc; i++ {
c.Printf(c.Str("%s\n"), c.Index(c.Argv, i))
}
}

50
cl/_testlibc/argv/out.ll Normal file
View File

@@ -0,0 +1,50 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@__llgo_argc = global ptr null
@__llgo_argv = global ptr null
@0 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main(i32 %0, ptr %1) {
_llgo_0:
store i32 %0, ptr @__llgo_argc, align 4
store ptr %1, ptr @__llgo_argv, align 8
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
br label %_llgo_3
_llgo_1: ; preds = %_llgo_3
%2 = load ptr, ptr @__llgo_argv, align 8
%3 = getelementptr ptr, ptr %2, i32 %7
%4 = load ptr, ptr %3, align 8
%5 = call i32 (ptr, ...) @printf(ptr @0, ptr %4)
%6 = add i32 %7, 1
br label %_llgo_3
_llgo_2: ; preds = %_llgo_3
ret void
_llgo_3: ; preds = %_llgo_1, %_llgo_0
%7 = phi i32 [ 0, %_llgo_0 ], [ %6, %_llgo_1 ]
%8 = load i32, ptr @__llgo_argc, align 4
%9 = icmp slt i32 %7, %8
br i1 %9, label %_llgo_1, label %_llgo_2
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare i32 @printf(ptr, ...)

View File

@@ -278,6 +278,8 @@ func (p *context) funcOf(fn *ssa.Function) (ret llssa.Function, ftype int) {
ftype = llgoCstr
case "advance":
ftype = llgoAdvance
case "index":
ftype = llgoIndex
case "alloca":
ftype = llgoAlloca
case "allocaCStr":
@@ -377,6 +379,12 @@ func cstr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
panic("cstr(<string-literal>): invalid arguments")
}
// func index(arr *T, idx int) T
func (p *context) index(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
return b.Load(p.advance(b, args))
}
// func advance(ptr *T, offset int) *T
func (p *context) advance(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
if len(args) == 2 {
ptr := p.compileValue(b, args[0])
@@ -489,6 +497,8 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
ret = cstr(b, call.Args)
case llgoAdvance:
ret = p.advance(b, call.Args)
case llgoIndex:
ret = p.index(b, call.Args)
case llgoAlloca:
ret = p.alloca(b, call.Args)
case llgoAllocaCStr:

View File

@@ -28,11 +28,9 @@ func testCompile(t *testing.T, src, expected string) {
cltest.TestCompileEx(t, src, "foo.go", expected)
}
/*
func TestFromTestlibc(t *testing.T) {
cltest.FromDir(t, "argv", "./_testlibc", false)
cltest.FromDir(t, "", "./_testlibc", false)
}
*/
func TestFromTestrt(t *testing.T) {
cltest.FromDir(t, "", "./_testrt", true)

View File

@@ -213,6 +213,7 @@ const (
llgoAlloca = llgoInstrBase + 2
llgoAllocaCStr = llgoInstrBase + 3
llgoAdvance = llgoInstrBase + 4
llgoIndex = llgoInstrBase + 5
)
func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, string, int) {

View File

@@ -496,12 +496,20 @@ func (b Builder) Phi(t Type) Phi {
// -----------------------------------------------------------------------------
// Advance returns the pointer ptr advanced by offset bytes.
// Advance returns the pointer ptr advanced by offset.
func (b Builder) Advance(ptr Expr, offset Expr) Expr {
if debugInstr {
log.Printf("Advance %v, %v\n", ptr.impl, offset.impl)
}
ret := llvm.CreateGEP(b.impl, b.Prog.tyInt8(), ptr.impl, []llvm.Value{offset.impl})
var elem llvm.Type
var prog = b.Prog
var telem = ptr.raw.Type.(*types.Pointer).Elem()
if telem == types.Typ[types.Invalid] { // void
elem = prog.tyInt8()
} else {
elem = prog.rawType(telem).ll
}
ret := llvm.CreateGEP(b.impl, elem, ptr.impl, []llvm.Value{offset.impl})
return Expr{ret, ptr.Type}
}