From 5a5d86ccc389cfe4c88c6fe3dacf86d1eb80540b Mon Sep 17 00:00:00 2001 From: xushiwei Date: Tue, 7 May 2024 16:05:18 +0800 Subject: [PATCH] cl: instr llgo.index/advance --- c/c.go | 2 +- cl/_testlibc/argv/in.go | 11 +++++++++ cl/_testlibc/argv/out.ll | 50 ++++++++++++++++++++++++++++++++++++++++ cl/compile.go | 10 ++++++++ cl/compile_test.go | 4 +--- cl/import.go | 1 + ssa/expr.go | 12 ++++++++-- 7 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 cl/_testlibc/argv/in.go create mode 100644 cl/_testlibc/argv/out.ll diff --git a/c/c.go b/c/c.go index b10248ac..1a1aea8a 100644 --- a/c/c.go +++ b/c/c.go @@ -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 } diff --git a/cl/_testlibc/argv/in.go b/cl/_testlibc/argv/in.go new file mode 100644 index 00000000..b4055521 --- /dev/null +++ b/cl/_testlibc/argv/in.go @@ -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)) + } +} diff --git a/cl/_testlibc/argv/out.ll b/cl/_testlibc/argv/out.ll new file mode 100644 index 00000000..9253ebe4 --- /dev/null +++ b/cl/_testlibc/argv/out.ll @@ -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, ...) diff --git a/cl/compile.go b/cl/compile.go index e3c37be3..24179d6d 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -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(): 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: diff --git a/cl/compile_test.go b/cl/compile_test.go index f64b60c6..2d8861cc 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -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) diff --git a/cl/import.go b/cl/import.go index 9635cca7..da103c03 100644 --- a/cl/import.go +++ b/cl/import.go @@ -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) { diff --git a/ssa/expr.go b/ssa/expr.go index a8e4a0a4..b4df26c1 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -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} }