diff --git a/cl/_testdata/print/out.ll b/cl/_testdata/print/out.ll index 9f89186a..8fbc290b 100644 --- a/cl/_testdata/print/out.ll +++ b/cl/_testdata/print/out.ll @@ -85,7 +85,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_0 store i1 true, ptr @"main.init$guard", align 1 - call void @"main.init$abi"() + call void @"main.init$after"() store i64 0, ptr @main.minhexdigits, align 4 br label %_llgo_2 @@ -1412,7 +1412,7 @@ declare i32 @printf(ptr, ...) declare void @"github.com/goplus/llgo/internal/runtime.init"() -define void @"main.init$abi"() { +define void @"main.init$after"() { _llgo_0: %0 = load ptr, ptr @_llgo_float32, align 8 %1 = icmp eq ptr %0, null diff --git a/cl/_testdata/vargs/out.ll b/cl/_testdata/vargs/out.ll index a687457b..2dcb1327 100644 --- a/cl/_testdata/vargs/out.ll +++ b/cl/_testdata/vargs/out.ll @@ -19,7 +19,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_0 store i1 true, ptr @"main.init$guard", align 1 - call void @"main.init$abi"() + call void @"main.init$after"() br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -118,7 +118,7 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"() declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) -define void @"main.init$abi"() { +define void @"main.init$after"() { _llgo_0: %0 = load ptr, ptr @_llgo_int, align 8 %1 = icmp eq ptr %0, null diff --git a/cl/_testgo/defer/out.ll b/cl/_testgo/defer/out.ll index b37f04be..6ef57dab 100644 --- a/cl/_testgo/defer/out.ll +++ b/cl/_testgo/defer/out.ll @@ -3,7 +3,7 @@ source_filename = "main" %"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } %"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr } -%"github.com/goplus/llgo/internal/runtime.Defer" = type { { ptr, ptr }, i64, ptr } +%"github.com/goplus/llgo/internal/runtime.Defer" = type { { ptr, ptr }, i64, ptr, i64 } @"main.init$guard" = global ptr null @0 = private unnamed_addr constant [6 x i8] c"error\00", align 1 @@ -67,75 +67,119 @@ _llgo_0: call void @main.init() %2 = load ptr, ptr @__llgo_defer, align 8 %3 = call ptr @pthread_getspecific(ptr %2) - %4 = alloca i8, i64 32, align 1 + %4 = alloca i8, i64 40, align 1 %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 0 - store ptr @"main$_llgo_defer", ptr %5, align 8 + store ptr null, ptr %5, align 8 %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1 store i64 0, ptr %6, align 4 %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 2 store ptr %3, ptr %7, align 8 %8 = call i32 @pthread_setspecific(ptr %2, ptr %4) %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1 - %10 = load i64, ptr %9, align 4 - %11 = or i64 %10, 1 - store i64 %11, ptr %9, align 4 - %12 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %12, i32 0, i32 0 - store ptr @1, ptr %13, align 8 - %14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %12, i32 0, i32 1 - store i64 5, ptr %14, align 4 - %15 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %12, align 8 - %16 = call i1 @main.f(%"github.com/goplus/llgo/internal/runtime.String" %15) - br i1 %16, label %_llgo_2, label %_llgo_4 + %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 3 + %11 = load i64, ptr %9, align 4 + %12 = or i64 %11, 1 + store i64 %12, ptr %9, align 4 + %13 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %13, i32 0, i32 0 + store ptr @1, ptr %14, align 8 + %15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %13, i32 0, i32 1 + store i64 5, ptr %15, align 4 + %16 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %13, align 8 + %17 = call i1 @main.f(%"github.com/goplus/llgo/internal/runtime.String" %16) + br i1 %17, label %_llgo_2, label %_llgo_4 _llgo_1: ; No predecessors! ret i32 0 _llgo_2: ; preds = %_llgo_0 - %17 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %18 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %17, i32 0, i32 0 - store ptr @2, ptr %18, align 8 - %19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %17, i32 0, i32 1 - store i64 5, ptr %19, align 4 - %20 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %17, align 8 - %21 = load ptr, ptr @__llgo_defer, align 8 - %22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1 - %23 = load i64, ptr %22, align 4 - %24 = or i64 %23, 2 - store i64 %24, ptr %22, align 4 + %18 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 0 + store ptr @2, ptr %19, align 8 + %20 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 1 + store i64 5, ptr %20, align 4 + %21 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %18, align 8 + %22 = load i64, ptr %9, align 4 + %23 = or i64 %22, 2 + store i64 %23, ptr %9, align 4 br label %_llgo_3 _llgo_3: ; preds = %_llgo_4, %_llgo_2 - %25 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %26 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %25, i32 0, i32 0 - store ptr @3, ptr %26, align 8 - %27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %25, i32 0, i32 1 - store i64 3, ptr %27, align 4 - %28 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %25, align 8 - %29 = load ptr, ptr @__llgo_defer, align 8 - %30 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1 - %31 = load i64, ptr %30, align 4 - %32 = or i64 %31, 4 - store i64 %32, ptr %30, align 4 - %33 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1 - %34 = load i64, ptr %33, align 4 - call void @"main$_llgo_defer"(i64 %34) - ret i32 0 + %24 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %25 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 0 + store ptr @3, ptr %25, align 8 + %26 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 1 + store i64 3, ptr %26, align 4 + %27 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %24, align 8 + %28 = load i64, ptr %9, align 4 + %29 = or i64 %28, 4 + store i64 %29, ptr %9, align 4 + store i64 0, ptr %10, align 4 + br label %_llgo_5 _llgo_4: ; preds = %_llgo_0 - %35 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %36 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 0 - store ptr @4, ptr %36, align 8 - %37 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 1 - store i64 5, ptr %37, align 4 - %38 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %35, align 8 - %39 = load ptr, ptr @__llgo_defer, align 8 - %40 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1 - %41 = load i64, ptr %40, align 4 - %42 = or i64 %41, 8 - store i64 %42, ptr %40, align 4 + %30 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %31 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %30, i32 0, i32 0 + store ptr @4, ptr %31, align 8 + %32 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %30, i32 0, i32 1 + store i64 5, ptr %32, align 4 + %33 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %30, align 8 + %34 = load i64, ptr %9, align 4 + %35 = or i64 %34, 8 + store i64 %35, ptr %9, align 4 call void @main.fail() br label %_llgo_3 + +_llgo_5: ; preds = %_llgo_3 + %36 = load i64, ptr %9, align 4 + %37 = and i64 %36, 8 + %38 = icmp ne i64 %37, 0 + br i1 %38, label %_llgo_7, label %_llgo_8 + +_llgo_6: ; preds = %_llgo_14 + ret i32 0 + +_llgo_7: ; preds = %_llgo_5 + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %33) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + br label %_llgo_8 + +_llgo_8: ; preds = %_llgo_7, %_llgo_5 + %39 = and i64 %36, 4 + %40 = icmp ne i64 %39, 0 + br i1 %40, label %_llgo_9, label %_llgo_10 + +_llgo_9: ; preds = %_llgo_8 + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %27) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + br label %_llgo_10 + +_llgo_10: ; preds = %_llgo_9, %_llgo_8 + %41 = and i64 %36, 2 + %42 = icmp ne i64 %41, 0 + br i1 %42, label %_llgo_11, label %_llgo_12 + +_llgo_11: ; preds = %_llgo_10 + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %21) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + br label %_llgo_12 + +_llgo_12: ; preds = %_llgo_11, %_llgo_10 + %43 = and i64 %36, 1 + %44 = icmp ne i64 %43, 0 + br i1 %44, label %_llgo_13, label %_llgo_14 + +_llgo_13: ; preds = %_llgo_12 + call void @"main.main$1"() + br label %_llgo_14 + +_llgo_14: ; preds = %_llgo_13, %_llgo_12 + %45 = load %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, align 8 + %46 = extractvalue %"github.com/goplus/llgo/internal/runtime.Defer" %45, 2 + %47 = call i32 @pthread_setspecific(ptr %2, ptr %46) + %48 = load i64, ptr %10, align 4 + switch i64 %48, label %_llgo_6 [ + ] } define void @"main.init$after"() { @@ -183,50 +227,6 @@ _llgo_0: ret void } -define void @"main$_llgo_defer"(i64 %0) { -_llgo_0: - %1 = and i64 %0, 1 - %2 = icmp ne i64 %1, 0 - br i1 %2, label %_llgo_1, label %_llgo_2 - -_llgo_1: ; preds = %_llgo_0 - call void @"main.main$1"() - br label %_llgo_2 - -_llgo_2: ; preds = %_llgo_1, %_llgo_0 - %3 = and i64 %0, 2 - %4 = icmp ne i64 %3, 0 - br i1 %4, label %_llgo_3, label %_llgo_4 - -_llgo_3: ; preds = %_llgo_2 - call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %20) - call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) - br label %_llgo_4 - -_llgo_4: ; preds = %_llgo_3, %_llgo_2 - %5 = and i64 %0, 4 - %6 = icmp ne i64 %5, 0 - br i1 %6, label %_llgo_5, label %_llgo_6 - -_llgo_5: ; preds = %_llgo_4 - call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %28) - call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) - br label %_llgo_6 - -_llgo_6: ; preds = %_llgo_5, %_llgo_4 - %7 = and i64 %0, 8 - %8 = icmp ne i64 %7, 0 - br i1 %8, label %_llgo_7, label %_llgo_8 - -_llgo_7: ; preds = %_llgo_6 - call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %38) - call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) - br label %_llgo_8 - -_llgo_8: ; preds = %_llgo_7, %_llgo_6 - ret void -} - declare ptr @pthread_getspecific(i32) declare i32 @pthread_setspecific(i32, ptr) diff --git a/cl/_testgo/errors/out.ll b/cl/_testgo/errors/out.ll index 599cc745..56719002 100644 --- a/cl/_testgo/errors/out.ll +++ b/cl/_testgo/errors/out.ll @@ -60,7 +60,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_0 store i1 true, ptr @"main.init$guard", align 1 - call void @"main.init$abi"() + call void @"main.init$after"() br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -102,7 +102,7 @@ _llgo_0: declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) -define void @"main.init$abi"() { +define void @"main.init$after"() { _llgo_0: %0 = call ptr @"github.com/goplus/llgo/internal/runtime.NewNamed"(i64 25, i64 0, i64 1) store ptr %0, ptr @_llgo_main.errorString, align 8 diff --git a/cl/_testgo/strucintf/out.ll b/cl/_testgo/strucintf/out.ll index f23f046d..57632d34 100644 --- a/cl/_testgo/strucintf/out.ll +++ b/cl/_testgo/strucintf/out.ll @@ -49,7 +49,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_0 store i1 true, ptr @"main.init$guard", align 1 call void @"github.com/goplus/llgo/cl/internal/foo.init"() - call void @"main.init$abi"() + call void @"main.init$after"() br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -241,7 +241,7 @@ _llgo_18: ; preds = %_llgo_17, %_llgo_16 declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64) -define void @"main.init$abi"() { +define void @"main.init$after"() { _llgo_0: %0 = load ptr, ptr @_llgo_int, align 8 %1 = icmp eq ptr %0, null diff --git a/cl/_testgo/struczero/out.ll b/cl/_testgo/struczero/out.ll index 2bd65e65..48894dd4 100644 --- a/cl/_testgo/struczero/out.ll +++ b/cl/_testgo/struczero/out.ll @@ -117,7 +117,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_0 store i1 true, ptr @"main.init$guard", align 1 call void @"github.com/goplus/llgo/cl/internal/foo.init"() - call void @"main.init$abi"() + call void @"main.init$after"() br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -185,7 +185,7 @@ _llgo_0: ret i32 0 } -define void @"main.init$abi"() { +define void @"main.init$after"() { _llgo_0: %0 = load ptr, ptr @"_llgo_github.com/goplus/llgo/cl/internal/foo.Foo", align 8 %1 = icmp eq ptr %0, null diff --git a/cl/_testrt/any/out.ll b/cl/_testrt/any/out.ll index d2f59f3f..83e277c1 100644 --- a/cl/_testrt/any/out.ll +++ b/cl/_testrt/any/out.ll @@ -68,7 +68,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_0 store i1 true, ptr @"main.init$guard", align 1 - call void @"main.init$abi"() + call void @"main.init$after"() br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -101,7 +101,7 @@ _llgo_0: ret i32 0 } -define void @"main.init$abi"() { +define void @"main.init$after"() { _llgo_0: %0 = load ptr, ptr @_llgo_int8, align 8 %1 = icmp eq ptr %0, null diff --git a/cl/_testrt/builtin/out.ll b/cl/_testrt/builtin/out.ll index 8045b41c..ffd5bc49 100644 --- a/cl/_testrt/builtin/out.ll +++ b/cl/_testrt/builtin/out.ll @@ -86,7 +86,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_0 store i1 true, ptr @"main.init$guard", align 1 - call void @"main.init$abi"() + call void @"main.init$after"() store i64 9223372036854775807, ptr @main.a, align 4 store i64 -9223372036854775808, ptr @main.b, align 4 store i64 -1, ptr @main.n, align 4 @@ -643,7 +643,7 @@ declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.SliceAppend"(%"github.com/goplus/llgo/internal/runtime.Slice", ptr, i64, i64) -define void @"main.init$abi"() { +define void @"main.init$after"() { _llgo_0: %0 = load ptr, ptr @_llgo_int, align 8 %1 = icmp eq ptr %0, null diff --git a/cl/_testrt/cast/out.ll b/cl/_testrt/cast/out.ll index 1f6b0f30..5225b11c 100644 --- a/cl/_testrt/cast/out.ll +++ b/cl/_testrt/cast/out.ll @@ -401,7 +401,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_0 store i1 true, ptr @"main.init$guard", align 1 - call void @"main.init$abi"() + call void @"main.init$after"() br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -472,7 +472,7 @@ _llgo_0: ret i32 0 } -define void @"main.init$abi"() { +define void @"main.init$after"() { _llgo_0: %0 = load ptr, ptr @_llgo_string, align 8 %1 = icmp eq ptr %0, null diff --git a/cl/_testrt/eface/out.ll b/cl/_testrt/eface/out.ll index af51095f..c809135b 100644 --- a/cl/_testrt/eface/out.ll +++ b/cl/_testrt/eface/out.ll @@ -199,7 +199,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_0 store i1 true, ptr @"main.init$guard", align 1 call void @"github.com/goplus/llgo/internal/abi.init"() - call void @"main.init$abi"() + call void @"main.init$after"() br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -436,7 +436,7 @@ declare void @"github.com/goplus/llgo/internal/abi.init"() declare void @"github.com/goplus/llgo/internal/runtime.init"() -define void @"main.init$abi"() { +define void @"main.init$after"() { _llgo_0: %0 = load ptr, ptr @_llgo_bool, align 8 %1 = icmp eq ptr %0, null diff --git a/cl/_testrt/panic/out.ll b/cl/_testrt/panic/out.ll index 4bac3016..ce254403 100644 --- a/cl/_testrt/panic/out.ll +++ b/cl/_testrt/panic/out.ll @@ -17,7 +17,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_0 store i1 true, ptr @"main.init$guard", align 1 - call void @"main.init$abi"() + call void @"main.init$after"() br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -51,7 +51,7 @@ _llgo_0: declare void @"github.com/goplus/llgo/internal/runtime.init"() -define void @"main.init$abi"() { +define void @"main.init$after"() { _llgo_0: %0 = load ptr, ptr @_llgo_string, align 8 %1 = icmp eq ptr %0, null diff --git a/internal/abi/llgo_autogen.lla b/internal/abi/llgo_autogen.lla index 747da4e5..eb0833a5 100644 Binary files a/internal/abi/llgo_autogen.lla and b/internal/abi/llgo_autogen.lla differ diff --git a/internal/runtime/llgo_autogen.lla b/internal/runtime/llgo_autogen.lla index 6574534d..cfd6dabb 100644 Binary files a/internal/runtime/llgo_autogen.lla and b/internal/runtime/llgo_autogen.lla differ diff --git a/internal/runtime/z_defer.go b/internal/runtime/z_defer.go index 7f59abb4..007d4888 100644 --- a/internal/runtime/z_defer.go +++ b/internal/runtime/z_defer.go @@ -21,6 +21,7 @@ type Defer struct { proc func(uintptr) bits uintptr link *Defer + rund int // index of RunDefers } // DeferProc calls deferred statements. @@ -28,5 +29,6 @@ func DeferProc(d *Defer) { for d != nil { d.proc(d.bits) d = d.link + _ = d.rund } } diff --git a/ssa/decl.go b/ssa/decl.go index 4dc2badf..8abe0339 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -22,7 +22,6 @@ import ( "sort" "strconv" "strings" - "unsafe" "github.com/goplus/llvm" ) @@ -181,16 +180,12 @@ type aFunction struct { blks []BasicBlock + defer_ *aDefer + params []Type freeVars Expr base int // base = 1 if hasFreeVars; base = 0 otherwise - - deferNextBit int // next defer bit - deferData Expr - deferParam Expr - deferb unsafe.Pointer - - hasVArg bool + hasVArg bool } // Function represents a function or method. diff --git a/ssa/package.go b/ssa/package.go index 4cb779a3..98e471b6 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -179,7 +179,7 @@ type aProgram struct { setSpecTy *types.Signature routineTy *types.Signature destructTy *types.Signature - deferFnTy *types.Signature + //deferFnTy *types.Signature paramObjPtr_ *types.Var diff --git a/ssa/stmt_builder.go b/ssa/stmt_builder.go index 9f92efea..17449b86 100644 --- a/ssa/stmt_builder.go +++ b/ssa/stmt_builder.go @@ -23,7 +23,6 @@ import ( "go/types" "log" "strings" - "unsafe" "github.com/goplus/llvm" ) @@ -65,7 +64,7 @@ type Builder = *aBuilder // EndBuild ends the build process of a function. func (b Builder) EndBuild() { - b.endDeferFunc() + b.Func.endDefer(b) } // Dispose disposes of the builder. @@ -141,6 +140,18 @@ const ( deferKey = "__llgo_defer" ) +type aDefer struct { + nextBit int // next defer bit + key Expr // pthread TLS key + data Expr // pointer to runtime.Defer + bitsPtr Expr // pointer to defer bits + rundPtr Expr // pointer to RunDefers index + procBlk BasicBlock // deferProc block + stmts []func(bits Expr) + runsNext []BasicBlock // next blocks of RunDefers +} + +/* // func(uintptr) func (p Program) tyDeferFunc() *types.Signature { if p.deferFnTy == nil { @@ -150,6 +161,7 @@ func (p Program) tyDeferFunc() *types.Signature { } return p.deferFnTy } +*/ func (p Package) deferInit(b Builder) { keyVar := p.VarOf(deferKey) @@ -175,23 +187,31 @@ func (b Builder) deferKey() Expr { return b.Load(b.Pkg.newDeferKey().Expr) } -// DeferFuncName returns the name of the defer procedure. -func (p Function) DeferFuncName() string { - return p.Name() + "$_llgo_defer" -} - -// DeferFunc returns the defer procedure of this function. -func (p Function) DeferFunc() Function { - name := p.DeferFuncName() - return p.Pkg.NewFunc(name, p.Prog.tyDeferFunc(), InC) -} - -func (b Builder) endDeferFunc() { +func (b Builder) getDefer() *aDefer { self := b.Func - if self.deferb != nil { - b = Builder(self.deferb) - b.Return() + if self.defer_ == nil { + // TODO(xsw): move to funtion start + // 0: proc func(uintptr) + // 1: bits uintptr + // 2: link *Defer + // 3: rund int + prog := b.Prog + key := b.deferKey() + deferfn := prog.Null(prog.VoidPtr()) + zero := prog.Val(uintptr(0)) + link := b.pthreadGetspecific(key) + ptr := b.aggregateAlloca(prog.Defer(), deferfn.impl, zero.impl, link.impl) + deferData := Expr{ptr, prog.DeferPtr()} + b.pthreadSetspecific(key, deferData) + self.defer_ = &aDefer{ + key: key, + data: deferData, + bitsPtr: b.FieldAddr(deferData, 1), + rundPtr: b.FieldAddr(deferData, 3), + procBlk: self.MakeBlock(), + } } + return self.defer_ } // Defer emits a defer instruction. @@ -200,43 +220,62 @@ func (b Builder) Defer(fn Expr, args ...Expr) { logCall("Defer", fn, args) } prog := b.Prog - self := b.Func - next := self.deferNextBit - self.deferNextBit++ - zero := prog.Val(uintptr(0)) - key := b.deferKey() - if next == 0 { - deferfn := self.DeferFunc() - deferb := deferfn.MakeBody(1) - self.deferb = unsafe.Pointer(deferb) - self.deferParam = deferfn.Param(0) - - // TODO(xsw): move to funtion start - // proc func(uintptr) - // bits uintptr - // link *Defer - link := b.pthreadGetspecific(key) - ptr := b.aggregateAlloca(prog.Defer(), deferfn.impl, zero.impl, link.impl) - self.deferData = Expr{ptr, prog.DeferPtr()} - b.pthreadSetspecific(key, self.deferData) - } - bitsPtr := b.FieldAddr(self.deferData, 1) + self := b.getDefer() + next := self.nextBit + self.nextBit++ + bits := b.Load(self.bitsPtr) nextbit := prog.Val(uintptr(1 << next)) - b.Store(bitsPtr, b.BinOp(token.OR, b.Load(bitsPtr), nextbit)) + b.Store(self.bitsPtr, b.BinOp(token.OR, bits, nextbit)) - b = Builder(self.deferb) - has := b.BinOp(token.NEQ, b.BinOp(token.AND, self.deferParam, nextbit), zero) - b.IfThen(has, func() { - b.Call(fn, args...) + self.stmts = append(self.stmts, func(bits Expr) { + zero := prog.Val(uintptr(0)) + has := b.BinOp(token.NEQ, b.BinOp(token.AND, bits, nextbit), zero) + b.IfThen(has, func() { + b.Call(fn, args...) + }) }) } // RunDefers emits instructions to run deferred instructions. func (b Builder) RunDefers() { - self := b.Func - deferfn := self.DeferFunc() - bitsPtr := b.FieldAddr(self.deferData, 1) - b.Call(deferfn.Expr, b.Load(bitsPtr)) + prog := b.Prog + self := b.getDefer() + b.Store(self.rundPtr, prog.Val(len(self.runsNext))) + b.Jump(self.procBlk) + + blk := b.Func.MakeBlock() + self.runsNext = append(self.runsNext, blk) + + b.SetBlockEx(blk, AtEnd, false) + b.blk.last = blk.last +} + +func (p Function) endDefer(b Builder) { + self := p.defer_ + if self == nil { + return + } + nexts := self.runsNext + n := len(nexts) + if n == 0 { + return + } + b.SetBlockEx(self.procBlk, AtEnd, true) + bits := b.Load(self.bitsPtr) + stmts := self.stmts + for i := len(stmts) - 1; i >= 0; i-- { + stmts[i](bits) + } + + link := b.getField(b.Load(self.data), 2) + b.pthreadSetspecific(self.key, link) + + prog := b.Prog + rund := b.Load(self.rundPtr) + sw := b.impl.CreateSwitch(rund.impl, nexts[0].first, n-1) + for i := 1; i < n; i++ { + sw.AddCase(prog.Val(i).impl, nexts[i].first) + } } // -----------------------------------------------------------------------------