diff --git a/cl/_testgo/closure2/in.go b/cl/_testgo/closure2/in.go new file mode 100644 index 000000000..33f0683b3 --- /dev/null +++ b/cl/_testgo/closure2/in.go @@ -0,0 +1,11 @@ +package main + +func main() { + x := 1 + f := func(i int) func(int) { + return func(i int) { + println("closure", i, x) + } + } + f(1)(2) +} diff --git a/cl/_testgo/closure2/out.ll b/cl/_testgo/closure2/out.ll new file mode 100644 index 000000000..9878e0f50 --- /dev/null +++ b/cl/_testgo/closure2/out.ll @@ -0,0 +1,96 @@ +; ModuleID = 'main' +source_filename = "main" + +%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } + +@"main.init$guard" = global i1 false, align 1 +@__llgo_argc = global i32 0, align 4 +@__llgo_argv = global ptr null, align 8 +@0 = private unnamed_addr constant [7 x i8] c"closure", 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 i32 @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() + %2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8) + store i64 1, ptr %2, align 4 + %3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8) + %4 = getelementptr inbounds { ptr }, ptr %3, i32 0, i32 0 + store ptr %2, ptr %4, align 8 + %5 = alloca { ptr, ptr }, align 8 + %6 = getelementptr inbounds { ptr, ptr }, ptr %5, i32 0, i32 0 + store ptr @"main.main$1", ptr %6, align 8 + %7 = getelementptr inbounds { ptr, ptr }, ptr %5, i32 0, i32 1 + store ptr %3, ptr %7, align 8 + %8 = load { ptr, ptr }, ptr %5, align 8 + %9 = extractvalue { ptr, ptr } %8, 1 + %10 = extractvalue { ptr, ptr } %8, 0 + %11 = call { ptr, ptr } %10(ptr %9, i64 1) + %12 = extractvalue { ptr, ptr } %11, 1 + %13 = extractvalue { ptr, ptr } %11, 0 + call void %13(ptr %12, i64 2) + ret i32 0 +} + +define { ptr, ptr } @"main.main$1"(ptr %0, i64 %1) { +_llgo_0: + %2 = load { ptr }, ptr %0, align 8 + %3 = extractvalue { ptr } %2, 0 + %4 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8) + %5 = getelementptr inbounds { ptr }, ptr %4, i32 0, i32 0 + store ptr %3, ptr %5, align 8 + %6 = alloca { ptr, ptr }, align 8 + %7 = getelementptr inbounds { ptr, ptr }, ptr %6, i32 0, i32 0 + store ptr @"main.main$1$1", ptr %7, align 8 + %8 = getelementptr inbounds { ptr, ptr }, ptr %6, i32 0, i32 1 + store ptr %4, ptr %8, align 8 + %9 = load { ptr, ptr }, ptr %6, align 8 + ret { ptr, ptr } %9 +} + +define void @"main.main$1$1"(ptr %0, i64 %1) { +_llgo_0: + %2 = load { ptr }, ptr %0, align 8 + %3 = extractvalue { ptr } %2, 0 + %4 = load i64, ptr %3, align 4 + %5 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %5, i32 0, i32 0 + store ptr @0, ptr %6, align 8 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %5, i32 0, i32 1 + store i64 7, ptr %7, align 4 + %8 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %5, align 8 + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %8) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %1) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %4) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + ret void +} + +declare void @"github.com/goplus/llgo/internal/runtime.init"() + +declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) + +declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String") + +declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64) diff --git a/cl/_testgo/defer6/in.go b/cl/_testgo/defer6/in.go new file mode 100644 index 000000000..252aa45e5 --- /dev/null +++ b/cl/_testgo/defer6/in.go @@ -0,0 +1,11 @@ +package main + +/* +#include +*/ +import "C" + +func main() { + p := C.malloc(1024) + defer C.free(p) +} diff --git a/cl/_testgo/defer6/out.ll b/cl/_testgo/defer6/out.ll new file mode 100644 index 000000000..47163382c --- /dev/null +++ b/cl/_testgo/defer6/out.ll @@ -0,0 +1,204 @@ +; ModuleID = 'main' +source_filename = "main" + +%"github.com/goplus/llgo/internal/runtime.Defer" = type { ptr, i64, ptr, ptr, ptr } +%"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr } +%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } + +@"github.com/goplus/llgo/internal/runtime.cgoAlwaysFalse" = external global i1, align 1 +@_cgo_cba5d90e7ea4_Cfunc__Cmalloc = external global i8, align 1 +@_cgo_cba5d90e7ea4_Cfunc_free = external global i8, align 1 +@main._cgo_cba5d90e7ea4_Cfunc__Cmalloc = global ptr null, align 8 +@main._cgo_cba5d90e7ea4_Cfunc_free = global ptr null, align 8 +@"main.init$guard" = global i1 false, align 1 +@__llgo_argc = global i32 0, align 4 +@__llgo_argv = global ptr null, align 8 +@__llgo_defer = linkonce global i32 0, align 4 +@_llgo_Pointer = linkonce global ptr null, align 8 + +define [0 x i8] @main._Cfunc_free(ptr %0) { +_llgo_0: + %1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8) + %2 = load ptr, ptr @main._cgo_cba5d90e7ea4_Cfunc_free, align 8 + %3 = load ptr, ptr %2, align 8 + %4 = call [0 x i8] %3(ptr %0) + ret [0 x i8] %4 +} + +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 + call void @syscall.init() + call void @"main.init$after"() + store ptr @_cgo_cba5d90e7ea4_Cfunc_free, ptr @main._cgo_cba5d90e7ea4_Cfunc_free, align 8 + store ptr @_cgo_cba5d90e7ea4_Cfunc__Cmalloc, ptr @main._cgo_cba5d90e7ea4_Cfunc__Cmalloc, align 8 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +define i32 @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() + %2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8) + %3 = call ptr @malloc(i64 1024) + store ptr %3, ptr %2, align 8 + %4 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8) + %5 = getelementptr inbounds { ptr }, ptr %4, i32 0, i32 0 + store ptr %2, ptr %5, align 8 + %6 = alloca { ptr, ptr }, align 8 + %7 = getelementptr inbounds { ptr, ptr }, ptr %6, i32 0, i32 0 + store ptr @"main.main$1", ptr %7, align 8 + %8 = getelementptr inbounds { ptr, ptr }, ptr %6, i32 0, i32 1 + store ptr %4, ptr %8, align 8 + %9 = load { ptr, ptr }, ptr %6, align 8 + %10 = extractvalue { ptr, ptr } %9, 1 + %11 = extractvalue { ptr, ptr } %9, 0 + %12 = call { ptr, ptr } %11(ptr %10) + %13 = load i32, ptr @__llgo_defer, align 4 + %14 = call ptr @pthread_getspecific(i32 %13) + %15 = alloca i8, i64 196, align 1 + %16 = alloca i8, i64 40, align 1 + %17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %16, i32 0, i32 0 + store ptr %15, ptr %17, align 8 + %18 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %16, i32 0, i32 1 + store i64 0, ptr %18, align 4 + %19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %16, i32 0, i32 2 + store ptr %14, ptr %19, align 8 + %20 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %16, i32 0, i32 3 + store ptr blockaddress(@main, %_llgo_2), ptr %20, align 8 + %21 = call i32 @pthread_setspecific(i32 %13, ptr %16) + %22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %16, i32 0, i32 1 + %23 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %16, i32 0, i32 3 + %24 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %16, i32 0, i32 4 + %25 = call i32 @sigsetjmp(ptr %15, i32 0) + %26 = icmp eq i32 %25, 0 + br i1 %26, label %_llgo_4, label %_llgo_5 + +_llgo_1: ; preds = %_llgo_3 + ret i32 0 + +_llgo_2: ; preds = %_llgo_5, %_llgo_4 + store ptr blockaddress(@main, %_llgo_3), ptr %23, align 8 + %27 = load i64, ptr %22, align 4 + %28 = extractvalue { ptr, ptr } %12, 1 + %29 = extractvalue { ptr, ptr } %12, 0 + call void %29(ptr %28) + %30 = load %"github.com/goplus/llgo/internal/runtime.Defer", ptr %16, align 8 + %31 = extractvalue %"github.com/goplus/llgo/internal/runtime.Defer" %30, 2 + %32 = call i32 @pthread_setspecific(i32 %13, ptr %31) + %33 = load ptr, ptr %24, align 8 + indirectbr ptr %33, [label %_llgo_3, label %_llgo_6] + +_llgo_3: ; preds = %_llgo_5, %_llgo_2 + call void @"github.com/goplus/llgo/internal/runtime.Rethrow"(ptr %14) + br label %_llgo_1 + +_llgo_4: ; preds = %_llgo_0 + store ptr blockaddress(@main, %_llgo_6), ptr %24, align 8 + br label %_llgo_2 + +_llgo_5: ; preds = %_llgo_0 + store ptr blockaddress(@main, %_llgo_3), ptr %24, align 8 + %34 = load ptr, ptr %23, align 8 + indirectbr ptr %34, [label %_llgo_3, label %_llgo_2] + +_llgo_6: ; preds = %_llgo_2 + ret i32 0 +} + +define { ptr, ptr } @"main.main$1"(ptr %0) { +_llgo_0: + %1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8) + %2 = load { ptr }, ptr %0, align 8 + %3 = extractvalue { ptr } %2, 0 + %4 = load ptr, ptr %3, align 8 + store ptr %4, ptr %1, align 8 + %5 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8) + %6 = getelementptr inbounds { ptr }, ptr %5, i32 0, i32 0 + store ptr %1, ptr %6, align 8 + %7 = alloca { ptr, ptr }, align 8 + %8 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 0 + store ptr @"main.main$1$1", ptr %8, align 8 + %9 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 1 + store ptr %5, ptr %9, align 8 + %10 = load { ptr, ptr }, ptr %7, align 8 + ret { ptr, ptr } %10 +} + +define void @"main.main$1$1"(ptr %0) { +_llgo_0: + %1 = load { ptr }, ptr %0, align 8 + %2 = extractvalue { ptr } %1, 0 + %3 = load ptr, ptr %2, align 8 + %4 = load ptr, ptr @_llgo_Pointer, align 8 + %5 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8 + %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %5, i32 0, i32 0 + store ptr %4, ptr %6, align 8 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %5, i32 0, i32 1 + store ptr %3, ptr %7, align 8 + %8 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %5, align 8 + %9 = extractvalue { ptr } %1, 0 + %10 = load ptr, ptr %9, align 8 + %11 = call [0 x i8] @main._Cfunc_free(ptr %10) + ret void +} + +declare void @runtime.throw(%"github.com/goplus/llgo/internal/runtime.String") + +declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) + +declare void @syscall.init() + +declare void @"github.com/goplus/llgo/internal/runtime.init"() + +declare ptr @malloc(i64) + +declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64) + +declare ptr @pthread_getspecific(i32) + +declare i32 @pthread_setspecific(i32, ptr) + +declare i32 @sigsetjmp(ptr, i32) + +declare void @"github.com/goplus/llgo/internal/runtime.Rethrow"(ptr) + +define void @"main.init$after"() { +_llgo_0: + %0 = load ptr, ptr @_llgo_Pointer, align 8 + %1 = icmp eq ptr %0, null + br i1 %1, label %_llgo_1, label %_llgo_2 + +_llgo_1: ; preds = %_llgo_0 + %2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 58) + call void @"github.com/goplus/llgo/internal/runtime.SetDirectIface"(ptr %2) + store ptr %2, ptr @_llgo_Pointer, align 8 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + %3 = load i32, ptr @__llgo_defer, align 4 + %4 = icmp eq i32 %3, 0 + br i1 %4, label %_llgo_3, label %_llgo_4 + +_llgo_3: ; preds = %_llgo_2 + %5 = call i32 @pthread_key_create(ptr @__llgo_defer, ptr null) + br label %_llgo_4 + +_llgo_4: ; preds = %_llgo_3, %_llgo_2 + ret void +} + +declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) + +declare void @"github.com/goplus/llgo/internal/runtime.SetDirectIface"(ptr) + +declare i32 @pthread_key_create(ptr, ptr) diff --git a/ssa/type_cvt.go b/ssa/type_cvt.go index cfefe2273..df54d0b8f 100644 --- a/ssa/type_cvt.go +++ b/ssa/type_cvt.go @@ -92,6 +92,9 @@ func (p goTypes) cvtType(typ types.Type) (raw types.Type, cvt bool) { return types.NewMap(key, elem), true } case *types.Struct: + if isClosure(t) { + return typ, false + } return p.cvtStruct(t) case *types.Named: if v, ok := p.typbg.Load(namedLinkname(t)); ok && v.(Background) == InC {