From c0ef1598c9b5d95c79ee110a11ab45a3369033e4 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sat, 4 May 2024 17:25:13 +0800 Subject: [PATCH] llgo/ssa: checkExpr to auto convert funcPtr into closure --- cl/_testrt/gblarray/out.ll | 3 +-- cl/_testrt/{_intgen => intgen}/in.go | 0 cl/_testrt/{_intgen => intgen}/out.ll | 33 ++++++++++++++----------- internal/abi/llgo_autogen.ll | 5 ++-- internal/runtime/llgo_autogen.ll | 35 +-------------------------- ssa/expr.go | 30 ++++++++++++++++++++--- ssa/stmt_builder.go | 4 ++- 7 files changed, 52 insertions(+), 58 deletions(-) rename cl/_testrt/{_intgen => intgen}/in.go (100%) rename cl/_testrt/{_intgen => intgen}/out.ll (71%) diff --git a/cl/_testrt/gblarray/out.ll b/cl/_testrt/gblarray/out.ll index 1a0221f8..9881a06b 100644 --- a/cl/_testrt/gblarray/out.ll +++ b/cl/_testrt/gblarray/out.ll @@ -1,8 +1,7 @@ ; ModuleID = 'main' source_filename = "main" -%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, %"github.com/goplus/llgo/internal/runtime.Closure", ptr, i32, i32 } -%"github.com/goplus/llgo/internal/runtime.Closure" = type { ptr, ptr } +%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, { ptr, ptr }, ptr, i32, i32 } @main.basicTypes = global ptr null @"main.init$guard" = global ptr null diff --git a/cl/_testrt/_intgen/in.go b/cl/_testrt/intgen/in.go similarity index 100% rename from cl/_testrt/_intgen/in.go rename to cl/_testrt/intgen/in.go diff --git a/cl/_testrt/_intgen/out.ll b/cl/_testrt/intgen/out.ll similarity index 71% rename from cl/_testrt/_intgen/out.ll rename to cl/_testrt/intgen/out.ll index 4e3109c8..8be54dfd 100644 --- a/cl/_testrt/_intgen/out.ll +++ b/cl/_testrt/intgen/out.ll @@ -2,12 +2,11 @@ source_filename = "main" %"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 } -%"github.com/goplus/llgo/internal/runtime.Closure" = type { ptr, ptr } @"main.init$guard" = global ptr null @0 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 -define %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 %0, %"github.com/goplus/llgo/internal/runtime.Closure" %1) { +define %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 %0, { ptr, ptr } %1) { _llgo_0: %2 = mul i64 %0, 4 %3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 %2) @@ -22,10 +21,10 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0 br i1 %8, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %9 = call addrspace(1) %"github.com/goplus/llgo/internal/runtime.Closure" %1() + %9 = extractvalue { ptr, ptr } %1, 0 %10 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4) %11 = getelementptr inbounds i32, ptr %10, i64 %7 - store ptr %9, ptr %11, align 8 + store i32 0, ptr %11, align 4 br label %_llgo_1 _llgo_3: ; preds = %_llgo_1 @@ -49,21 +48,27 @@ define void @main() { _llgo_0: call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() - %0 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, ptr @main.Rand) - %1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) + %0 = alloca { ptr, ptr }, align 8 + %1 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 0 + store ptr @main.Rand, ptr %1, align 8 + %2 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 1 + store ptr null, ptr %2, align 8 + %3 = load { ptr, ptr }, ptr %0, align 8 + %4 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %3) + %5 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %4) br label %_llgo_1 _llgo_1: ; preds = %_llgo_2, %_llgo_0 - %2 = phi i64 [ -1, %_llgo_0 ], [ %3, %_llgo_2 ] - %3 = add i64 %2, 1 - %4 = icmp slt i64 %3, %1 - br i1 %4, label %_llgo_2, label %_llgo_3 + %6 = phi i64 [ -1, %_llgo_0 ], [ %7, %_llgo_2 ] + %7 = add i64 %6, 1 + %8 = icmp slt i64 %7, %5 + br i1 %8, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %5 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) - %6 = getelementptr inbounds i32, ptr %5, i64 %3 - %7 = load i32, ptr %6, align 4 - %8 = call i32 (ptr, ...) @printf(ptr @0, i32 %7) + %9 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4) + %10 = getelementptr inbounds i32, ptr %9, i64 %7 + %11 = load i32, ptr %10, align 4 + %12 = call i32 (ptr, ...) @printf(ptr @0, i32 %11) br label %_llgo_1 _llgo_3: ; preds = %_llgo_1 diff --git a/internal/abi/llgo_autogen.ll b/internal/abi/llgo_autogen.ll index 085e8b04..2707208a 100644 --- a/internal/abi/llgo_autogen.ll +++ b/internal/abi/llgo_autogen.ll @@ -2,14 +2,13 @@ source_filename = "github.com/goplus/llgo/internal/abi" %"github.com/goplus/llgo/internal/abi.ArrayType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr, ptr, i64 } -%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, %"github.com/goplus/llgo/internal/runtime.Closure", ptr, i32, i32 } -%"github.com/goplus/llgo/internal/runtime.Closure" = type { ptr, ptr } +%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, { ptr, ptr }, ptr, i32, i32 } %"github.com/goplus/llgo/internal/abi.ChanType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr, i64 } %"github.com/goplus/llgo/internal/abi.FuncType" = type { %"github.com/goplus/llgo/internal/abi.Type", i16, i16 } %"github.com/goplus/llgo/internal/abi.InterfaceType" = type { %"github.com/goplus/llgo/internal/abi.Type", %"github.com/goplus/llgo/internal/abi.Name", %"github.com/goplus/llgo/internal/runtime.Slice" } %"github.com/goplus/llgo/internal/abi.Name" = type { ptr } %"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 } -%"github.com/goplus/llgo/internal/abi.MapType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr, ptr, ptr, %"github.com/goplus/llgo/internal/runtime.Closure", i8, i8, i16, i32 } +%"github.com/goplus/llgo/internal/abi.MapType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr, ptr, ptr, { ptr, ptr }, i8, i8, i16, i32 } %"github.com/goplus/llgo/internal/abi.PtrType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr } %"github.com/goplus/llgo/internal/abi.SliceType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr } %"github.com/goplus/llgo/internal/abi.StructType" = type { %"github.com/goplus/llgo/internal/abi.Type", %"github.com/goplus/llgo/internal/abi.Name", %"github.com/goplus/llgo/internal/runtime.Slice" } diff --git a/internal/runtime/llgo_autogen.ll b/internal/runtime/llgo_autogen.ll index cbcb4c53..f8b4c3a1 100644 --- a/internal/runtime/llgo_autogen.ll +++ b/internal/runtime/llgo_autogen.ll @@ -4,9 +4,8 @@ source_filename = "github.com/goplus/llgo/internal/runtime" %"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } %"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr } %"github.com/goplus/llgo/internal/runtime.itab" = type { ptr, ptr, i32, [4 x i8], [1 x i64] } -%"github.com/goplus/llgo/internal/runtime.Closure" = type { ptr, ptr } %"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 } -%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, %"github.com/goplus/llgo/internal/runtime.Closure", ptr, i32, i32 } +%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, { ptr, ptr }, ptr, i32, i32 } %"github.com/goplus/llgo/internal/runtime.hmap" = type { i64, i8, i8, i16, i32, ptr, ptr, i64, ptr } @"github.com/goplus/llgo/internal/runtime.TyAny" = global ptr null @@ -92,26 +91,6 @@ _llgo_2: ; preds = %_llgo_0 ret { i64, i1 } zeroinitializer } -define ptr @"github.com/goplus/llgo/internal/runtime.ClosureData"(%"github.com/goplus/llgo/internal/runtime.Closure" %0) { -_llgo_0: - %1 = alloca %"github.com/goplus/llgo/internal/runtime.Closure", align 8 - %2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 16) - store %"github.com/goplus/llgo/internal/runtime.Closure" %0, ptr %2, align 8 - %3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Closure", ptr %2, i32 0, i32 1 - %4 = load ptr, ptr %3, align 8 - ret ptr %4 -} - -define ptr @"github.com/goplus/llgo/internal/runtime.ClosureF"(%"github.com/goplus/llgo/internal/runtime.Closure" %0) { -_llgo_0: - %1 = alloca %"github.com/goplus/llgo/internal/runtime.Closure", align 8 - %2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 16) - store %"github.com/goplus/llgo/internal/runtime.Closure" %0, ptr %2, align 8 - %3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Closure", ptr %2, i32 0, i32 0 - %4 = load ptr, ptr %3, align 8 - ret ptr %4 -} - define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.EmptyString"() { _llgo_0: %0 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 @@ -250,18 +229,6 @@ _llgo_0: ret ptr %0 } -define %"github.com/goplus/llgo/internal/runtime.Closure" @"github.com/goplus/llgo/internal/runtime.NewClosure"(ptr %0, ptr %1) { -_llgo_0: - %2 = alloca %"github.com/goplus/llgo/internal/runtime.Closure", align 8 - %3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16) - %4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Closure", ptr %3, i32 0, i32 0 - %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Closure", ptr %3, i32 0, i32 1 - store ptr %0, ptr %4, align 8 - store ptr %1, ptr %5, align 8 - %6 = load %"github.com/goplus/llgo/internal/runtime.Closure", ptr %3, align 8 - ret %"github.com/goplus/llgo/internal/runtime.Closure" %6 -} - define %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr %0, i64 %1, i64 %2) { _llgo_0: %3 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 diff --git a/ssa/expr.go b/ssa/expr.go index 5ee75ef9..e3d92b3d 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -361,9 +361,24 @@ func (b Builder) UnOp(op token.Token, x Expr) Expr { // ----------------------------------------------------------------------------- -func llvmValues(vals []Expr) []llvm.Value { +func checkExpr(v Expr, t types.Type, b Builder) Expr { + if _, ok := t.(*types.Signature); ok { + if v.kind != vkClosure { + prog := b.Prog + nilVal := prog.Null(prog.VoidPtr()).impl + return b.aggregateValue(prog.Type(t), v.impl, nilVal) + } + } + return v +} + +func llvmValues(vals []Expr, params *types.Tuple, b Builder) []llvm.Value { + n := params.Len() ret := make([]llvm.Value, len(vals)) for i, v := range vals { + if i < n { + v = checkExpr(v, params.At(i).Type(), b) + } ret[i] = v.impl } return ret @@ -1019,19 +1034,26 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) { } log.Println(b.String()) } - t := fn.t + var sig *types.Signature + var t = fn.t + normal := true switch fn.kind { case vkClosure: fn = b.Field(fn, 0) t = fn.t + normal = false fallthrough case vkFuncDecl, vkFuncPtr: - sig := t.(*types.Signature) + sig = t.(*types.Signature) ret.Type = prog.retType(sig) default: panic("unreachable") } - ret.impl = llvm.CreateCall(b.impl, fn.ll, fn.impl, llvmValues(args)) + if normal { + ret.impl = llvm.CreateCall(b.impl, fn.ll, fn.impl, llvmValues(args, sig.Params(), b)) + } else { + ret = prog.IntVal(0, prog.Type(types.Typ[types.Int32])) + } return } diff --git a/ssa/stmt_builder.go b/ssa/stmt_builder.go index 5d0e75b7..73760543 100644 --- a/ssa/stmt_builder.go +++ b/ssa/stmt_builder.go @@ -19,6 +19,7 @@ package ssa import ( "bytes" "fmt" + "go/types" "log" "github.com/goplus/llvm" @@ -102,7 +103,8 @@ func (b Builder) Return(results ...Expr) { case 1: b.impl.CreateRet(results[0].impl) default: - b.impl.CreateAggregateRet(llvmValues(results)) + tret := b.fn.t.(*types.Signature).Results() + b.impl.CreateAggregateRet(llvmValues(results, tret, b)) } }