diff --git a/cl/_testgo/cgodefer/cgodefer.go b/cl/_testgo/cgodefer/cgodefer.go index 5ce8dd6bfe..6925b641c8 100644 --- a/cl/_testgo/cgodefer/cgodefer.go +++ b/cl/_testgo/cgodefer/cgodefer.go @@ -6,6 +6,11 @@ package main */ import "C" +func main() { + p := C.malloc(1024) + defer C.free(p) +} + // CHECK-LABEL: define [0 x i8] @main._Cfunc_free(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) @@ -15,6 +20,27 @@ import "C" // CHECK-NEXT: ret [0 x i8] %4 // CHECK-NEXT: } +// CHECK-LABEL: define ptr @main._Cgo_ptr(ptr %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: ret ptr %0 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @main.init(){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 +// CHECK-NEXT: br i1 %0, label %_llgo_2, label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 +// CHECK-NEXT: call void @syscall.init() +// CHECK-NEXT: store ptr @_cgo_{{.*}}_Cfunc_free, ptr @main._cgo_{{.*}}_Cfunc_free, align 8 +// CHECK-NEXT: store ptr @_cgo_{{.*}}_Cfunc__Cmalloc, ptr @main._cgo_{{.*}}_Cfunc__Cmalloc, align 8 +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: ret void +// CHECK-NEXT: } + // CHECK-LABEL: define void @main.main(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) @@ -45,7 +71,7 @@ import "C" // CHECK-NEXT: %17 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 4 // CHECK-NEXT: %18 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, i32 0, i32 5 // CHECK-NEXT: store ptr null, ptr %18, align 8 -// CHECK-NEXT: %19 = call i32 @{{.*}}sigsetjmp(ptr %9, i32 0) +// CHECK-NEXT: %19 = call i32 @{{(__)?}}sigsetjmp(ptr %9, i32 0) // CHECK-NEXT: %20 = icmp eq i32 %19, 0 // CHECK-NEXT: br i1 %20, label %_llgo_4, label %_llgo_5 // CHECK-EMPTY: @@ -91,44 +117,45 @@ import "C" // CHECK-NEXT: store ptr %32, ptr %18, align 8 // CHECK-NEXT: %33 = extractvalue { ptr, i64, { ptr, ptr } } %31, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %30) -// CHECK-NEXT: %34 = extractvalue { ptr, ptr } %33, 1 -// CHECK-NEXT: %35 = extractvalue { ptr, ptr } %33, 0 -// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %35) -// CHECK-NEXT: call void %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %34) +// CHECK-NEXT: %34 = extractvalue { ptr, ptr } %33, 0 +// CHECK-NEXT: %35 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr %34) +// CHECK-NEXT: %36 = extractvalue { ptr, ptr } %33, 1 +// CHECK-NEXT: %37 = extractvalue { ptr, ptr } %33, 0 +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %37) +// CHECK-NEXT: call void %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %36) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %35) // CHECK-NEXT: br label %_llgo_8 // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 -// CHECK-NEXT: %36 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, align 8 -// CHECK-NEXT: %37 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %36, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %37) -// CHECK-NEXT: %38 = load ptr, ptr %17, align 8 -// CHECK-NEXT: indirectbr ptr %38, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: %38 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %10, align 8 +// CHECK-NEXT: %39 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %38, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %39) +// CHECK-NEXT: %40 = load ptr, ptr %17, align 8 +// CHECK-NEXT: indirectbr ptr %40, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: } + +// CHECK-LABEL: define { ptr, ptr } @"main.main$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) +// CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %3 = extractvalue { ptr } %2, 0 +// CHECK-NEXT: %4 = load ptr, ptr %3, align 8 +// CHECK-NEXT: store ptr %4, ptr %1, align 8 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %6 = getelementptr inbounds { ptr }, ptr %5, i32 0, i32 0 +// CHECK-NEXT: store ptr %1, ptr %6, align 8 +// CHECK-NEXT: %7 = insertvalue { ptr, ptr } { ptr @"main.main$1$1", ptr undef }, ptr %5, 1 +// CHECK-NEXT: ret { ptr, ptr } %7 +// CHECK-NEXT: } + +// CHECK-LABEL: define void @"main.main$1$1"(ptr {{(nest|swiftself)}} %0){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 +// CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_Pointer, ptr undef }, ptr %3, 1 +// CHECK-NEXT: %5 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call [0 x i8] @main._Cfunc_free(ptr %6) +// CHECK-NEXT: ret void // CHECK-NEXT: } -func main() { - // CHECK-LABEL: define { ptr, ptr } @"main.main$1"(ptr {{(nest|swiftself)}} %0){{.*}} { - // CHECK-NEXT: _llgo_0: - // CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) - // CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 - // CHECK-NEXT: %3 = extractvalue { ptr } %2, 0 - // CHECK-NEXT: %4 = load ptr, ptr %3, align 8 - // CHECK-NEXT: store ptr %4, ptr %1, align 8 - // CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) - // CHECK-NEXT: %6 = getelementptr inbounds { ptr }, ptr %5, i32 0, i32 0 - // CHECK-NEXT: store ptr %1, ptr %6, align 8 - // CHECK-NEXT: %7 = insertvalue { ptr, ptr } { ptr @"main.main$1$1", ptr undef }, ptr %5, 1 - // CHECK-NEXT: ret { ptr, ptr } %7 - // CHECK-NEXT: } - p := C.malloc(1024) - // CHECK-LABEL: define void @"main.main$1$1"(ptr {{(nest|swiftself)}} %0){{.*}} { - // CHECK-NEXT: _llgo_0: - // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 - // CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 - // CHECK-NEXT: %3 = load ptr, ptr %2, align 8 - // CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_Pointer, ptr undef }, ptr %3, 1 - // CHECK-NEXT: %5 = extractvalue { ptr } %1, 0 - // CHECK-NEXT: %6 = load ptr, ptr %5, align 8 - // CHECK-NEXT: %7 = call [0 x i8] @main._Cfunc_free(ptr %6) - // CHECK-NEXT: ret void - // CHECK-NEXT: } - defer C.free(p) -} diff --git a/cl/_testgo/closureall/in.go b/cl/_testgo/closureall/in.go index 5d7e0ed0d9..10e445f318 100644 --- a/cl/_testgo/closureall/in.go +++ b/cl/_testgo/closureall/in.go @@ -5,10 +5,10 @@ import _ "unsafe" // for go:linkname import "github.com/goplus/lib/c" -// CHECK: @0 = private unnamed_addr constant [46 x i8] c"{{.*}}/cl/_testgo/closureall.S", align 1 -// CHECK: @1 = private unnamed_addr constant [3 x i8] c"Inc", align 1 -// CHECK: @7 = private unnamed_addr constant [3 x i8] c"Add", align 1 -// CHECK: @9 = private unnamed_addr constant [23 x i8] c"interface{Add(int) int}", align 1 +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [46 x i8] c"{{.*}}/cl/_testgo/closureall.S", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"Inc", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"Add", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [23 x i8] c"interface{Add(int) int}", align 1{{$}} //go:linkname cSqrt C.sqrt func cSqrt(x c.Double) c.Double @@ -30,29 +30,10 @@ type S struct { v int } -// CHECK-LABEL: define i64 @main.S.Inc(%main.S %0, i64 %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = alloca %main.S, align 8 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %2, i8 0, i64 8, i1 false) -// CHECK-NEXT: store %main.S %0, ptr %2, align 8 -// CHECK-NEXT: %3 = getelementptr inbounds %main.S, ptr %2, i32 0, i32 0 -// CHECK-NEXT: %4 = load i64, ptr %3, align 8 -// CHECK-NEXT: %5 = add i64 %4, %1 -// CHECK-NEXT: ret i64 %5 -// CHECK-NEXT: } - func (s S) Inc(x int) int { return s.v + x } -// CHECK-LABEL: define i64 @"main.(*S).Add"(ptr %0, i64 %1){{.*}} { -// CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds %main.S, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %3 = load i64, ptr %2, align 8 -// CHECK-NEXT: %4 = add i64 %3, %1 -// CHECK-NEXT: ret i64 %4 -// CHECK-NEXT: } - func (s *S) Add(x int) int { return s.v + x } @@ -100,10 +81,29 @@ func makeWithFree(base int) Fn { return func(x int) int { return x + base } } +// CHECK-LABEL: define i64 @main.S.Inc(%main.S %0, i64 %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %2 = alloca %main.S, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %2, i8 0, i64 8, i1 false) +// CHECK-NEXT: store %main.S %0, ptr %2, align 8 +// CHECK-NEXT: %3 = getelementptr inbounds %main.S, ptr %2, i32 0, i32 0 +// CHECK-NEXT: %4 = load i64, ptr %3, align 8 +// CHECK-NEXT: %5 = add i64 %4, %1 +// CHECK-NEXT: ret i64 %5 +// CHECK-NEXT: } + +// CHECK-LABEL: define i64 @"main.(*S).Add"(ptr %0, i64 %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: %2 = getelementptr inbounds %main.S, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %3 = load i64, ptr %2, align 8 +// CHECK-NEXT: %4 = add i64 %3, %1 +// CHECK-NEXT: ret i64 %4 +// CHECK-NEXT: } + // CHECK-LABEL: define i64 @"main.(*S).Inc"(ptr %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = icmp eq ptr %0, null -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %2, %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 46 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @1, i64 3 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %2, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 46 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: %3 = load %main.S, ptr %0, align 8 // CHECK-NEXT: %4 = call i64 @main.S.Inc(%main.S %3, i64 %1) // CHECK-NEXT: ret i64 %4 @@ -184,13 +184,13 @@ func makeWithFree(base int) Fn { // CHECK-NEXT: %27 = extractvalue { ptr, ptr } %25, 0 // CHECK-NEXT: %__llgo_funcval_code3 = call ptr asm "", "=r,0"(ptr %27) // CHECK-NEXT: %28 = call i64 %__llgo_funcval_code3(ptr {{(nest|swiftself)}} %26, i64 9) -// CHECK-NEXT: %29 = call double @sqrt(double 4.000000e+00) +// CHECK-NEXT: %29 = call double @{{(sqrt|main.cSqrt)}}(double 4.000000e+00) // CHECK-NEXT: %30 = call i32 @main.callCInt({ ptr, ptr } { ptr @abs, ptr null }, i32 -3) // CHECK-NEXT: %31 = call i32 @main.callCallback(ptr @"main.main$1", i32 7) // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %21, %"{{.*}}/runtime/internal/runtime.String" { ptr @9, i64 23 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @7, i64 3 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %21, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 23 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: unreachable // CHECK-NEXT: } @@ -258,8 +258,11 @@ func makeWithFree(base int) Fn { // CHECK-NEXT: %7 = load ptr, ptr %6, align 8 // CHECK-NEXT: %8 = insertvalue { ptr, ptr } undef, ptr %7, 0 // CHECK-NEXT: %9 = insertvalue { ptr, ptr } %8, ptr %4, 1 -// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %9, 1 -// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %9, 0 -// CHECK-NEXT: %12 = call i64 %11(ptr %10, i64 %1) -// CHECK-NEXT: ret i64 %12 +// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %9, 0 +// CHECK-NEXT: %11 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @"main.interface{Add(int) int}.Add$bound", ptr %10) +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %9, 1 +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %9, 0 +// CHECK-NEXT: %14 = call i64 %13(ptr %12, i64 %1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %11) +// CHECK-NEXT: ret i64 %14 // CHECK-NEXT: } diff --git a/cl/_testgo/closureenv/in.go b/cl/_testgo/closureenv/in.go index b83578930d..0ab147b9ad 100644 --- a/cl/_testgo/closureenv/in.go +++ b/cl/_testgo/closureenv/in.go @@ -1,14 +1,14 @@ // LITTEST package main -// CHECK: {{^}}@0 = private unnamed_addr constant [18 x i8] c"zero-sized capture", align 1{{$}} -// CHECK: {{^}}@2 = private unnamed_addr constant [26 x i8] c"zero-sized capture address", align 1{{$}} -// CHECK: {{^}}@3 = private unnamed_addr constant [26 x i8] c"zero-sized pointer capture", align 1{{$}} -// CHECK: {{^}}@6 = private unnamed_addr constant [5 x i8] c"IsNil", align 1{{$}} -// CHECK: {{^}}@10 = private unnamed_addr constant [23 x i8] c"interface{IsNil() bool}", align 1{{$}} -// CHECK: {{^}}@11 = private unnamed_addr constant [25 x i8] c"nil receiver method value", align 1{{$}} -// CHECK: {{^}}@12 = private unnamed_addr constant [2 x i8] c"ok", align 1{{$}} -// CHECK: {{^}}@13 = private unnamed_addr constant [32 x i8] c"typed-nil interface method value", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [18 x i8] c"zero-sized capture", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [26 x i8] c"zero-sized capture address", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [26 x i8] c"zero-sized pointer capture", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"IsNil", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [23 x i8] c"interface{IsNil() bool}", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [25 x i8] c"nil receiver method value", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [2 x i8] c"ok", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [32 x i8] c"typed-nil interface method value", align 1{{$}} type nilReceiver struct{} @@ -86,7 +86,7 @@ func main() { // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 // CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 18 }, ptr %5, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 18 }, ptr %5, align 8 // CHECK-NEXT: %6 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %5, 1 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %6) // CHECK-NEXT: unreachable @@ -104,7 +104,7 @@ func main() { // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 // CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 26 }, ptr %14, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 26 }, ptr %14, align 8 // CHECK-NEXT: %15 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %14, 1 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %15) // CHECK-NEXT: unreachable @@ -119,7 +119,7 @@ func main() { // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_4 // CHECK-NEXT: %20 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @3, i64 26 }, ptr %20, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 26 }, ptr %20, align 8 // CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %20, 1 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %21) // CHECK-NEXT: unreachable @@ -137,13 +137,13 @@ func main() { // CHECK-EMPTY: // CHECK-NEXT: _llgo_7: ; preds = %_llgo_6 // CHECK-NEXT: %28 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @11, i64 25 }, ptr %28, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 25 }, ptr %28, align 8 // CHECK-NEXT: %29 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %28, 1 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %29) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_6 -// CHECK-NEXT: %30 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$36psrSzSiKQuwmDQNUwPgWt23w6DHhlw0KM1_Hu7IbY", ptr @"*_llgo_main.nilReceiver") +// CHECK-NEXT: %30 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface${{[-A-Za-z0-9_]+}}", ptr @"*_llgo_main.nilReceiver") // CHECK-NEXT: %31 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %30, 0 // CHECK-NEXT: %32 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %31, ptr null, 1 // CHECK-NEXT: %33 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %32) @@ -152,13 +152,13 @@ func main() { // CHECK-EMPTY: // CHECK-NEXT: _llgo_9: ; preds = %_llgo_11 // CHECK-NEXT: %35 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @13, i64 32 }, ptr %35, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 32 }, ptr %35, align 8 // CHECK-NEXT: %36 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %35, 1 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %36) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_10: ; preds = %_llgo_11 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @12, i64 2 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 2 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void // CHECK-EMPTY: @@ -174,7 +174,7 @@ func main() { // CHECK-NEXT: br i1 %42, label %_llgo_10, label %_llgo_9 // CHECK-EMPTY: // CHECK-NEXT: _llgo_12: ; preds = %_llgo_8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %33, %"{{.*}}/runtime/internal/runtime.String" { ptr @10, i64 23 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @6, i64 5 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %33, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 23 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) // CHECK-NEXT: unreachable // CHECK-NEXT: } @@ -248,8 +248,11 @@ func main() { // CHECK-NEXT: %6 = load ptr, ptr %5, align 8 // CHECK-NEXT: %7 = insertvalue { ptr, ptr } undef, ptr %6, 0 // CHECK-NEXT: %8 = insertvalue { ptr, ptr } %7, ptr %3, 1 -// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %8, 1 -// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %8, 0 -// CHECK-NEXT: %11 = call i1 %10(ptr %9) -// CHECK-NEXT: ret i1 %11 +// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @"main.interface{IsNil() bool}.IsNil$bound", ptr %9) +// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %8, 1 +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %13 = call i1 %12(ptr %11) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %10) +// CHECK-NEXT: ret i1 %13 // CHECK-NEXT: } diff --git a/cl/_testgo/defer4/in.go b/cl/_testgo/defer4/in.go index 583580903e..c9dbafee92 100644 --- a/cl/_testgo/defer4/in.go +++ b/cl/_testgo/defer4/in.go @@ -48,7 +48,7 @@ func main() { // CHECK-LABEL: define void @main.fail(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -74,7 +74,9 @@ func main() { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5 // CHECK-NEXT: store ptr blockaddress(@main.fail, %_llgo_6), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.fail$1") // CHECK-NEXT: call void @"main.fail$1"() +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) // CHECK-NEXT: br label %_llgo_6 // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_8 @@ -82,78 +84,80 @@ func main() { // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: %14 = load ptr, ptr %10, align 8 -// CHECK-NEXT: %15 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) -// CHECK-NEXT: %16 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %15, i32 0, i32 0 -// CHECK-NEXT: store ptr %14, ptr %16, align 8 -// CHECK-NEXT: %17 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %15, i32 0, i32 1 -// CHECK-NEXT: store i64 0, ptr %17, align 8 -// CHECK-NEXT: %18 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %15, i32 0, i32 2 -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %18, align 8 -// CHECK-NEXT: store ptr %15, ptr %10, align 8 -// CHECK-NEXT: %19 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %19, align 8 -// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %19, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %20) +// CHECK-NEXT: %15 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %16 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %17 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %16, i32 0, i32 0 +// CHECK-NEXT: store ptr %15, ptr %17, align 8 +// CHECK-NEXT: %18 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %16, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %18, align 8 +// CHECK-NEXT: %19 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %16, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }, ptr %19, align 8 +// CHECK-NEXT: store ptr %16, ptr %10, align 8 +// CHECK-NEXT: %20 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %20, align 8 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %20, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %21) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@main.fail, %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %21 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %21, [label %_llgo_3, label %_llgo_6, label %_llgo_2] +// CHECK-NEXT: %22 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %22, [label %_llgo_3, label %_llgo_6, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: store ptr blockaddress(@main.fail, %_llgo_3), ptr %8, align 8 -// CHECK-NEXT: %22 = load i64, ptr %7, align 8 -// CHECK-NEXT: %23 = load ptr, ptr %10, align 8 -// CHECK-NEXT: %24 = icmp ne ptr %23, null -// CHECK-NEXT: br i1 %24, label %_llgo_7, label %_llgo_8 +// CHECK-NEXT: %23 = load i64, ptr %7, align 8 +// CHECK-NEXT: %24 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %25 = icmp ne ptr %24, null +// CHECK-NEXT: br i1 %25, label %_llgo_7, label %_llgo_8 // CHECK-EMPTY: // CHECK-NEXT: _llgo_7: ; preds = %_llgo_6 -// CHECK-NEXT: %25 = load ptr, ptr %10, align 8 -// CHECK-NEXT: %26 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %25, align 8 -// CHECK-NEXT: %27 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %26, 0 -// CHECK-NEXT: store ptr %27, ptr %10, align 8 -// CHECK-NEXT: %28 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %26, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %25) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %28) +// CHECK-NEXT: %26 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %27 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" }, ptr %26, align 8 +// CHECK-NEXT: %28 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %27, 0 +// CHECK-NEXT: store ptr %28, ptr %10, align 8 +// CHECK-NEXT: %29 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.String" } %27, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %26) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %29) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: br label %_llgo_8 // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_6 -// CHECK-NEXT: %29 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %30 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %29, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %30) -// CHECK-NEXT: %31 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %31, [label %_llgo_3] +// CHECK-NEXT: %30 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %31 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %30, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %31) +// CHECK-NEXT: %32 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %32, [label %_llgo_3] // CHECK-NEXT: } // CHECK-LABEL: define void @"main.fail$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: %2 = xor i1 %1, true -// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.fail$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: %3 = xor i1 %2, true +// CHECK-NEXT: br i1 %3, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %3 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %0, 0 -// CHECK-NEXT: %4 = icmp eq ptr %3, @_llgo_string -// CHECK-NEXT: br i1 %4, label %_llgo_3, label %_llgo_4 +// CHECK-NEXT: %4 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %1, 0 +// CHECK-NEXT: %5 = icmp eq ptr %4, @_llgo_string +// CHECK-NEXT: br i1 %5, label %_llgo_3, label %_llgo_4 // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_3, %_llgo_0 // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_1 -// CHECK-NEXT: %5 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %0, 1 -// CHECK-NEXT: %6 = load %"{{.*}}/runtime/internal/runtime.String", ptr %5, align 8 +// CHECK-NEXT: %6 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %1, 1 +// CHECK-NEXT: %7 = load %"{{.*}}/runtime/internal/runtime.String", ptr %6, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %6) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %7) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %3, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }, %"{{.*}}/runtime/internal/runtime.String" zeroinitializer) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %4, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 6 }, %"{{.*}}/runtime/internal/runtime.String" zeroinitializer) // CHECK-NEXT: unreachable // CHECK-NEXT: } @@ -173,7 +177,7 @@ func main() { // CHECK-LABEL: define void @main.main(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 diff --git a/cl/_testgo/deferclosure/in.go b/cl/_testgo/deferclosure/in.go index ecd61152a3..7c87545949 100644 --- a/cl/_testgo/deferclosure/in.go +++ b/cl/_testgo/deferclosure/in.go @@ -133,7 +133,7 @@ func main() { // CHECK-NEXT: store ptr %0, ptr %2, align 8 // CHECK-NEXT: %3 = insertvalue { ptr, ptr } { ptr @"main.testDeferClosureValue$1", ptr undef }, ptr %1, 1 // CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %5 = alloca i8 +// CHECK-NEXT: %5 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 0 // CHECK-NEXT: store ptr %5, ptr %7, align 8 @@ -227,12 +227,13 @@ func main() { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = alloca %main.FuncHolder, align 8 // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %0, i8 0, i64 16, i1 false) +// CHECK-NEXT: store volatile %main.FuncHolder zeroinitializer, ptr %0, align 8 // CHECK-NEXT: %1 = getelementptr inbounds %main.FuncHolder, ptr %0, i32 0, i32 0 -// CHECK-NEXT: store { ptr, ptr } { ptr @"main.testDeferFieldAccess$1", ptr null }, ptr %1, align 8 +// CHECK-NEXT: store volatile { ptr, ptr } { ptr @"main.testDeferFieldAccess$1", ptr null }, ptr %1, align 8 // CHECK-NEXT: %2 = getelementptr inbounds %main.FuncHolder, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %3 = load { ptr, ptr }, ptr %2, align 8 +// CHECK-NEXT: %3 = load volatile { ptr, ptr }, ptr %2, align 8 // CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %5 = alloca i8 +// CHECK-NEXT: %5 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 0 // CHECK-NEXT: store ptr %5, ptr %7, align 8 @@ -296,18 +297,21 @@ func main() { // CHECK-NEXT: store ptr %28, ptr %14, align 8 // CHECK-NEXT: %29 = extractvalue { ptr, i64, { ptr, ptr } } %27, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %26) -// CHECK-NEXT: %30 = extractvalue { ptr, ptr } %29, 1 -// CHECK-NEXT: %31 = extractvalue { ptr, ptr } %29, 0 -// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %31) -// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %30) +// CHECK-NEXT: %30 = extractvalue { ptr, ptr } %29, 0 +// CHECK-NEXT: %31 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr %30) +// CHECK-NEXT: %32 = extractvalue { ptr, ptr } %29, 1 +// CHECK-NEXT: %33 = extractvalue { ptr, ptr } %29, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %33) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %31) // CHECK-NEXT: br label %_llgo_8 // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 -// CHECK-NEXT: %32 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, align 8 -// CHECK-NEXT: %33 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %32, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %33) -// CHECK-NEXT: %34 = load ptr, ptr %13, align 8 -// CHECK-NEXT: indirectbr ptr %34, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: %34 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, align 8 +// CHECK-NEXT: %35 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %34, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %35) +// CHECK-NEXT: %36 = load ptr, ptr %13, align 8 +// CHECK-NEXT: indirectbr ptr %36, [label %_llgo_3, label %_llgo_6] // CHECK-NEXT: } // CHECK-LABEL: define void @"main.testDeferFieldAccess$1"(){{.*}} { @@ -322,7 +326,7 @@ func main() { // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) // CHECK-NEXT: call void @"main.(*Handler).SetHandler"(ptr %0, { ptr, ptr } { ptr @"main.testDeferMethodLiteral$1", ptr null }) // CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %2 = alloca i8 +// CHECK-NEXT: %2 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %3, i32 0, i32 0 // CHECK-NEXT: store ptr %2, ptr %4, align 8 @@ -426,7 +430,7 @@ func main() { // CHECK-NEXT: store ptr %1, ptr %3, align 8 // CHECK-NEXT: %4 = insertvalue { ptr, ptr } { ptr @"main.testDeferStructClosure$1", ptr undef }, ptr %2, 1 // CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %6 = alloca i8 +// CHECK-NEXT: %6 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %7, i32 0, i32 0 // CHECK-NEXT: store ptr %6, ptr %8, align 8 diff --git a/cl/_testgo/deferiface/in.go b/cl/_testgo/deferiface/in.go index bcee22b9ae..74d4c7e1ab 100644 --- a/cl/_testgo/deferiface/in.go +++ b/cl/_testgo/deferiface/in.go @@ -1,8 +1,8 @@ // LITTEST package main -// CHECK: {{^}}@0 = private unnamed_addr constant [5 x i8] c"reset", align 1{{$}} -// CHECK: {{^}}@8 = private unnamed_addr constant [4 x i8] c"body", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"reset", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [4 x i8] c"body", align 1{{$}} type resetter interface { Reset() @@ -42,7 +42,7 @@ func main() { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.item, ptr %0, i32 0, i32 0 // CHECK-NEXT: %2 = load i64, ptr %1, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 5 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %2) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) @@ -54,7 +54,7 @@ func main() { // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) // CHECK-NEXT: %1 = getelementptr inbounds %main.item, ptr %0, i32 0, i32 0 // CHECK-NEXT: store i64 42, ptr %1, align 8 -// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$yjH5fOWhYIH6Pv7ce-kmK-CVKIWOLvKPVzRvjwBotEM", ptr @"*_llgo_main.item") +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface${{[-A-Za-z0-9_]+}}", ptr @"*_llgo_main.item") // CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %2, 0 // CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %3, ptr %0, 1 // CHECK-NEXT: call void @main.run(%"{{.*}}/runtime/internal/runtime.iface" %4) @@ -86,7 +86,7 @@ func main() { // CHECK-NEXT: %16 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 4 // CHECK-NEXT: %17 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, i32 0, i32 5 // CHECK-NEXT: store ptr null, ptr %17, align 8 -// CHECK-NEXT: %18 = call i32 @{{.*}}sigsetjmp(ptr %8, i32 0) +// CHECK-NEXT: %18 = call i32 @{{(__)?}}sigsetjmp(ptr %8, i32 0) // CHECK-NEXT: %19 = icmp eq i32 %18, 0 // CHECK-NEXT: br i1 %19, label %_llgo_4, label %_llgo_5 // CHECK-EMPTY: @@ -114,7 +114,7 @@ func main() { // CHECK-NEXT: %27 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %24, i32 0, i32 2 // CHECK-NEXT: store { ptr, ptr } %6, ptr %27, align 8 // CHECK-NEXT: store ptr %24, ptr %17, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @8, i64 4 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 4 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: store ptr blockaddress(@main.run, %_llgo_6), ptr %16, align 8 // CHECK-NEXT: br label %_llgo_2 @@ -134,15 +134,18 @@ func main() { // CHECK-NEXT: store ptr %31, ptr %17, align 8 // CHECK-NEXT: %32 = extractvalue { ptr, i64, { ptr, ptr } } %30, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %29) -// CHECK-NEXT: %33 = extractvalue { ptr, ptr } %32, 1 -// CHECK-NEXT: %34 = extractvalue { ptr, ptr } %32, 0 -// CHECK-NEXT: call void %34(ptr %33) +// CHECK-NEXT: %33 = extractvalue { ptr, ptr } %32, 0 +// CHECK-NEXT: %34 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr %33) +// CHECK-NEXT: %35 = extractvalue { ptr, ptr } %32, 1 +// CHECK-NEXT: %36 = extractvalue { ptr, ptr } %32, 0 +// CHECK-NEXT: call void %36(ptr %35) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %34) // CHECK-NEXT: br label %_llgo_8 // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 -// CHECK-NEXT: %35 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, align 8 -// CHECK-NEXT: %36 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %35, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %36) -// CHECK-NEXT: %37 = load ptr, ptr %16, align 8 -// CHECK-NEXT: indirectbr ptr %37, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: %37 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %9, align 8 +// CHECK-NEXT: %38 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %37, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %38) +// CHECK-NEXT: %39 = load ptr, ptr %16, align 8 +// CHECK-NEXT: indirectbr ptr %39, [label %_llgo_3, label %_llgo_6] // CHECK-NEXT: } diff --git a/cl/_testgo/genericembediface/in.go b/cl/_testgo/genericembediface/in.go index be2c2122ee..95472a2c13 100644 --- a/cl/_testgo/genericembediface/in.go +++ b/cl/_testgo/genericembediface/in.go @@ -5,12 +5,12 @@ import ( "github.com/goplus/llgo/cl/_testgo/genericembediface/streamlib" ) -// CHECK: {{^}}@2 = private unnamed_addr constant [20 x i8] c"ServerReflectionInfo", align 1{{$}} -// CHECK: {{^}}@5 = private unnamed_addr constant [7 x i8] c"Context", align 1{{$}} -// CHECK: {{^}}@11 = private unnamed_addr constant [68 x i8] c"{{.*}}/cl/_testgo/genericembediface.ReflectionServer", align 1{{$}} -// CHECK: {{^}}@19 = private unnamed_addr constant [4 x i8] c"pass", align 1{{$}} -// CHECK: {{^}}@20 = private unnamed_addr constant [58 x i8] c"{{.*}}/cl/_testgo/genericembediface.server", align 1{{$}} -// CHECK: {{^}}@21 = private unnamed_addr constant [58 x i8] c"{{.*}}/cl/_testgo/genericembediface.stream", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [20 x i8] c"ServerReflectionInfo", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [7 x i8] c"Context", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [68 x i8] c"{{.*}}/cl/_testgo/genericembediface.ReflectionServer", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [4 x i8] c"pass", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [58 x i8] c"{{.*}}/cl/_testgo/genericembediface.server", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [58 x i8] c"{{.*}}/cl/_testgo/genericembediface.stream", align 1{{$}} type Request struct{} type Response struct{} @@ -19,6 +19,27 @@ type ReflectionServer interface { ServerReflectionInfo(streamlib.BidiStreamingServer[Request, Response]) error } +func handler(srv any, stream streamlib.ServerStream) error { + return srv.(ReflectionServer).ServerReflectionInfo(&streamlib.GenericServerStream[Request, Response]{ServerStream: stream}) +} + +type server struct{} + +func (server) ServerReflectionInfo(streamlib.BidiStreamingServer[Request, Response]) error { + return nil +} + +type stream struct{} + +func (stream) Context() string { + return "Context" +} + +func main() { + _ = handler(server{}, stream{}) + println("pass") +} + // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @main.handler(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.iface" %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %0, 0 @@ -48,7 +69,7 @@ type ReflectionServer interface { // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %21 // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %2, %"{{.*}}/runtime/internal/runtime.String" { ptr @11, i64 68 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 20 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %2, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 68 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 20 }) // CHECK-NEXT: unreachable // CHECK-NEXT: } @@ -66,22 +87,6 @@ type ReflectionServer interface { // CHECK-NEXT: ret void // CHECK-NEXT: } -func handler(srv any, stream streamlib.ServerStream) error { - return srv.(ReflectionServer).ServerReflectionInfo(&streamlib.GenericServerStream[Request, Response]{ServerStream: stream}) -} - -type server struct{} - -func (server) ServerReflectionInfo(streamlib.BidiStreamingServer[Request, Response]) error { - return nil -} - -type stream struct{} - -func (stream) Context() string { - return "Context" -} - // CHECK-LABEL: define void @main.main(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) @@ -93,7 +98,7 @@ func (stream) Context() string { // CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %3, 0 // CHECK-NEXT: %5 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %4, ptr %2, 1 // CHECK-NEXT: %6 = call %"{{.*}}/runtime/internal/runtime.iface" @main.handler(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.iface" %5) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @19, i64 4 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 4 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void // CHECK-NEXT: } @@ -103,15 +108,10 @@ func (stream) Context() string { // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer // CHECK-NEXT: } -func main() { - _ = handler(server{}, stream{}) - println("pass") -} - // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @"main.(*server).ServerReflectionInfo"(ptr %0, %"{{.*}}/runtime/internal/runtime.iface" %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = icmp eq ptr %0, null -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %2, %"{{.*}}/runtime/internal/runtime.String" { ptr @20, i64 58 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 20 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %2, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 58 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 20 }) // CHECK-NEXT: %3 = icmp eq ptr %0, null // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %3) // CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.iface" @main.server.ServerReflectionInfo(%main.server zeroinitializer, %"{{.*}}/runtime/internal/runtime.iface" %1) @@ -120,13 +120,13 @@ func main() { // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @main.stream.Context(%main.stream %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 7 } +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 7 } // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @"main.(*stream).Context"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = icmp eq ptr %0, null -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @21, i64 58 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 7 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 58 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 7 }) // CHECK-NEXT: %2 = icmp eq ptr %0, null // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %2) // CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.String" @main.stream.Context(%main.stream zeroinitializer) @@ -143,10 +143,13 @@ func main() { // CHECK-NEXT: %6 = load ptr, ptr %5, align 8 // CHECK-NEXT: %7 = insertvalue { ptr, ptr } undef, ptr %6, 0 // CHECK-NEXT: %8 = insertvalue { ptr, ptr } %7, ptr %3, 1 -// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %8, 1 -// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %8, 0 -// CHECK-NEXT: %11 = call %"{{.*}}/runtime/internal/runtime.String" %10(ptr %9) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %11 +// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @"{{.*}}/cl/_testgo/genericembediface/streamlib.(*GenericServerStream[main.Request,main.Response]).Context", ptr %9) +// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %8, 1 +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %13 = call %"{{.*}}/runtime/internal/runtime.String" %12(ptr %11) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %10) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %13 // CHECK-NEXT: } // CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/cl/_testgo/genericembediface/streamlib.GenericServerStream[main.Request,main.Response].Context"(%"{{.*}}/cl/_testgo/genericembediface/streamlib.GenericServerStream[main.Request,main.Response]" %0){{.*}} { @@ -162,8 +165,11 @@ func main() { // CHECK-NEXT: %7 = load ptr, ptr %6, align 8 // CHECK-NEXT: %8 = insertvalue { ptr, ptr } undef, ptr %7, 0 // CHECK-NEXT: %9 = insertvalue { ptr, ptr } %8, ptr %4, 1 -// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %9, 1 -// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %9, 0 -// CHECK-NEXT: %12 = call %"{{.*}}/runtime/internal/runtime.String" %11(ptr %10) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %12 +// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %9, 0 +// CHECK-NEXT: %11 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @"{{.*}}/cl/_testgo/genericembediface/streamlib.GenericServerStream[main.Request,main.Response].Context", ptr %10) +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %9, 1 +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %9, 0 +// CHECK-NEXT: %14 = call %"{{.*}}/runtime/internal/runtime.String" %13(ptr %12) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %11) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %14 // CHECK-NEXT: } diff --git a/cl/_testgo/goexit/in.go b/cl/_testgo/goexit/in.go index a2a9ba68fb..39ba36ad6a 100644 --- a/cl/_testgo/goexit/in.go +++ b/cl/_testgo/goexit/in.go @@ -93,7 +93,7 @@ func demo3() { // CHECK-NEXT: store ptr %2, ptr %4, align 8 // CHECK-NEXT: %5 = insertvalue { ptr, ptr } { ptr @"main.demo1$1$1", ptr undef }, ptr %3, 1 // CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %7 = alloca i8 +// CHECK-NEXT: %7 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 0 // CHECK-NEXT: store ptr %7, ptr %9, align 8 @@ -216,7 +216,7 @@ func demo3() { // CHECK-NEXT: store ptr %2, ptr %4, align 8 // CHECK-NEXT: %5 = insertvalue { ptr, ptr } { ptr @"main.demo2$1$1", ptr undef }, ptr %3, 1 // CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %7 = alloca i8 +// CHECK-NEXT: %7 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 0 // CHECK-NEXT: store ptr %7, ptr %9, align 8 @@ -279,44 +279,49 @@ func demo3() { // CHECK-NEXT: store ptr %30, ptr %16, align 8 // CHECK-NEXT: %31 = extractvalue { ptr, i64, { ptr, ptr } } %29, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %28) -// CHECK-NEXT: %32 = extractvalue { ptr, ptr } %31, 1 -// CHECK-NEXT: %33 = extractvalue { ptr, ptr } %31, 0 -// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %33) -// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %32) +// CHECK-NEXT: %32 = extractvalue { ptr, ptr } %31, 0 +// CHECK-NEXT: %33 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr %32) +// CHECK-NEXT: %34 = extractvalue { ptr, ptr } %31, 1 +// CHECK-NEXT: %35 = extractvalue { ptr, ptr } %31, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %35) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %34) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %33) // CHECK-NEXT: br label %_llgo_8 // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 -// CHECK-NEXT: %34 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, align 8 -// CHECK-NEXT: %35 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %34, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %35) -// CHECK-NEXT: %36 = load ptr, ptr %15, align 8 -// CHECK-NEXT: indirectbr ptr %36, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: %36 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, align 8 +// CHECK-NEXT: %37 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %36, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %37) +// CHECK-NEXT: %38 = load ptr, ptr %15, align 8 +// CHECK-NEXT: indirectbr ptr %38, [label %_llgo_3, label %_llgo_6] // CHECK-NEXT: } // CHECK-LABEL: define void @"main.demo2$1$1"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 -// CHECK-NEXT: %2 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %3 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %2, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: %4 = xor i1 %3, true -// CHECK-NEXT: br i1 %4, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %2 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.demo2$1$1", ptr %2) +// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %2) +// CHECK-NEXT: %4 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %3, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: %5 = xor i1 %4, true +// CHECK-NEXT: br i1 %5, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %5, align 8 -// CHECK-NEXT: %6 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %5, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %6) +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %6, align 8 +// CHECK-NEXT: %7 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %6, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %7) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %7 = extractvalue { ptr } %1, 0 -// CHECK-NEXT: %8 = load ptr, ptr %7, align 8 -// CHECK-NEXT: %9 = call ptr @llvm.stacksave.p0() -// CHECK-NEXT: %10 = alloca i1, align 1 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %10, i8 0, i64 1, i1 false) -// CHECK-NEXT: store i1 true, ptr %10, align 1 -// CHECK-NEXT: %11 = call i1 @"{{.*}}/runtime/internal/runtime.ChanSend"(ptr %8, ptr %10, i64 1) -// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %9) +// CHECK-NEXT: %8 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %9 = load ptr, ptr %8, align 8 +// CHECK-NEXT: %10 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %11 = alloca i1, align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %11, i8 0, i64 1, i1 false) +// CHECK-NEXT: store i1 true, ptr %11, align 1 +// CHECK-NEXT: %12 = call i1 @"{{.*}}/runtime/internal/runtime.ChanSend"(ptr %9, ptr %11, i64 1) +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %10) // CHECK-NEXT: ret void // CHECK-NEXT: } @@ -352,7 +357,7 @@ func demo3() { // CHECK-NEXT: store ptr %2, ptr %4, align 8 // CHECK-NEXT: %5 = insertvalue { ptr, ptr } { ptr @"main.demo3$1$1", ptr undef }, ptr %3, 1 // CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %7 = alloca i8 +// CHECK-NEXT: %7 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 0 // CHECK-NEXT: store ptr %7, ptr %9, align 8 @@ -378,7 +383,9 @@ func demo3() { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.demo3$1", %_llgo_7), ptr %14, align 8 // CHECK-NEXT: %19 = load i64, ptr %13, align 8 +// CHECK-NEXT: %20 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.demo3$1$2") // CHECK-NEXT: call void @"main.demo3$1$2"() +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %20) // CHECK-NEXT: br label %_llgo_7 // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_9 @@ -386,104 +393,111 @@ func demo3() { // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: %20 = load ptr, ptr %16, align 8 -// CHECK-NEXT: %21 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) -// CHECK-NEXT: %22 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %21, i32 0, i32 0 -// CHECK-NEXT: store ptr %20, ptr %22, align 8 -// CHECK-NEXT: %23 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %21, i32 0, i32 1 -// CHECK-NEXT: store i64 0, ptr %23, align 8 -// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %21, i32 0, i32 2 -// CHECK-NEXT: store { ptr, ptr } %5, ptr %24, align 8 -// CHECK-NEXT: store ptr %21, ptr %16, align 8 +// CHECK-NEXT: %21 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %22 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %23 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %22, i32 0, i32 0 +// CHECK-NEXT: store ptr %21, ptr %23, align 8 +// CHECK-NEXT: %24 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %22, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %24, align 8 +// CHECK-NEXT: %25 = getelementptr inbounds { ptr, i64, { ptr, ptr } }, ptr %22, i32 0, i32 2 +// CHECK-NEXT: store { ptr, ptr } %5, ptr %25, align 8 +// CHECK-NEXT: store ptr %22, ptr %16, align 8 // CHECK-NEXT: call void @runtime.Goexit() // CHECK-NEXT: store ptr blockaddress(@"main.demo3$1", %_llgo_6), ptr %15, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.demo3$1", %_llgo_3), ptr %15, align 8 -// CHECK-NEXT: %25 = load ptr, ptr %14, align 8 -// CHECK-NEXT: indirectbr ptr %25, [label %_llgo_3, label %_llgo_7, label %_llgo_2] +// CHECK-NEXT: %26 = load ptr, ptr %14, align 8 +// CHECK-NEXT: indirectbr ptr %26, [label %_llgo_3, label %_llgo_7, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_9 // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_7: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: store ptr blockaddress(@"main.demo3$1", %_llgo_3), ptr %14, align 8 -// CHECK-NEXT: %26 = load i64, ptr %13, align 8 -// CHECK-NEXT: %27 = load ptr, ptr %16, align 8 -// CHECK-NEXT: %28 = icmp ne ptr %27, null -// CHECK-NEXT: br i1 %28, label %_llgo_8, label %_llgo_9 +// CHECK-NEXT: %27 = load i64, ptr %13, align 8 +// CHECK-NEXT: %28 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %29 = icmp ne ptr %28, null +// CHECK-NEXT: br i1 %29, label %_llgo_8, label %_llgo_9 // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_7 -// CHECK-NEXT: %29 = load ptr, ptr %16, align 8 -// CHECK-NEXT: %30 = load { ptr, i64, { ptr, ptr } }, ptr %29, align 8 -// CHECK-NEXT: %31 = extractvalue { ptr, i64, { ptr, ptr } } %30, 0 -// CHECK-NEXT: store ptr %31, ptr %16, align 8 -// CHECK-NEXT: %32 = extractvalue { ptr, i64, { ptr, ptr } } %30, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %29) -// CHECK-NEXT: %33 = extractvalue { ptr, ptr } %32, 1 -// CHECK-NEXT: %34 = extractvalue { ptr, ptr } %32, 0 -// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %34) -// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %33) +// CHECK-NEXT: %30 = load ptr, ptr %16, align 8 +// CHECK-NEXT: %31 = load { ptr, i64, { ptr, ptr } }, ptr %30, align 8 +// CHECK-NEXT: %32 = extractvalue { ptr, i64, { ptr, ptr } } %31, 0 +// CHECK-NEXT: store ptr %32, ptr %16, align 8 +// CHECK-NEXT: %33 = extractvalue { ptr, i64, { ptr, ptr } } %31, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %30) +// CHECK-NEXT: %34 = extractvalue { ptr, ptr } %33, 0 +// CHECK-NEXT: %35 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr %34) +// CHECK-NEXT: %36 = extractvalue { ptr, ptr } %33, 1 +// CHECK-NEXT: %37 = extractvalue { ptr, ptr } %33, 0 +// CHECK-NEXT: %__llgo_funcval_code = call ptr asm "", "=r,0"(ptr %37) +// CHECK-NEXT: call void %__llgo_funcval_code(ptr {{(nest|swiftself)}} %36) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %35) // CHECK-NEXT: br label %_llgo_9 // CHECK-EMPTY: // CHECK-NEXT: _llgo_9: ; preds = %_llgo_8, %_llgo_7 -// CHECK-NEXT: %35 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, align 8 -// CHECK-NEXT: %36 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %35, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %36) -// CHECK-NEXT: %37 = load ptr, ptr %15, align 8 -// CHECK-NEXT: indirectbr ptr %37, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: %38 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, align 8 +// CHECK-NEXT: %39 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %38, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %39) +// CHECK-NEXT: %40 = load ptr, ptr %15, align 8 +// CHECK-NEXT: indirectbr ptr %40, [label %_llgo_3, label %_llgo_6] // CHECK-NEXT: } // CHECK-LABEL: define void @"main.demo3$1$1"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 -// CHECK-NEXT: %2 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %3, align 8 -// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 -// CHECK-NEXT: %5 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %2, %"{{.*}}/runtime/internal/runtime.eface" %4) -// CHECK-NEXT: %6 = xor i1 %5, true -// CHECK-NEXT: br i1 %6, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %2 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.demo3$1$1", ptr %2) +// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %2) +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %4, align 8 +// CHECK-NEXT: %5 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %4, 1 +// CHECK-NEXT: %6 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %3, %"{{.*}}/runtime/internal/runtime.eface" %5) +// CHECK-NEXT: %7 = xor i1 %6, true +// CHECK-NEXT: br i1 %7, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }, ptr %7, align 8 -// CHECK-NEXT: %8 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %7, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %8) +// CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }, ptr %8, align 8 +// CHECK-NEXT: %9 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %8, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %9) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %9 = extractvalue { ptr } %1, 0 -// CHECK-NEXT: %10 = load ptr, ptr %9, align 8 -// CHECK-NEXT: %11 = call ptr @llvm.stacksave.p0() -// CHECK-NEXT: %12 = alloca i1, align 1 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %12, i8 0, i64 1, i1 false) -// CHECK-NEXT: store i1 true, ptr %12, align 1 -// CHECK-NEXT: %13 = call i1 @"{{.*}}/runtime/internal/runtime.ChanSend"(ptr %10, ptr %12, i64 1) -// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %11) +// CHECK-NEXT: %10 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %11 = load ptr, ptr %10, align 8 +// CHECK-NEXT: %12 = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: %13 = alloca i1, align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %13, i8 0, i64 1, i1 false) +// CHECK-NEXT: store i1 true, ptr %13, align 1 +// CHECK-NEXT: %14 = call i1 @"{{.*}}/runtime/internal/runtime.ChanSend"(ptr %11, ptr %13, i64 1) +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %12) // CHECK-NEXT: ret void // CHECK-NEXT: } // CHECK-LABEL: define void @"main.demo3$1$2"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: %2 = xor i1 %1, true -// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.demo3$1$2", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: %3 = xor i1 %2, true +// CHECK-NEXT: br i1 %3, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %3, align 8 -// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 8 }, ptr %4, align 8 +// CHECK-NEXT: %5 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %4, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %5) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %5, align 8 -// CHECK-NEXT: %6 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %5, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %6) +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }, ptr %6, align 8 +// CHECK-NEXT: %7 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %6, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %7) // CHECK-NEXT: unreachable // CHECK-NEXT: } diff --git a/cl/_testgo/ifaceprom/in.go b/cl/_testgo/ifaceprom/in.go index 3dd49d6e04..dedb859701 100644 --- a/cl/_testgo/ifaceprom/in.go +++ b/cl/_testgo/ifaceprom/in.go @@ -5,11 +5,11 @@ package main // struct. In particular, this test exercises that the correct // method is called. -// CHECK: @0 = private unnamed_addr constant [3 x i8] c"two", align 1 -// CHECK: @1 = private unnamed_addr constant [48 x i8] c"{{.*}}/cl/_testgo/ifaceprom.impl", align 1 -// CHECK: @2 = private unnamed_addr constant [3 x i8] c"one", align 1 -// CHECK: @13 = private unnamed_addr constant [45 x i8] c"{{.*}}/cl/_testgo/ifaceprom.I", align 1 -// CHECK: @14 = private unnamed_addr constant [4 x i8] c"pass", align 1 +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"two", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [48 x i8] c"{{.*}}/cl/_testgo/ifaceprom.impl", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"one", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [45 x i8] c"{{.*}}/cl/_testgo/ifaceprom.I", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [4 x i8] c"pass", align 1{{$}} type I interface { one() int @@ -79,10 +79,13 @@ func main() { // CHECK-NEXT: %7 = load ptr, ptr %6, align 8 // CHECK-NEXT: %8 = insertvalue { ptr, ptr } undef, ptr %7, 0 // CHECK-NEXT: %9 = insertvalue { ptr, ptr } %8, ptr %4, 1 -// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %9, 1 -// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %9, 0 -// CHECK-NEXT: %12 = call i64 %11(ptr %10) -// CHECK-NEXT: ret i64 %12 +// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %9, 0 +// CHECK-NEXT: %11 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @main.S.one, ptr %10) +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %9, 1 +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %9, 0 +// CHECK-NEXT: %14 = call i64 %13(ptr %12) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %11) +// CHECK-NEXT: ret i64 %14 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @main.S.two(%main.S %0){{.*}} { @@ -98,10 +101,13 @@ func main() { // CHECK-NEXT: %7 = load ptr, ptr %6, align 8 // CHECK-NEXT: %8 = insertvalue { ptr, ptr } undef, ptr %7, 0 // CHECK-NEXT: %9 = insertvalue { ptr, ptr } %8, ptr %4, 1 -// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %9, 1 -// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %9, 0 -// CHECK-NEXT: %12 = call %"{{.*}}/runtime/internal/runtime.String" %11(ptr %10) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %12 +// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %9, 0 +// CHECK-NEXT: %11 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @main.S.two, ptr %10) +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %9, 1 +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %9, 0 +// CHECK-NEXT: %14 = call %"{{.*}}/runtime/internal/runtime.String" %13(ptr %12) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %11) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %14 // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.(*S).one"(ptr %0){{.*}} { @@ -114,10 +120,13 @@ func main() { // CHECK-NEXT: %6 = load ptr, ptr %5, align 8 // CHECK-NEXT: %7 = insertvalue { ptr, ptr } undef, ptr %6, 0 // CHECK-NEXT: %8 = insertvalue { ptr, ptr } %7, ptr %3, 1 -// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %8, 1 -// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %8, 0 -// CHECK-NEXT: %11 = call i64 %10(ptr %9) -// CHECK-NEXT: ret i64 %11 +// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @"main.(*S).one", ptr %9) +// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %8, 1 +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %13 = call i64 %12(ptr %11) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %10) +// CHECK-NEXT: ret i64 %13 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @"main.(*S).two"(ptr %0){{.*}} { @@ -130,10 +139,13 @@ func main() { // CHECK-NEXT: %6 = load ptr, ptr %5, align 8 // CHECK-NEXT: %7 = insertvalue { ptr, ptr } undef, ptr %6, 0 // CHECK-NEXT: %8 = insertvalue { ptr, ptr } %7, ptr %3, 1 -// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %8, 1 -// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %8, 0 -// CHECK-NEXT: %11 = call %"{{.*}}/runtime/internal/runtime.String" %10(ptr %9) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %11 +// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @"main.(*S).two", ptr %9) +// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %8, 1 +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %13 = call %"{{.*}}/runtime/internal/runtime.String" %12(ptr %11) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %10) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %13 // CHECK-NEXT: } // CHECK-LABEL: define i64 @main.impl.one(%main.impl %0){{.*}} { @@ -143,13 +155,13 @@ func main() { // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @main.impl.two(%main.impl %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 3 } +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 } // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.(*impl).one"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = icmp eq ptr %0, null -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @1, i64 48 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 3 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 48 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: %2 = icmp eq ptr %0, null // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %2) // CHECK-NEXT: %3 = call i64 @main.impl.one(%main.impl zeroinitializer) @@ -159,7 +171,7 @@ func main() { // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @"main.(*impl).two"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = icmp eq ptr %0, null -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @1, i64 48 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 3 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 48 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: %2 = icmp eq ptr %0, null // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %2) // CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.String" @main.impl.two(%main.impl zeroinitializer) @@ -186,7 +198,7 @@ func main() { // CHECK-NEXT: %1 = getelementptr inbounds %main.S, ptr %0, i32 0, i32 0 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 0) // CHECK-NEXT: store %main.impl zeroinitializer, ptr %2, align 1 -// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"{{.*}}/cl/_testgo/ifaceprom.iface${{[-A-Za-z0-9_]+}}", ptr @_llgo_main.impl) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"{{.*}}/cl/_testgo/ifaceprom.iface$zZ89tENb5h_KNjvpxf1TXPfaWFYn0IZrZwyVf42lRtA", ptr @_llgo_main.impl) // CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %3, 0 // CHECK-NEXT: %5 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %4, ptr %2, 1 // CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %5, ptr %1, align 8 @@ -273,7 +285,7 @@ func main() { // CHECK-NEXT: %54 = extractvalue { ptr, ptr } %53, 1 // CHECK-NEXT: %55 = extractvalue { ptr, ptr } %53, 0 // CHECK-NEXT: %56 = call %"{{.*}}/runtime/internal/runtime.String" %55(ptr %54) -// CHECK-NEXT: %57 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %56, %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 3 }) +// CHECK-NEXT: %57 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %56, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: %58 = xor i1 %57, true // CHECK-NEXT: br i1 %58, label %_llgo_9, label %_llgo_10 // CHECK-EMPTY: @@ -296,7 +308,7 @@ func main() { // CHECK-NEXT: %69 = extractvalue { ptr, ptr } %68, 1 // CHECK-NEXT: %70 = extractvalue { ptr, ptr } %68, 0 // CHECK-NEXT: %71 = call %"{{.*}}/runtime/internal/runtime.String" %70(ptr %69) -// CHECK-NEXT: %72 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %71, %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 3 }) +// CHECK-NEXT: %72 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %71, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: %73 = xor i1 %72, true // CHECK-NEXT: br i1 %73, label %_llgo_11, label %_llgo_12 // CHECK-EMPTY: @@ -336,7 +348,7 @@ func main() { // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_16: ; preds = %_llgo_23 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @14, i64 4 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 4 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void // CHECK-EMPTY: @@ -353,7 +365,7 @@ func main() { // CHECK-NEXT: br i1 %94, label %_llgo_5, label %_llgo_6 // CHECK-EMPTY: // CHECK-NEXT: _llgo_18: ; preds = %_llgo_4 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %36, %"{{.*}}/runtime/internal/runtime.String" { ptr @13, i64 45 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 3 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %36, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 45 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_19: ; preds = %_llgo_6 @@ -369,7 +381,7 @@ func main() { // CHECK-NEXT: br i1 %101, label %_llgo_7, label %_llgo_8 // CHECK-EMPTY: // CHECK-NEXT: _llgo_20: ; preds = %_llgo_6 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %42, %"{{.*}}/runtime/internal/runtime.String" { ptr @13, i64 45 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 3 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %42, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 45 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_21: ; preds = %_llgo_12 @@ -381,12 +393,12 @@ func main() { // CHECK-NEXT: %106 = extractvalue { ptr, ptr } %104, 0 // CHECK-NEXT: %__llgo_funcval_code2 = call ptr asm "", "=r,0"(ptr %106) // CHECK-NEXT: %107 = call %"{{.*}}/runtime/internal/runtime.String" %__llgo_funcval_code2(ptr {{(nest|swiftself)}} %105) -// CHECK-NEXT: %108 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %107, %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 3 }) +// CHECK-NEXT: %108 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %107, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: %109 = xor i1 %108, true // CHECK-NEXT: br i1 %109, label %_llgo_13, label %_llgo_14 // CHECK-EMPTY: // CHECK-NEXT: _llgo_22: ; preds = %_llgo_12 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %78, %"{{.*}}/runtime/internal/runtime.String" { ptr @13, i64 45 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 3 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %78, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 45 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_23: ; preds = %_llgo_14 @@ -398,12 +410,12 @@ func main() { // CHECK-NEXT: %114 = extractvalue { ptr, ptr } %112, 0 // CHECK-NEXT: %__llgo_funcval_code3 = call ptr asm "", "=r,0"(ptr %114) // CHECK-NEXT: %115 = call %"{{.*}}/runtime/internal/runtime.String" %__llgo_funcval_code3(ptr {{(nest|swiftself)}} %113) -// CHECK-NEXT: %116 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %115, %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 3 }) +// CHECK-NEXT: %116 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %115, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: %117 = xor i1 %116, true // CHECK-NEXT: br i1 %117, label %_llgo_15, label %_llgo_16 // CHECK-EMPTY: // CHECK-NEXT: _llgo_24: ; preds = %_llgo_14 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %84, %"{{.*}}/runtime/internal/runtime.String" { ptr @13, i64 45 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 3 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %84, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 45 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: unreachable // CHECK-NEXT: } @@ -417,10 +429,13 @@ func main() { // CHECK-NEXT: %6 = load ptr, ptr %5, align 8 // CHECK-NEXT: %7 = insertvalue { ptr, ptr } undef, ptr %6, 0 // CHECK-NEXT: %8 = insertvalue { ptr, ptr } %7, ptr %3, 1 -// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %8, 1 -// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %8, 0 -// CHECK-NEXT: %11 = call i64 %10(ptr %9) -// CHECK-NEXT: ret i64 %11 +// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @"main.I.one$bound", ptr %9) +// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %8, 1 +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %13 = call i64 %12(ptr %11) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %10) +// CHECK-NEXT: ret i64 %13 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @"main.I.two$bound"(ptr {{(nest|swiftself)}} %0){{.*}} { @@ -433,8 +448,11 @@ func main() { // CHECK-NEXT: %6 = load ptr, ptr %5, align 8 // CHECK-NEXT: %7 = insertvalue { ptr, ptr } undef, ptr %6, 0 // CHECK-NEXT: %8 = insertvalue { ptr, ptr } %7, ptr %3, 1 -// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %8, 1 -// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %8, 0 -// CHECK-NEXT: %11 = call %"{{.*}}/runtime/internal/runtime.String" %10(ptr %9) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %11 +// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @"main.I.two$bound", ptr %9) +// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %8, 1 +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %8, 0 +// CHECK-NEXT: %13 = call %"{{.*}}/runtime/internal/runtime.String" %12(ptr %11) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %10) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %13 // CHECK-NEXT: } diff --git a/cl/_testgo/indexerr/in.go b/cl/_testgo/indexerr/in.go index 62fdecd500..b12c5d6897 100644 --- a/cl/_testgo/indexerr/in.go +++ b/cl/_testgo/indexerr/in.go @@ -215,7 +215,7 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#1"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -241,12 +241,14 @@ func slice2(n int) { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#1", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#1$1") // CHECK-NEXT: call void @"main.init#1$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) @@ -259,8 +261,8 @@ func slice2(n int) { // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#1", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %17 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %18 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -268,15 +270,17 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#1$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#1$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }, ptr %2, align 8 -// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -286,7 +290,7 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#10"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -312,42 +316,44 @@ func slice2(n int) { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#10", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#10$1") // CHECK-NEXT: call void @"main.init#10$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) -// CHECK-NEXT: %18 = getelementptr inbounds i64, ptr %17, i64 0 -// CHECK-NEXT: store i64 1, ptr %18, align 8 -// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %17, i64 1 -// CHECK-NEXT: store i64 2, ptr %19, align 8 -// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %17, 0 -// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %20, i64 2, 1 -// CHECK-NEXT: %22 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %21, i64 2, 2 -// CHECK-NEXT: %23 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, 0 -// CHECK-NEXT: %24 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, 1 -// CHECK-NEXT: %25 = icmp uge i64 -1, %24 -// CHECK-NEXT: %26 = or i1 %25, true -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %26, i64 -1, i1 true, i64 %24) -// CHECK-NEXT: %27 = getelementptr inbounds i64, ptr %23, i64 -1 -// CHECK-NEXT: %28 = load i64, ptr %27, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %28) +// CHECK-NEXT: %18 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %18, i64 0 +// CHECK-NEXT: store i64 1, ptr %19, align 8 +// CHECK-NEXT: %20 = getelementptr inbounds i64, ptr %18, i64 1 +// CHECK-NEXT: store i64 2, ptr %20, align 8 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %18, 0 +// CHECK-NEXT: %22 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %21, i64 2, 1 +// CHECK-NEXT: %23 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, i64 2, 2 +// CHECK-NEXT: %24 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %23, 0 +// CHECK-NEXT: %25 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %23, 1 +// CHECK-NEXT: %26 = icmp uge i64 -1, %25 +// CHECK-NEXT: %27 = or i1 %26, true +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %27, i64 -1, i1 true, i64 %25) +// CHECK-NEXT: %28 = getelementptr inbounds i64, ptr %24, i64 -1 +// CHECK-NEXT: %29 = load i64, ptr %28, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %29) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: store ptr blockaddress(@"main.init#10", %_llgo_6), ptr %9, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#10", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %29 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %29, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %30 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %30, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -355,15 +361,17 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#10$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#10$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 12 }, ptr %2, align 8 -// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 12 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -373,7 +381,7 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#11"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -399,41 +407,43 @@ func slice2(n int) { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#11", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#11$1") // CHECK-NEXT: call void @"main.init#11$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) -// CHECK-NEXT: %18 = getelementptr inbounds i64, ptr %17, i64 0 -// CHECK-NEXT: store i64 1, ptr %18, align 8 -// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %17, i64 1 -// CHECK-NEXT: store i64 2, ptr %19, align 8 -// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %17, 0 -// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %20, i64 2, 1 -// CHECK-NEXT: %22 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %21, i64 2, 2 -// CHECK-NEXT: %23 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, 0 -// CHECK-NEXT: %24 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, 1 -// CHECK-NEXT: %25 = icmp uge i64 2, %24 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %25, i64 2, i1 true, i64 %24) -// CHECK-NEXT: %26 = getelementptr inbounds i64, ptr %23, i64 2 -// CHECK-NEXT: %27 = load i64, ptr %26, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %27) +// CHECK-NEXT: %18 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %18, i64 0 +// CHECK-NEXT: store i64 1, ptr %19, align 8 +// CHECK-NEXT: %20 = getelementptr inbounds i64, ptr %18, i64 1 +// CHECK-NEXT: store i64 2, ptr %20, align 8 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %18, 0 +// CHECK-NEXT: %22 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %21, i64 2, 1 +// CHECK-NEXT: %23 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, i64 2, 2 +// CHECK-NEXT: %24 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %23, 0 +// CHECK-NEXT: %25 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %23, 1 +// CHECK-NEXT: %26 = icmp uge i64 2, %25 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %26, i64 2, i1 true, i64 %25) +// CHECK-NEXT: %27 = getelementptr inbounds i64, ptr %24, i64 2 +// CHECK-NEXT: %28 = load i64, ptr %27, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %28) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: store ptr blockaddress(@"main.init#11", %_llgo_6), ptr %9, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#11", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %28 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %28, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %29 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %29, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -441,15 +451,17 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#11$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#11$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %2, align 8 -// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -459,7 +471,7 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#12"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -485,41 +497,43 @@ func slice2(n int) { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#12", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#12$1") // CHECK-NEXT: call void @"main.init#12$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) -// CHECK-NEXT: %18 = getelementptr inbounds i64, ptr %17, i64 0 -// CHECK-NEXT: store i64 1, ptr %18, align 8 -// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %17, i64 1 -// CHECK-NEXT: store i64 2, ptr %19, align 8 -// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %17, 0 -// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %20, i64 2, 1 -// CHECK-NEXT: %22 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %21, i64 2, 2 -// CHECK-NEXT: %23 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, 0 -// CHECK-NEXT: %24 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, 1 -// CHECK-NEXT: %25 = icmp uge i64 2, %24 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %25, i64 2, i1 false, i64 %24) -// CHECK-NEXT: %26 = getelementptr inbounds i64, ptr %23, i64 2 -// CHECK-NEXT: %27 = load i64, ptr %26, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %27) +// CHECK-NEXT: %18 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %18, i64 0 +// CHECK-NEXT: store i64 1, ptr %19, align 8 +// CHECK-NEXT: %20 = getelementptr inbounds i64, ptr %18, i64 1 +// CHECK-NEXT: store i64 2, ptr %20, align 8 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %18, 0 +// CHECK-NEXT: %22 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %21, i64 2, 1 +// CHECK-NEXT: %23 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %22, i64 2, 2 +// CHECK-NEXT: %24 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %23, 0 +// CHECK-NEXT: %25 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %23, 1 +// CHECK-NEXT: %26 = icmp uge i64 2, %25 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %26, i64 2, i1 false, i64 %25) +// CHECK-NEXT: %27 = getelementptr inbounds i64, ptr %24, i64 2 +// CHECK-NEXT: %28 = load i64, ptr %27, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %28) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: store ptr blockaddress(@"main.init#12", %_llgo_6), ptr %9, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#12", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %28 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %28, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %29 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %29, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -527,15 +541,17 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#12$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#12$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 12 }, ptr %2, align 8 -// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 12 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -545,7 +561,7 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#2"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -571,12 +587,14 @@ func slice2(n int) { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#2", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#2$1") // CHECK-NEXT: call void @"main.init#2$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) @@ -589,8 +607,8 @@ func slice2(n int) { // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#2", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %17 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %18 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -598,15 +616,17 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#2$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#2$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 18 }, ptr %2, align 8 -// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 18 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -616,7 +636,7 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#3"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -642,12 +662,14 @@ func slice2(n int) { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#3", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#3$1") // CHECK-NEXT: call void @"main.init#3$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) @@ -660,8 +682,8 @@ func slice2(n int) { // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#3", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %17 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %18 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -669,15 +691,17 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#3$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#3$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }, ptr %2, align 8 -// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 17 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -687,7 +711,7 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#4"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -713,12 +737,14 @@ func slice2(n int) { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#4", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#4$1") // CHECK-NEXT: call void @"main.init#4$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) @@ -731,8 +757,8 @@ func slice2(n int) { // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#4", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %17 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %18 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -740,15 +766,17 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#4$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#4$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }, ptr %2, align 8 -// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -758,7 +786,7 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#5"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -784,12 +812,14 @@ func slice2(n int) { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#5", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#5$1") // CHECK-NEXT: call void @"main.init#5$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) @@ -802,8 +832,8 @@ func slice2(n int) { // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#5", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %17 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %18 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -811,15 +841,17 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#5$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#5$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 18 }, ptr %2, align 8 -// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 18 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -829,7 +861,7 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#6"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -855,12 +887,14 @@ func slice2(n int) { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#6", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#6$1") // CHECK-NEXT: call void @"main.init#6$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) @@ -873,8 +907,8 @@ func slice2(n int) { // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#6", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %17 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %18 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -882,15 +916,17 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#6$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#6$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }, ptr %2, align 8 -// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -900,7 +936,7 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#7"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -926,36 +962,39 @@ func slice2(n int) { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#7", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#7$1") // CHECK-NEXT: call void @"main.init#7$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: %17 = alloca [2 x i64], align 8 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %17, i8 0, i64 16, i1 false) -// CHECK-NEXT: %18 = getelementptr inbounds i64, ptr %17, i64 0 -// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %17, i64 1 -// CHECK-NEXT: store i64 1, ptr %18, align 8 -// CHECK-NEXT: store i64 2, ptr %19, align 8 +// CHECK-NEXT: %18 = alloca [2 x i64], align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %18, i8 0, i64 16, i1 false) +// CHECK-NEXT: store volatile [2 x i64] zeroinitializer, ptr %18, align 8 +// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %18, i64 0 +// CHECK-NEXT: %20 = getelementptr inbounds i64, ptr %18, i64 1 +// CHECK-NEXT: store volatile i64 1, ptr %19, align 8 +// CHECK-NEXT: store volatile i64 2, ptr %20, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 true, i64 -1, i1 true, i64 2) -// CHECK-NEXT: %20 = getelementptr inbounds i64, ptr %17, i64 -1 -// CHECK-NEXT: %21 = load i64, ptr %20, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %21) +// CHECK-NEXT: %21 = getelementptr inbounds i64, ptr %18, i64 -1 +// CHECK-NEXT: %22 = load volatile i64, ptr %21, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %22) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: store ptr blockaddress(@"main.init#7", %_llgo_6), ptr %9, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#7", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %22 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %22, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %23 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %23, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -963,15 +1002,17 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#7$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#7$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 12 }, ptr %2, align 8 -// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 12 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -981,7 +1022,7 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#8"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -1007,36 +1048,39 @@ func slice2(n int) { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#8", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#8$1") // CHECK-NEXT: call void @"main.init#8$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: %17 = alloca [2 x i64], align 8 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %17, i8 0, i64 16, i1 false) -// CHECK-NEXT: %18 = getelementptr inbounds i64, ptr %17, i64 0 -// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %17, i64 1 -// CHECK-NEXT: store i64 1, ptr %18, align 8 -// CHECK-NEXT: store i64 2, ptr %19, align 8 +// CHECK-NEXT: %18 = alloca [2 x i64], align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %18, i8 0, i64 16, i1 false) +// CHECK-NEXT: store volatile [2 x i64] zeroinitializer, ptr %18, align 8 +// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %18, i64 0 +// CHECK-NEXT: %20 = getelementptr inbounds i64, ptr %18, i64 1 +// CHECK-NEXT: store volatile i64 1, ptr %19, align 8 +// CHECK-NEXT: store volatile i64 2, ptr %20, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 true, i64 2, i1 true, i64 2) -// CHECK-NEXT: %20 = getelementptr inbounds i64, ptr %17, i64 2 -// CHECK-NEXT: %21 = load i64, ptr %20, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %21) +// CHECK-NEXT: %21 = getelementptr inbounds i64, ptr %18, i64 2 +// CHECK-NEXT: %22 = load volatile i64, ptr %21, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %22) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: store ptr blockaddress(@"main.init#8", %_llgo_6), ptr %9, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#8", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %22 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %22, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %23 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %23, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -1044,15 +1088,17 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#8$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#8$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %2, align 8 -// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -1062,7 +1108,7 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#9"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -1088,36 +1134,39 @@ func slice2(n int) { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#9", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#9$1") // CHECK-NEXT: call void @"main.init#9$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: %17 = alloca [2 x i64], align 8 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %17, i8 0, i64 16, i1 false) -// CHECK-NEXT: %18 = getelementptr inbounds i64, ptr %17, i64 0 -// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %17, i64 1 -// CHECK-NEXT: store i64 1, ptr %18, align 8 -// CHECK-NEXT: store i64 2, ptr %19, align 8 +// CHECK-NEXT: %18 = alloca [2 x i64], align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %18, i8 0, i64 16, i1 false) +// CHECK-NEXT: store volatile [2 x i64] zeroinitializer, ptr %18, align 8 +// CHECK-NEXT: %19 = getelementptr inbounds i64, ptr %18, i64 0 +// CHECK-NEXT: %20 = getelementptr inbounds i64, ptr %18, i64 1 +// CHECK-NEXT: store volatile i64 1, ptr %19, align 8 +// CHECK-NEXT: store volatile i64 2, ptr %20, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 true, i64 2, i1 false, i64 2) -// CHECK-NEXT: %20 = getelementptr inbounds i64, ptr %17, i64 2 -// CHECK-NEXT: %21 = load i64, ptr %20, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %21) +// CHECK-NEXT: %21 = getelementptr inbounds i64, ptr %18, i64 2 +// CHECK-NEXT: %22 = load volatile i64, ptr %21, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %22) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: store ptr blockaddress(@"main.init#9", %_llgo_6), ptr %9, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#9", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %22 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %22, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %23 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %23, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -1125,15 +1174,17 @@ func slice2(n int) { // CHECK-LABEL: define void @"main.init#9$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#9$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 12 }, ptr %2, align 8 -// CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %2, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %3) +// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 12 }, ptr %3, align 8 +// CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %3, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %4) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 diff --git a/cl/_testgo/makeslice/in.go b/cl/_testgo/makeslice/in.go index de2ee3bba9..a8f3b01e70 100644 --- a/cl/_testgo/makeslice/in.go +++ b/cl/_testgo/makeslice/in.go @@ -126,7 +126,7 @@ func init() { // CHECK-LABEL: define void @"main.init#3"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -152,26 +152,28 @@ func init() { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#3", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#3$1") // CHECK-NEXT: call void @"main.init#3$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: %17 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.MakeSlice"(i64 -1, i64 -1, i64 8) +// CHECK-NEXT: %18 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.MakeSlice"(i64 -1, i64 -1, i64 8) // CHECK-NEXT: store ptr blockaddress(@"main.init#3", %_llgo_6), ptr %9, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#3", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %18 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %19 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %19, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -179,9 +181,11 @@ func init() { // CHECK-LABEL: define void @"main.init#3$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#3$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }) @@ -195,7 +199,7 @@ func init() { // CHECK-LABEL: define void @"main.init#4"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -221,26 +225,28 @@ func init() { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#4", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#4$1") // CHECK-NEXT: call void @"main.init#4$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: %17 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.MakeSlice"(i64 2, i64 1, i64 8) +// CHECK-NEXT: %18 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.MakeSlice"(i64 2, i64 1, i64 8) // CHECK-NEXT: store ptr blockaddress(@"main.init#4", %_llgo_6), ptr %9, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#4", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %18 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %19 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %19, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -248,9 +254,11 @@ func init() { // CHECK-LABEL: define void @"main.init#4$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#4$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }) @@ -264,7 +272,7 @@ func init() { // CHECK-LABEL: define void @"main.init#5"(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %1 = alloca i8 +// CHECK-NEXT: %1 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 @@ -290,26 +298,28 @@ func init() { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5, %_llgo_4 // CHECK-NEXT: store ptr blockaddress(@"main.init#5", %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @"main.init#5$1") // CHECK-NEXT: call void @"main.init#5$1"() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3, label %_llgo_6] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: %17 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.MakeSlice"(i64 9223372036854775807, i64 9223372036854775807, i64 8) +// CHECK-NEXT: %18 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.MakeSlice"(i64 9223372036854775807, i64 9223372036854775807, i64 8) // CHECK-NEXT: store ptr blockaddress(@"main.init#5", %_llgo_6), ptr %9, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@"main.init#5", %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %18 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %18, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %19 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %19, [label %_llgo_3, label %_llgo_2] // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_2 // CHECK-NEXT: ret void @@ -317,9 +327,11 @@ func init() { // CHECK-LABEL: define void @"main.init#5$1"(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %1, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.init#5$1", ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 10 }) diff --git a/cl/_testgo/reader/in.go b/cl/_testgo/reader/in.go index 2fd463b8a6..79e7b6a5a3 100644 --- a/cl/_testgo/reader/in.go +++ b/cl/_testgo/reader/in.go @@ -5,21 +5,21 @@ import ( "unicode/utf8" ) -// CHECK: @2 = private unnamed_addr constant [7 x i8] c"WriteTo", align 1 -// CHECK: @17 = private unnamed_addr constant [5 x i8] c"Close", align 1 -// CHECK: @28 = private unnamed_addr constant [3 x i8] c"EOF", align 1 -// CHECK: @29 = private unnamed_addr constant [11 x i8] c"short write", align 1 -// CHECK: @30 = private unnamed_addr constant [11 x i8] c"hello world", align 1 -// CHECK: @53 = private unnamed_addr constant [50 x i8] c"{{.*}}/cl/_testgo/reader.nopCloser", align 1 -// CHECK: @54 = private unnamed_addr constant [49 x i8] c"{{.*}}/cl/_testgo/reader.WriterTo", align 1 -// CHECK: @55 = private unnamed_addr constant [58 x i8] c"{{.*}}/cl/_testgo/reader.nopCloserWriterTo", align 1 -// CHECK: @56 = private unnamed_addr constant [37 x i8] c"stringsReader.ReadAt: negative offset", align 1 -// CHECK: @57 = private unnamed_addr constant [34 x i8] c"stringsReader.Seek: invalid whence", align 1 -// CHECK: @58 = private unnamed_addr constant [37 x i8] c"stringsReader.Seek: negative position", align 1 -// CHECK: @59 = private unnamed_addr constant [48 x i8] c"stringsReader.UnreadByte: at beginning of string", align 1 -// CHECK: @60 = private unnamed_addr constant [49 x i8] c"strings.Reader.UnreadRune: at beginning of string", align 1 -// CHECK: @61 = private unnamed_addr constant [62 x i8] c"strings.Reader.UnreadRune: previous operation was not ReadRune", align 1 -// CHECK: @62 = private unnamed_addr constant [48 x i8] c"stringsReader.WriteTo: invalid WriteString count", align 1 +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [7 x i8] c"WriteTo", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"Close", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"EOF", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [11 x i8] c"short write", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [11 x i8] c"hello world", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [50 x i8] c"{{.*}}/cl/_testgo/reader.nopCloser", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [49 x i8] c"{{.*}}/cl/_testgo/reader.WriterTo", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [58 x i8] c"{{.*}}/cl/_testgo/reader.nopCloserWriterTo", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [37 x i8] c"stringsReader.ReadAt: negative offset", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [34 x i8] c"stringsReader.Seek: invalid whence", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [37 x i8] c"stringsReader.Seek: negative position", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [48 x i8] c"stringsReader.UnreadByte: at beginning of string", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [49 x i8] c"strings.Reader.UnreadRune: at beginning of string", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [62 x i8] c"strings.Reader.UnreadRune: previous operation was not ReadRune", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [48 x i8] c"stringsReader.WriteTo: invalid WriteString count", align 1{{$}} type Reader interface { Read(p []byte) (n int, err error) @@ -129,6 +129,200 @@ func WriteString(w Writer, s string) (n int, err error) { return w.Write([]byte(s)) } +func NopCloser(r Reader) ReadCloser { + if _, ok := r.(WriterTo); ok { + return nopCloserWriterTo{r} + } + return nopCloser{r} +} + +type nopCloser struct { + Reader +} + +func (nopCloser) Close() error { return nil } + +type nopCloserWriterTo struct { + Reader +} + +func (nopCloserWriterTo) Close() error { return nil } + +func (c nopCloserWriterTo) WriteTo(w Writer) (n int64, err error) { + return c.Reader.(WriterTo).WriteTo(w) +} + +func ReadAll(r Reader) ([]byte, error) { + b := make([]byte, 0, 512) + for { + n, err := r.Read(b[len(b):cap(b)]) + b = b[:len(b)+n] + if err != nil { + if err == EOF { + err = nil + } + return b, err + } + + if len(b) == cap(b) { + // Add more capacity (let append pick how much). + b = append(b, 0)[:len(b)] + } + } +} + +type stringReader struct { + s string + i int64 // current reading index + prevRune int // index of previous rune; or < 0 +} + +func (r *stringReader) Len() int { + if r.i >= int64(len(r.s)) { + return 0 + } + return int(int64(len(r.s)) - r.i) +} + +func (r *stringReader) Size() int64 { return int64(len(r.s)) } + +func (r *stringReader) Read(b []byte) (n int, err error) { + if r.i >= int64(len(r.s)) { + return 0, EOF + } + r.prevRune = -1 + n = copy(b, r.s[r.i:]) + r.i += int64(n) + return +} + +func (r *stringReader) ReadAt(b []byte, off int64) (n int, err error) { + if off < 0 { + return 0, newError("stringsReader.ReadAt: negative offset") + } + if off >= int64(len(r.s)) { + return 0, EOF + } + n = copy(b, r.s[off:]) + if n < len(b) { + err = EOF + } + return +} + +func (r *stringReader) ReadByte() (byte, error) { + r.prevRune = -1 + if r.i >= int64(len(r.s)) { + return 0, EOF + } + b := r.s[r.i] + r.i++ + return b, nil +} + +func (r *stringReader) UnreadByte() error { + if r.i <= 0 { + return newError("stringsReader.UnreadByte: at beginning of string") + } + r.prevRune = -1 + r.i-- + return nil +} + +func (r *stringReader) ReadRune() (ch rune, size int, err error) { + if r.i >= int64(len(r.s)) { + r.prevRune = -1 + return 0, 0, EOF + } + r.prevRune = int(r.i) + if c := r.s[r.i]; c < utf8.RuneSelf { + r.i++ + return rune(c), 1, nil + } + ch, size = utf8.DecodeRuneInString(r.s[r.i:]) + r.i += int64(size) + return +} + +func (r *stringReader) UnreadRune() error { + if r.i <= 0 { + return newError("strings.Reader.UnreadRune: at beginning of string") + } + if r.prevRune < 0 { + return newError("strings.Reader.UnreadRune: previous operation was not ReadRune") + } + r.i = int64(r.prevRune) + r.prevRune = -1 + return nil +} + +const ( + SeekStart = 0 // seek relative to the origin of the file + SeekCurrent = 1 // seek relative to the current offset + SeekEnd = 2 // seek relative to the end +) + +func (r *stringReader) Seek(offset int64, whence int) (int64, error) { + r.prevRune = -1 + var abs int64 + switch whence { + case SeekStart: + abs = offset + case SeekCurrent: + abs = r.i + offset + case SeekEnd: + abs = int64(len(r.s)) + offset + default: + return 0, newError("stringsReader.Seek: invalid whence") + } + if abs < 0 { + return 0, newError("stringsReader.Seek: negative position") + } + r.i = abs + return abs, nil +} + +func (r *stringReader) WriteTo(w Writer) (n int64, err error) { + r.prevRune = -1 + if r.i >= int64(len(r.s)) { + return 0, nil + } + s := r.s[r.i:] + m, err := WriteString(w, s) + if m > len(s) { + panic("stringsReader.WriteTo: invalid WriteString count") + } + r.i += int64(m) + n = int64(m) + if m != len(s) && err == nil { + err = ErrShortWrite + } + return +} + +func newError(text string) error { + return &errorString{text} +} + +type errorString struct { + s string +} + +func (e *errorString) Error() string { + return e.s +} + +var ( + EOF = newError("EOF") + ErrShortWrite = newError("short write") +) + +func main() { + r := &stringReader{s: "hello world"} + data, err := ReadAll(r) + println(string(data), err) +} + // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @main.NopCloser(%"{{.*}}/runtime/internal/runtime.iface" %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %0) @@ -180,29 +374,6 @@ func WriteString(w Writer, s string) (n int, err error) { // CHECK-NEXT: br i1 %25, label %_llgo_1, label %_llgo_2 // CHECK-NEXT: } -func NopCloser(r Reader) ReadCloser { - if _, ok := r.(WriterTo); ok { - return nopCloserWriterTo{r} - } - return nopCloser{r} -} - -type nopCloser struct { - Reader -} - -func (nopCloser) Close() error { return nil } - -type nopCloserWriterTo struct { - Reader -} - -func (nopCloserWriterTo) Close() error { return nil } - -func (c nopCloserWriterTo) WriteTo(w Writer) (n int64, err error) { - return c.Reader.(WriterTo).WriteTo(w) -} - // CHECK-LABEL: define { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @main.ReadAll(%"{{.*}}/runtime/internal/runtime.iface" %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 512) @@ -346,162 +517,6 @@ func (c nopCloserWriterTo) WriteTo(w Writer) (n int64, err error) { // CHECK-NEXT: br i1 %39, label %_llgo_1, label %_llgo_2 // CHECK-NEXT: } -func ReadAll(r Reader) ([]byte, error) { - b := make([]byte, 0, 512) - for { - n, err := r.Read(b[len(b):cap(b)]) - b = b[:len(b)+n] - if err != nil { - if err == EOF { - err = nil - } - return b, err - } - - if len(b) == cap(b) { - // Add more capacity (let append pick how much). - b = append(b, 0)[:len(b)] - } - } -} - -type stringReader struct { - s string - i int64 // current reading index - prevRune int // index of previous rune; or < 0 -} - -func (r *stringReader) Len() int { - if r.i >= int64(len(r.s)) { - return 0 - } - return int(int64(len(r.s)) - r.i) -} - -func (r *stringReader) Size() int64 { return int64(len(r.s)) } - -func (r *stringReader) Read(b []byte) (n int, err error) { - if r.i >= int64(len(r.s)) { - return 0, EOF - } - r.prevRune = -1 - n = copy(b, r.s[r.i:]) - r.i += int64(n) - return -} - -func (r *stringReader) ReadAt(b []byte, off int64) (n int, err error) { - if off < 0 { - return 0, newError("stringsReader.ReadAt: negative offset") - } - if off >= int64(len(r.s)) { - return 0, EOF - } - n = copy(b, r.s[off:]) - if n < len(b) { - err = EOF - } - return -} - -func (r *stringReader) ReadByte() (byte, error) { - r.prevRune = -1 - if r.i >= int64(len(r.s)) { - return 0, EOF - } - b := r.s[r.i] - r.i++ - return b, nil -} - -func (r *stringReader) UnreadByte() error { - if r.i <= 0 { - return newError("stringsReader.UnreadByte: at beginning of string") - } - r.prevRune = -1 - r.i-- - return nil -} - -func (r *stringReader) ReadRune() (ch rune, size int, err error) { - if r.i >= int64(len(r.s)) { - r.prevRune = -1 - return 0, 0, EOF - } - r.prevRune = int(r.i) - if c := r.s[r.i]; c < utf8.RuneSelf { - r.i++ - return rune(c), 1, nil - } - ch, size = utf8.DecodeRuneInString(r.s[r.i:]) - r.i += int64(size) - return -} - -func (r *stringReader) UnreadRune() error { - if r.i <= 0 { - return newError("strings.Reader.UnreadRune: at beginning of string") - } - if r.prevRune < 0 { - return newError("strings.Reader.UnreadRune: previous operation was not ReadRune") - } - r.i = int64(r.prevRune) - r.prevRune = -1 - return nil -} - -const ( - SeekStart = 0 // seek relative to the origin of the file - SeekCurrent = 1 // seek relative to the current offset - SeekEnd = 2 // seek relative to the end -) - -func (r *stringReader) Seek(offset int64, whence int) (int64, error) { - r.prevRune = -1 - var abs int64 - switch whence { - case SeekStart: - abs = offset - case SeekCurrent: - abs = r.i + offset - case SeekEnd: - abs = int64(len(r.s)) + offset - default: - return 0, newError("stringsReader.Seek: invalid whence") - } - if abs < 0 { - return 0, newError("stringsReader.Seek: negative position") - } - r.i = abs - return abs, nil -} - -func (r *stringReader) WriteTo(w Writer) (n int64, err error) { - r.prevRune = -1 - if r.i >= int64(len(r.s)) { - return 0, nil - } - s := r.s[r.i:] - m, err := WriteString(w, s) - if m > len(s) { - panic("stringsReader.WriteTo: invalid WriteString count") - } - r.i += int64(m) - n = int64(m) - if m != len(s) && err == nil { - err = ErrShortWrite - } - return -} - -func newError(text string) error { - return &errorString{text} -} - -type errorString struct { - s string -} - // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @"main.(*errorString).Error"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.errorString, ptr %0, i32 0, i32 0 @@ -517,9 +532,9 @@ type errorString struct { // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 // CHECK-NEXT: store i1 true, ptr @"main.init$guard", align 1 // CHECK-NEXT: call void @"unicode/utf8.init"() -// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @28, i64 3 }) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %1, ptr @main.EOF, align 8 -// CHECK-NEXT: %2 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @29, i64 11 }) +// CHECK-NEXT: %2 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 11 }) // CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.iface" %2, ptr @main.ErrShortWrite, align 8 // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: @@ -527,20 +542,11 @@ type errorString struct { // CHECK-NEXT: ret void // CHECK-NEXT: } -func (e *errorString) Error() string { - return e.s -} - -var ( - EOF = newError("EOF") - ErrShortWrite = newError("short write") -) - // CHECK-LABEL: define void @main.main(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) // CHECK-NEXT: %1 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @30, i64 11 }, ptr %1, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 11 }, ptr %1, align 8 // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface${{[-A-Za-z0-9_]+}}", ptr @"*_llgo_main.stringReader") // CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %2, 0 // CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %3, ptr %0, 1 @@ -571,12 +577,6 @@ var ( // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer // CHECK-NEXT: } -func main() { - r := &stringReader{s: "hello world"} - data, err := ReadAll(r) - println(string(data), err) -} - // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @main.nopCloser.Read(%main.nopCloser %0, %"{{.*}}/runtime/internal/runtime.Slice" %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = alloca %main.nopCloser, align 8 @@ -590,20 +590,23 @@ func main() { // CHECK-NEXT: %8 = load ptr, ptr %7, align 8 // CHECK-NEXT: %9 = insertvalue { ptr, ptr } undef, ptr %8, 0 // CHECK-NEXT: %10 = insertvalue { ptr, ptr } %9, ptr %5, 1 -// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %10, 1 -// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %10, 0 -// CHECK-NEXT: %13 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } %12(ptr %11, %"{{.*}}/runtime/internal/runtime.Slice" %1) -// CHECK-NEXT: %14 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %13, 0 -// CHECK-NEXT: %15 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %13, 1 -// CHECK-NEXT: %16 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %14, 0 -// CHECK-NEXT: %17 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %16, %"{{.*}}/runtime/internal/runtime.iface" %15, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %17 +// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %10, 0 +// CHECK-NEXT: %12 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @main.nopCloser.Read, ptr %11) +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %10, 1 +// CHECK-NEXT: %14 = extractvalue { ptr, ptr } %10, 0 +// CHECK-NEXT: %15 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } %14(ptr %13, %"{{.*}}/runtime/internal/runtime.Slice" %1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %12) +// CHECK-NEXT: %16 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %15, 0 +// CHECK-NEXT: %17 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %15, 1 +// CHECK-NEXT: %18 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %16, 0 +// CHECK-NEXT: %19 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %18, %"{{.*}}/runtime/internal/runtime.iface" %17, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %19 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @"main.(*nopCloser).Close"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = icmp eq ptr %0, null -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @53, i64 50 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @17, i64 5 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 50 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) // CHECK-NEXT: %2 = load %main.nopCloser, ptr %0, align 8 // CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.iface" @main.nopCloser.Close(%main.nopCloser %2) // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %3 @@ -619,14 +622,17 @@ func main() { // CHECK-NEXT: %7 = load ptr, ptr %6, align 8 // CHECK-NEXT: %8 = insertvalue { ptr, ptr } undef, ptr %7, 0 // CHECK-NEXT: %9 = insertvalue { ptr, ptr } %8, ptr %4, 1 -// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %9, 1 -// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %9, 0 -// CHECK-NEXT: %12 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } %11(ptr %10, %"{{.*}}/runtime/internal/runtime.Slice" %1) -// CHECK-NEXT: %13 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %12, 0 -// CHECK-NEXT: %14 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %12, 1 -// CHECK-NEXT: %15 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %13, 0 -// CHECK-NEXT: %16 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %15, %"{{.*}}/runtime/internal/runtime.iface" %14, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %16 +// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %9, 0 +// CHECK-NEXT: %11 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @"main.(*nopCloser).Read", ptr %10) +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %9, 1 +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %9, 0 +// CHECK-NEXT: %14 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } %13(ptr %12, %"{{.*}}/runtime/internal/runtime.Slice" %1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %11) +// CHECK-NEXT: %15 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %14, 0 +// CHECK-NEXT: %16 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %14, 1 +// CHECK-NEXT: %17 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %15, 0 +// CHECK-NEXT: %18 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %17, %"{{.*}}/runtime/internal/runtime.iface" %16, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %18 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @main.nopCloserWriterTo.Close(%main.nopCloserWriterTo %0){{.*}} { @@ -647,14 +653,17 @@ func main() { // CHECK-NEXT: %8 = load ptr, ptr %7, align 8 // CHECK-NEXT: %9 = insertvalue { ptr, ptr } undef, ptr %8, 0 // CHECK-NEXT: %10 = insertvalue { ptr, ptr } %9, ptr %5, 1 -// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %10, 1 -// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %10, 0 -// CHECK-NEXT: %13 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } %12(ptr %11, %"{{.*}}/runtime/internal/runtime.Slice" %1) -// CHECK-NEXT: %14 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %13, 0 -// CHECK-NEXT: %15 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %13, 1 -// CHECK-NEXT: %16 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %14, 0 -// CHECK-NEXT: %17 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %16, %"{{.*}}/runtime/internal/runtime.iface" %15, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %17 +// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %10, 0 +// CHECK-NEXT: %12 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @main.nopCloserWriterTo.Read, ptr %11) +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %10, 1 +// CHECK-NEXT: %14 = extractvalue { ptr, ptr } %10, 0 +// CHECK-NEXT: %15 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } %14(ptr %13, %"{{.*}}/runtime/internal/runtime.Slice" %1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %12) +// CHECK-NEXT: %16 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %15, 0 +// CHECK-NEXT: %17 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %15, 1 +// CHECK-NEXT: %18 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %16, 0 +// CHECK-NEXT: %19 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %18, %"{{.*}}/runtime/internal/runtime.iface" %17, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %19 // CHECK-NEXT: } // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @main.nopCloserWriterTo.WriteTo(%main.nopCloserWriterTo %0, %"{{.*}}/runtime/internal/runtime.iface" %1){{.*}} { @@ -689,14 +698,14 @@ func main() { // CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %23 // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %5, %"{{.*}}/runtime/internal/runtime.String" { ptr @54, i64 49 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 7 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %5, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 49 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 7 }) // CHECK-NEXT: unreachable // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @"main.(*nopCloserWriterTo).Close"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = icmp eq ptr %0, null -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @55, i64 58 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @17, i64 5 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 58 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 5 }) // CHECK-NEXT: %2 = load %main.nopCloserWriterTo, ptr %0, align 8 // CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.iface" @main.nopCloserWriterTo.Close(%main.nopCloserWriterTo %2) // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %3 @@ -712,20 +721,23 @@ func main() { // CHECK-NEXT: %7 = load ptr, ptr %6, align 8 // CHECK-NEXT: %8 = insertvalue { ptr, ptr } undef, ptr %7, 0 // CHECK-NEXT: %9 = insertvalue { ptr, ptr } %8, ptr %4, 1 -// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %9, 1 -// CHECK-NEXT: %11 = extractvalue { ptr, ptr } %9, 0 -// CHECK-NEXT: %12 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } %11(ptr %10, %"{{.*}}/runtime/internal/runtime.Slice" %1) -// CHECK-NEXT: %13 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %12, 0 -// CHECK-NEXT: %14 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %12, 1 -// CHECK-NEXT: %15 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %13, 0 -// CHECK-NEXT: %16 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %15, %"{{.*}}/runtime/internal/runtime.iface" %14, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %16 +// CHECK-NEXT: %10 = extractvalue { ptr, ptr } %9, 0 +// CHECK-NEXT: %11 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrameAlias"(ptr @"main.(*nopCloserWriterTo).Read", ptr %10) +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %9, 1 +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %9, 0 +// CHECK-NEXT: %14 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } %13(ptr %12, %"{{.*}}/runtime/internal/runtime.Slice" %1) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %11) +// CHECK-NEXT: %15 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %14, 0 +// CHECK-NEXT: %16 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %14, 1 +// CHECK-NEXT: %17 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %15, 0 +// CHECK-NEXT: %18 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %17, %"{{.*}}/runtime/internal/runtime.iface" %16, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %18 // CHECK-NEXT: } // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*nopCloserWriterTo).WriteTo"(ptr %0, %"{{.*}}/runtime/internal/runtime.iface" %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = icmp eq ptr %0, null -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %2, %"{{.*}}/runtime/internal/runtime.String" { ptr @55, i64 58 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 7 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicWrapNilPointer"(i1 %2, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 58 }, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 7 }) // CHECK-NEXT: %3 = load %main.nopCloserWriterTo, ptr %0, align 8 // CHECK-NEXT: %4 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @main.nopCloserWriterTo.WriteTo(%main.nopCloserWriterTo %3, %"{{.*}}/runtime/internal/runtime.iface" %1) // CHECK-NEXT: %5 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4, 0 @@ -801,7 +813,7 @@ func main() { // CHECK-NEXT: br i1 %3, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @56, i64 37 }) +// CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 37 }) // CHECK-NEXT: %5 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } { i64 0, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %4, 1 // CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %5 // CHECK-EMPTY: @@ -987,12 +999,12 @@ func main() { // CHECK-NEXT: br i1 %15, label %_llgo_5, label %_llgo_7 // CHECK-EMPTY: // CHECK-NEXT: _llgo_7: ; preds = %_llgo_6 -// CHECK-NEXT: %16 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @57, i64 34 }) +// CHECK-NEXT: %16 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 34 }) // CHECK-NEXT: %17 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } { i64 0, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %16, 1 // CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %17 // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_1 -// CHECK-NEXT: %18 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @58, i64 37 }) +// CHECK-NEXT: %18 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 37 }) // CHECK-NEXT: %19 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } { i64 0, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %18, 1 // CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %19 // CHECK-EMPTY: @@ -1020,7 +1032,7 @@ func main() { // CHECK-NEXT: br i1 %3, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @59, i64 48 }) +// CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 48 }) // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %4 // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -1042,7 +1054,7 @@ func main() { // CHECK-NEXT: br i1 %3, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @60, i64 49 }) +// CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 49 }) // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %4 // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 @@ -1052,7 +1064,7 @@ func main() { // CHECK-NEXT: br i1 %7, label %_llgo_3, label %_llgo_4 // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 -// CHECK-NEXT: %8 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @61, i64 62 }) +// CHECK-NEXT: %8 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 62 }) // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %8 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 @@ -1096,7 +1108,7 @@ func main() { // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 // CHECK-NEXT: %20 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @62, i64 48 }, ptr %20, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 48 }, ptr %20, align 8 // CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %20, 1 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %21) // CHECK-NEXT: unreachable diff --git a/cl/_testgo/recoverthenpanic/in.go b/cl/_testgo/recoverthenpanic/in.go index 6d1364b14f..f4fe1c94e9 100644 --- a/cl/_testgo/recoverthenpanic/in.go +++ b/cl/_testgo/recoverthenpanic/in.go @@ -1,124 +1,126 @@ // LITTEST package main -// CHECK: @0 = private unnamed_addr constant [19 x i8] c"will panic in defer", align 1 -// CHECK: @1 = private unnamed_addr constant [3 x i8] c"end", align 1 -// CHECK: @2 = private unnamed_addr constant [13 x i8] c"panic in main", align 1 +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [19 x i8] c"will panic in defer", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [3 x i8] c"end", align 1{{$}} +// CHECK: {{^}}@{{[0-9]+}} = private unnamed_addr constant [13 x i8] c"panic in main", align 1{{$}} + +func End() { + if recovered := recover(); recovered != nil { + // Record but don't stop the panic. + defer panic(recovered) + println("will panic in defer") + } + println("end") +} + +func main() { + defer End() + panic("panic in main") +} // CHECK-LABEL: define void @main.End(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %1 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %0, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: %2 = xor i1 %1, true -// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %4 = alloca i8, i64 {{.*}}, align 1 -// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) -// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 0 -// CHECK-NEXT: store ptr %4, ptr %6, align 8 -// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 1 -// CHECK-NEXT: store i64 0, ptr %7, align 8 -// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 2 -// CHECK-NEXT: store ptr %3, ptr %8, align 8 -// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 -// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_5), ptr %9, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %5) -// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 1 -// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 3 -// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 4 -// CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, i32 0, i32 5 -// CHECK-NEXT: store ptr null, ptr %13, align 8 -// CHECK-NEXT: %14 = call i32 @{{.*}}sigsetjmp(ptr %4, i32 0) -// CHECK-NEXT: %15 = icmp eq i32 %14, 0 -// CHECK-NEXT: br i1 %15, label %_llgo_4, label %_llgo_7 +// CHECK-NEXT: %0 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @main.End, ptr %0) +// CHECK-NEXT: %1 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %0) +// CHECK-NEXT: %2 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %1, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: %3 = xor i1 %2, true +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() +// CHECK-NEXT: %5 = alloca i8, i64 {{.*}}, align 1 +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 0 +// CHECK-NEXT: store ptr %5, ptr %7, align 8 +// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %8, align 8 +// CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 2 +// CHECK-NEXT: store ptr %4, ptr %9, align 8 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 3 +// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_5), ptr %10, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %6) +// CHECK-NEXT: %11 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 1 +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 3 +// CHECK-NEXT: %13 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 4 +// CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, i32 0, i32 5 +// CHECK-NEXT: store ptr null, ptr %14, align 8 +// CHECK-NEXT: %15 = call i32 @{{(__)?}}sigsetjmp(ptr %5, i32 0) +// CHECK-NEXT: %16 = icmp eq i32 %15, 0 +// CHECK-NEXT: br i1 %16, label %_llgo_4, label %_llgo_7 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_4 -// CHECK-NEXT: %16 = load i64, ptr %10, align 8 -// CHECK-NEXT: %17 = or i64 %16, 1 -// CHECK-NEXT: store i64 %17, ptr %10, align 8 -// CHECK-NEXT: %18 = load ptr, ptr %13, align 8 -// CHECK-NEXT: %19 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) -// CHECK-NEXT: %20 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.eface" }, ptr %19, i32 0, i32 0 -// CHECK-NEXT: store ptr %18, ptr %20, align 8 -// CHECK-NEXT: %21 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.eface" }, ptr %19, i32 0, i32 1 -// CHECK-NEXT: store i64 0, ptr %21, align 8 -// CHECK-NEXT: %22 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.eface" }, ptr %19, i32 0, i32 2 -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %0, ptr %22, align 8 -// CHECK-NEXT: store ptr %19, ptr %13, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 19 }) +// CHECK-NEXT: %17 = load i64, ptr %11, align 8 +// CHECK-NEXT: %18 = or i64 %17, 1 +// CHECK-NEXT: store i64 %18, ptr %11, align 8 +// CHECK-NEXT: %19 = load ptr, ptr %14, align 8 +// CHECK-NEXT: %20 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 32) +// CHECK-NEXT: %21 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.eface" }, ptr %20, i32 0, i32 0 +// CHECK-NEXT: store ptr %19, ptr %21, align 8 +// CHECK-NEXT: %22 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.eface" }, ptr %20, i32 0, i32 1 +// CHECK-NEXT: store i64 0, ptr %22, align 8 +// CHECK-NEXT: %23 = getelementptr inbounds { ptr, i64, %"{{.*}}/runtime/internal/runtime.eface" }, ptr %20, i32 0, i32 2 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %1, ptr %23, align 8 +// CHECK-NEXT: store ptr %20, ptr %14, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 19 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: br label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_4 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @1, i64 3 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_8), ptr %12, align 8 +// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_8), ptr %13, align 8 // CHECK-NEXT: br label %_llgo_5 // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_6 // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: br i1 %3, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_7, %_llgo_2 -// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_6), ptr %11, align 8 -// CHECK-NEXT: %23 = load i64, ptr %10, align 8 -// CHECK-NEXT: %24 = and i64 %23, 1 -// CHECK-NEXT: %25 = icmp ne i64 %24, 0 -// CHECK-NEXT: br i1 %25, label %_llgo_9, label %_llgo_10 +// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_6), ptr %12, align 8 +// CHECK-NEXT: %24 = load i64, ptr %11, align 8 +// CHECK-NEXT: %25 = and i64 %24, 1 +// CHECK-NEXT: %26 = icmp ne i64 %25, 0 +// CHECK-NEXT: br i1 %26, label %_llgo_9, label %_llgo_10 // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_7, %_llgo_10 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %3) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %4) // CHECK-NEXT: br label %_llgo_3 // CHECK-EMPTY: // CHECK-NEXT: _llgo_7: ; preds = %_llgo_0 -// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_6), ptr %12, align 8 -// CHECK-NEXT: %26 = load ptr, ptr %11, align 8 -// CHECK-NEXT: indirectbr ptr %26, [label %_llgo_6, label %_llgo_5] +// CHECK-NEXT: store ptr blockaddress(@main.End, %_llgo_6), ptr %13, align 8 +// CHECK-NEXT: %27 = load ptr, ptr %12, align 8 +// CHECK-NEXT: indirectbr ptr %27, [label %_llgo_6, label %_llgo_5] // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_10 // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_9: ; preds = %_llgo_5 -// CHECK-NEXT: %27 = load ptr, ptr %13, align 8 -// CHECK-NEXT: %28 = icmp ne ptr %27, null -// CHECK-NEXT: br i1 %28, label %_llgo_11, label %_llgo_12 +// CHECK-NEXT: %28 = load ptr, ptr %14, align 8 +// CHECK-NEXT: %29 = icmp ne ptr %28, null +// CHECK-NEXT: br i1 %29, label %_llgo_11, label %_llgo_12 // CHECK-EMPTY: // CHECK-NEXT: _llgo_10: ; preds = %_llgo_12, %_llgo_5 -// CHECK-NEXT: %29 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %5, align 8 -// CHECK-NEXT: %30 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %29, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %30) -// CHECK-NEXT: %31 = load ptr, ptr %12, align 8 -// CHECK-NEXT: indirectbr ptr %31, [label %_llgo_6, label %_llgo_8] +// CHECK-NEXT: %30 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %6, align 8 +// CHECK-NEXT: %31 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %30, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %31) +// CHECK-NEXT: %32 = load ptr, ptr %13, align 8 +// CHECK-NEXT: indirectbr ptr %32, [label %_llgo_6, label %_llgo_8] // CHECK-EMPTY: // CHECK-NEXT: _llgo_11: ; preds = %_llgo_9 -// CHECK-NEXT: %32 = load ptr, ptr %13, align 8 -// CHECK-NEXT: %33 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.eface" }, ptr %32, align 8 -// CHECK-NEXT: %34 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.eface" } %33, 0 -// CHECK-NEXT: store ptr %34, ptr %13, align 8 -// CHECK-NEXT: %35 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.eface" } %33, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %35) +// CHECK-NEXT: %33 = load ptr, ptr %14, align 8 +// CHECK-NEXT: %34 = load { ptr, i64, %"{{.*}}/runtime/internal/runtime.eface" }, ptr %33, align 8 +// CHECK-NEXT: %35 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.eface" } %34, 0 +// CHECK-NEXT: store ptr %35, ptr %14, align 8 +// CHECK-NEXT: %36 = extractvalue { ptr, i64, %"{{.*}}/runtime/internal/runtime.eface" } %34, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %33) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %36) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_12: ; preds = %_llgo_9 // CHECK-NEXT: br label %_llgo_10 // CHECK-NEXT: } -func End() { - if recovered := recover(); recovered != nil { - // Record but don't stop the panic. - defer panic(recovered) - println("will panic in defer") - } - println("end") -} - -func main() { - defer End() - panic("panic in main") -} - // CHECK-LABEL: define void @main.init(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = load i1, ptr @"main.init$guard", align 1 @@ -151,7 +153,7 @@ func main() { // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 4 // CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, i32 0, i32 5 // CHECK-NEXT: store ptr null, ptr %10, align 8 -// CHECK-NEXT: %11 = call i32 @{{.*}}sigsetjmp(ptr %1, i32 0) +// CHECK-NEXT: %11 = call i32 @{{(__)?}}sigsetjmp(ptr %1, i32 0) // CHECK-NEXT: %12 = icmp eq i32 %11, 0 // CHECK-NEXT: br i1 %12, label %_llgo_4, label %_llgo_5 // CHECK-EMPTY: @@ -161,26 +163,28 @@ func main() { // CHECK-NEXT: _llgo_2: ; preds = %_llgo_5 // CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %8, align 8 // CHECK-NEXT: %13 = load i64, ptr %7, align 8 +// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr @main.End) // CHECK-NEXT: call void @main.End() -// CHECK-NEXT: %14 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %14, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %15) -// CHECK-NEXT: %16 = load ptr, ptr %9, align 8 -// CHECK-NEXT: indirectbr ptr %16, [label %_llgo_3] +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %14) +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %2, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %15, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %16) +// CHECK-NEXT: %17 = load ptr, ptr %9, align 8 +// CHECK-NEXT: indirectbr ptr %17, [label %_llgo_3] // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_5, %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Rethrow"(ptr %0) // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 13 }, ptr %17, align 8 -// CHECK-NEXT: %18 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %17, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %18) +// CHECK-NEXT: %18 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %18, align 8 +// CHECK-NEXT: %19 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %18, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %19) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_0 // CHECK-NEXT: store ptr blockaddress(@main.main, %_llgo_3), ptr %9, align 8 -// CHECK-NEXT: %19 = load ptr, ptr %8, align 8 -// CHECK-NEXT: indirectbr ptr %19, [label %_llgo_3, label %_llgo_2] +// CHECK-NEXT: %20 = load ptr, ptr %8, align 8 +// CHECK-NEXT: indirectbr ptr %20, [label %_llgo_3, label %_llgo_2] // CHECK-NEXT: } diff --git a/cl/_testgo/reflectconv/in.go b/cl/_testgo/reflectconv/in.go index c1902c3320..fd98e51395 100644 --- a/cl/_testgo/reflectconv/in.go +++ b/cl/_testgo/reflectconv/in.go @@ -2267,7 +2267,7 @@ func shouldPanic(expect string, f func()) { // CHECK-NEXT: %346 = call %reflect.Value %__llgo_funcval_code45(ptr {{(nest|swiftself)}} %344, %"{{.*}}/runtime/internal/runtime.eface" %343) // CHECK-NEXT: store %reflect.Value %339, ptr %333, align 8 // CHECK-NEXT: store %reflect.Value %346, ptr %340, align 8 -// CHECK-NEXT: %347 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 23 +// CHECK-NEXT: %347 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 {{(21|23)}} // CHECK-NEXT: %348 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %347, i32 0, i32 0 // CHECK-NEXT: %349 = load { ptr, ptr }, ptr @main.V, align 8 // CHECK-NEXT: %350 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 4) @@ -2435,7 +2435,7 @@ func shouldPanic(expect string, f func()) { // CHECK-NEXT: %466 = call %reflect.Value %__llgo_funcval_code61(ptr {{(nest|swiftself)}} %464, %"{{.*}}/runtime/internal/runtime.eface" %463) // CHECK-NEXT: store %reflect.Value %459, ptr %453, align 8 // CHECK-NEXT: store %reflect.Value %466, ptr %460, align 8 -// CHECK-NEXT: %467 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 31 +// CHECK-NEXT: %467 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 {{(28|31)}} // CHECK-NEXT: %468 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %467, i32 0, i32 0 // CHECK-NEXT: %469 = load { ptr, ptr }, ptr @main.V, align 8 // CHECK-NEXT: %470 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) @@ -9415,7 +9415,7 @@ func shouldPanic(expect string, f func()) { // CHECK-NEXT: %5471 = call %reflect.Value %__llgo_funcval_code734(ptr {{(nest|swiftself)}} %5469, %"{{.*}}/runtime/internal/runtime.eface" %5468) // CHECK-NEXT: %5472 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5464, i32 0, i32 1 // CHECK-NEXT: %5473 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 40) -// CHECK-NEXT: %5474 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw", ptr @"*_llgo_bytes.Buffer") +// CHECK-NEXT: %5474 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface${{[-A-Za-z0-9_]+}}", ptr @"*_llgo_bytes.Buffer") // CHECK-NEXT: %5475 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %5474, 0 // CHECK-NEXT: %5476 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %5475, ptr %5473, 1 // CHECK-NEXT: %5477 = call %reflect.Value @main.ReaderV(%"{{.*}}/runtime/internal/runtime.iface" %5476) @@ -9424,13 +9424,13 @@ func shouldPanic(expect string, f func()) { // CHECK-NEXT: %5478 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %1, i64 369 // CHECK-NEXT: %5479 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5478, i32 0, i32 0 // CHECK-NEXT: %5480 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 40) -// CHECK-NEXT: %5481 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$Zutt7i_AwOTtBOIzyS7ZA5vhcNcbk0kRAoRC98HJDos", ptr @"*_llgo_bytes.Buffer") +// CHECK-NEXT: %5481 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface${{[-A-Za-z0-9_]+}}", ptr @"*_llgo_bytes.Buffer") // CHECK-NEXT: %5482 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %5481, 0 // CHECK-NEXT: %5483 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %5482, ptr %5480, 1 // CHECK-NEXT: %5484 = call %reflect.Value @main.ReadWriterV(%"{{.*}}/runtime/internal/runtime.iface" %5483) // CHECK-NEXT: %5485 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5478, i32 0, i32 1 // CHECK-NEXT: %5486 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 40) -// CHECK-NEXT: %5487 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$uycIKA3bbxRhudEjW1hHKWKdLqHQsCVy8NdW1bkQmNw", ptr @"*_llgo_bytes.Buffer") +// CHECK-NEXT: %5487 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface${{[-A-Za-z0-9_]+}}", ptr @"*_llgo_bytes.Buffer") // CHECK-NEXT: %5488 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %5487, 0 // CHECK-NEXT: %5489 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %5488, ptr %5486, 1 // CHECK-NEXT: %5490 = call %reflect.Value @main.ReaderV(%"{{.*}}/runtime/internal/runtime.iface" %5489) @@ -9447,7 +9447,7 @@ func shouldPanic(expect string, f func()) { // CHECK-NEXT: %5498 = call %reflect.Value %__llgo_funcval_code735(ptr {{(nest|swiftself)}} %5496, %"{{.*}}/runtime/internal/runtime.eface" %5495) // CHECK-NEXT: %5499 = getelementptr inbounds { %reflect.Value, %reflect.Value }, ptr %5491, i32 0, i32 1 // CHECK-NEXT: %5500 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 40) -// CHECK-NEXT: %5501 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$Zutt7i_AwOTtBOIzyS7ZA5vhcNcbk0kRAoRC98HJDos", ptr @"*_llgo_bytes.Buffer") +// CHECK-NEXT: %5501 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface${{[-A-Za-z0-9_]+}}", ptr @"*_llgo_bytes.Buffer") // CHECK-NEXT: %5502 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %5501, 0 // CHECK-NEXT: %5503 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %5502, ptr %5500, 1 // CHECK-NEXT: %5504 = call %reflect.Value @main.ReadWriterV(%"{{.*}}/runtime/internal/runtime.iface" %5503) @@ -9481,7 +9481,7 @@ func shouldPanic(expect string, f func()) { // CHECK-NEXT: store ptr %2, ptr %4, align 8 // CHECK-NEXT: %5 = insertvalue { ptr, ptr } { ptr @"main.shouldPanic$1", ptr undef }, ptr %3, 1 // CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.GetThreadDefer"() -// CHECK-NEXT: %7 = alloca i8 +// CHECK-NEXT: %7 = alloca i8, i64 {{.*}}, align 1 // CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 48) // CHECK-NEXT: %9 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, i32 0, i32 0 // CHECK-NEXT: store ptr %7, ptr %9, align 8 @@ -9547,136 +9547,141 @@ func shouldPanic(expect string, f func()) { // CHECK-NEXT: store ptr %32, ptr %16, align 8 // CHECK-NEXT: %33 = extractvalue { ptr, i64, { ptr, ptr } } %31, 2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.FreeDeferNode"(ptr %30) -// CHECK-NEXT: %34 = extractvalue { ptr, ptr } %33, 1 -// CHECK-NEXT: %35 = extractvalue { ptr, ptr } %33, 0 -// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %35) -// CHECK-NEXT: call void %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %34) +// CHECK-NEXT: %34 = extractvalue { ptr, ptr } %33, 0 +// CHECK-NEXT: %35 = call ptr @"{{.*}}/runtime/internal/runtime.StartRecoverFrame"(ptr %34) +// CHECK-NEXT: %36 = extractvalue { ptr, ptr } %33, 1 +// CHECK-NEXT: %37 = extractvalue { ptr, ptr } %33, 0 +// CHECK-NEXT: %__llgo_funcval_code1 = call ptr asm "", "=r,0"(ptr %37) +// CHECK-NEXT: call void %__llgo_funcval_code1(ptr {{(nest|swiftself)}} %36) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.EndRecoverFrame"(ptr %35) // CHECK-NEXT: br label %_llgo_8 // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_7, %_llgo_2 -// CHECK-NEXT: %36 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, align 8 -// CHECK-NEXT: %37 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %36, 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %37) -// CHECK-NEXT: %38 = load ptr, ptr %15, align 8 -// CHECK-NEXT: indirectbr ptr %38, [label %_llgo_3, label %_llgo_6] +// CHECK-NEXT: %38 = load %"{{.*}}/runtime/internal/runtime.Defer", ptr %8, align 8 +// CHECK-NEXT: %39 = extractvalue %"{{.*}}/runtime/internal/runtime.Defer" %38, 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.SetThreadDefer"(ptr %39) +// CHECK-NEXT: %40 = load ptr, ptr %15, align 8 +// CHECK-NEXT: indirectbr ptr %40, [label %_llgo_3, label %_llgo_6] // CHECK-NEXT: } // CHECK-LABEL: define void @"main.shouldPanic$1"(ptr {{(nest|swiftself)}} %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 -// CHECK-NEXT: %2 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"() -// CHECK-NEXT: %3 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %2, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) -// CHECK-NEXT: br i1 %3, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %2 = alloca i8, align 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.BindRecoverFrame"(ptr @"main.shouldPanic$1", ptr %2) +// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.eface" @"{{.*}}/runtime/internal/runtime.Recover"(ptr %2) +// CHECK-NEXT: %4 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %3, %"{{.*}}/runtime/internal/runtime.eface" zeroinitializer) +// CHECK-NEXT: br i1 %4, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %4, align 8 -// CHECK-NEXT: %5 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %4, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %5) +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 13 }, ptr %5, align 8 +// CHECK-NEXT: %6 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %5, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %6) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %6 = extractvalue { ptr } %1, 0 -// CHECK-NEXT: %7 = load %"{{.*}}/runtime/internal/runtime.String", ptr %6, align 8 -// CHECK-NEXT: %8 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %7, %"{{.*}}/runtime/internal/runtime.String" zeroinitializer) -// CHECK-NEXT: %9 = xor i1 %8, true -// CHECK-NEXT: br i1 %9, label %_llgo_3, label %_llgo_4 +// CHECK-NEXT: %7 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %8 = load %"{{.*}}/runtime/internal/runtime.String", ptr %7, align 8 +// CHECK-NEXT: %9 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %8, %"{{.*}}/runtime/internal/runtime.String" zeroinitializer) +// CHECK-NEXT: %10 = xor i1 %9, true +// CHECK-NEXT: br i1 %10, label %_llgo_3, label %_llgo_4 // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 -// CHECK-NEXT: %10 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %2, 0 -// CHECK-NEXT: %11 = icmp eq ptr %10, @_llgo_string -// CHECK-NEXT: br i1 %11, label %_llgo_13, label %_llgo_14 +// CHECK-NEXT: %11 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %3, 0 +// CHECK-NEXT: %12 = icmp eq ptr %11, @_llgo_string +// CHECK-NEXT: br i1 %12, label %_llgo_13, label %_llgo_14 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_11, %_llgo_2 // CHECK-NEXT: ret void // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_8, %_llgo_6 -// CHECK-NEXT: %12 = phi %"{{.*}}/runtime/internal/runtime.String" [ %43, %_llgo_6 ], [ %16, %_llgo_8 ] -// CHECK-NEXT: %13 = call i1 @strings.HasPrefix(%"{{.*}}/runtime/internal/runtime.String" %12, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 7 }) -// CHECK-NEXT: br i1 %13, label %_llgo_11, label %_llgo_10 +// CHECK-NEXT: %13 = phi %"{{.*}}/runtime/internal/runtime.String" [ %44, %_llgo_6 ], [ %17, %_llgo_8 ] +// CHECK-NEXT: %14 = call i1 @strings.HasPrefix(%"{{.*}}/runtime/internal/runtime.String" %13, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 7 }) +// CHECK-NEXT: br i1 %14, label %_llgo_11, label %_llgo_10 // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_15 // CHECK-NEXT: br label %_llgo_5 // CHECK-EMPTY: // CHECK-NEXT: _llgo_7: ; preds = %_llgo_15 -// CHECK-NEXT: %14 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %2, 0 -// CHECK-NEXT: %15 = icmp eq ptr %14, @"*_llgo_reflect.ValueError" -// CHECK-NEXT: br i1 %15, label %_llgo_16, label %_llgo_17 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %3, 0 +// CHECK-NEXT: %16 = icmp eq ptr %15, @"*_llgo_reflect.ValueError" +// CHECK-NEXT: br i1 %16, label %_llgo_16, label %_llgo_17 // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_18 -// CHECK-NEXT: %16 = call %"{{.*}}/runtime/internal/runtime.String" @"reflect.(*ValueError).Error"(ptr %49) +// CHECK-NEXT: %17 = call %"{{.*}}/runtime/internal/runtime.String" @"reflect.(*ValueError).Error"(ptr %50) // CHECK-NEXT: br label %_llgo_5 // CHECK-EMPTY: // CHECK-NEXT: _llgo_9: ; preds = %_llgo_18 -// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) -// CHECK-NEXT: %18 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %17, i64 0 -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %2, ptr %18, align 8 -// CHECK-NEXT: %19 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %17, 0 -// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %19, i64 1, 1 -// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %20, i64 1, 2 -// CHECK-NEXT: %22 = call %"{{.*}}/runtime/internal/runtime.String" @fmt.Sprintf(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 32 }, %"{{.*}}/runtime/internal/runtime.Slice" %21) -// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %22, ptr %23, align 8 -// CHECK-NEXT: %24 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %23, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %24) +// CHECK-NEXT: %18 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %19 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.eface", ptr %18, i64 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %3, ptr %19, align 8 +// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %18, 0 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %20, i64 1, 1 +// CHECK-NEXT: %22 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %21, i64 1, 2 +// CHECK-NEXT: %23 = call %"{{.*}}/runtime/internal/runtime.String" @fmt.Sprintf(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 32 }, %"{{.*}}/runtime/internal/runtime.Slice" %22) +// CHECK-NEXT: %24 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %23, ptr %24, align 8 +// CHECK-NEXT: %25 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %24, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %25) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_10: ; preds = %_llgo_5 -// CHECK-NEXT: %25 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 44 }, %"{{.*}}/runtime/internal/runtime.String" %12) -// CHECK-NEXT: %26 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %25, ptr %26, align 8 -// CHECK-NEXT: %27 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %26, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %27) +// CHECK-NEXT: %26 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 44 }, %"{{.*}}/runtime/internal/runtime.String" %13) +// CHECK-NEXT: %27 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %26, ptr %27, align 8 +// CHECK-NEXT: %28 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %27, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %28) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_11: ; preds = %_llgo_5 -// CHECK-NEXT: %28 = extractvalue { ptr } %1, 0 -// CHECK-NEXT: %29 = load %"{{.*}}/runtime/internal/runtime.String", ptr %28, align 8 -// CHECK-NEXT: %30 = call i1 @strings.Contains(%"{{.*}}/runtime/internal/runtime.String" %12, %"{{.*}}/runtime/internal/runtime.String" %29) -// CHECK-NEXT: br i1 %30, label %_llgo_4, label %_llgo_12 +// CHECK-NEXT: %29 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %30 = load %"{{.*}}/runtime/internal/runtime.String", ptr %29, align 8 +// CHECK-NEXT: %31 = call i1 @strings.Contains(%"{{.*}}/runtime/internal/runtime.String" %13, %"{{.*}}/runtime/internal/runtime.String" %30) +// CHECK-NEXT: br i1 %31, label %_llgo_4, label %_llgo_12 // CHECK-EMPTY: // CHECK-NEXT: _llgo_12: ; preds = %_llgo_11 -// CHECK-NEXT: %31 = extractvalue { ptr } %1, 0 -// CHECK-NEXT: %32 = load %"{{.*}}/runtime/internal/runtime.String", ptr %31, align 8 -// CHECK-NEXT: %33 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 31 }, %"{{.*}}/runtime/internal/runtime.String" %32) -// CHECK-NEXT: %34 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %33, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) -// CHECK-NEXT: %35 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %34, %"{{.*}}/runtime/internal/runtime.String" %12) -// CHECK-NEXT: %36 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %35, ptr %36, align 8 -// CHECK-NEXT: %37 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %36, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %37) +// CHECK-NEXT: %32 = extractvalue { ptr } %1, 0 +// CHECK-NEXT: %33 = load %"{{.*}}/runtime/internal/runtime.String", ptr %32, align 8 +// CHECK-NEXT: %34 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 31 }, %"{{.*}}/runtime/internal/runtime.String" %33) +// CHECK-NEXT: %35 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %34, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{[0-9]+}}, i64 3 }) +// CHECK-NEXT: %36 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %35, %"{{.*}}/runtime/internal/runtime.String" %13) +// CHECK-NEXT: %37 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" %36, ptr %37, align 8 +// CHECK-NEXT: %38 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %37, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %38) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_13: ; preds = %_llgo_3 -// CHECK-NEXT: %38 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %2, 1 -// CHECK-NEXT: %39 = load %"{{.*}}/runtime/internal/runtime.String", ptr %38, align 8 -// CHECK-NEXT: %40 = insertvalue { %"{{.*}}/runtime/internal/runtime.String", i1 } undef, %"{{.*}}/runtime/internal/runtime.String" %39, 0 -// CHECK-NEXT: %41 = insertvalue { %"{{.*}}/runtime/internal/runtime.String", i1 } %40, i1 true, 1 +// CHECK-NEXT: %39 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %3, 1 +// CHECK-NEXT: %40 = load %"{{.*}}/runtime/internal/runtime.String", ptr %39, align 8 +// CHECK-NEXT: %41 = insertvalue { %"{{.*}}/runtime/internal/runtime.String", i1 } undef, %"{{.*}}/runtime/internal/runtime.String" %40, 0 +// CHECK-NEXT: %42 = insertvalue { %"{{.*}}/runtime/internal/runtime.String", i1 } %41, i1 true, 1 // CHECK-NEXT: br label %_llgo_15 // CHECK-EMPTY: // CHECK-NEXT: _llgo_14: ; preds = %_llgo_3 // CHECK-NEXT: br label %_llgo_15 // CHECK-EMPTY: // CHECK-NEXT: _llgo_15: ; preds = %_llgo_14, %_llgo_13 -// CHECK-NEXT: %42 = phi { %"{{.*}}/runtime/internal/runtime.String", i1 } [ %41, %_llgo_13 ], [ zeroinitializer, %_llgo_14 ] -// CHECK-NEXT: %43 = extractvalue { %"{{.*}}/runtime/internal/runtime.String", i1 } %42, 0 -// CHECK-NEXT: %44 = extractvalue { %"{{.*}}/runtime/internal/runtime.String", i1 } %42, 1 -// CHECK-NEXT: br i1 %44, label %_llgo_6, label %_llgo_7 +// CHECK-NEXT: %43 = phi { %"{{.*}}/runtime/internal/runtime.String", i1 } [ %42, %_llgo_13 ], [ zeroinitializer, %_llgo_14 ] +// CHECK-NEXT: %44 = extractvalue { %"{{.*}}/runtime/internal/runtime.String", i1 } %43, 0 +// CHECK-NEXT: %45 = extractvalue { %"{{.*}}/runtime/internal/runtime.String", i1 } %43, 1 +// CHECK-NEXT: br i1 %45, label %_llgo_6, label %_llgo_7 // CHECK-EMPTY: // CHECK-NEXT: _llgo_16: ; preds = %_llgo_7 -// CHECK-NEXT: %45 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %2, 1 -// CHECK-NEXT: %46 = insertvalue { ptr, i1 } undef, ptr %45, 0 -// CHECK-NEXT: %47 = insertvalue { ptr, i1 } %46, i1 true, 1 +// CHECK-NEXT: %46 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %3, 1 +// CHECK-NEXT: %47 = insertvalue { ptr, i1 } undef, ptr %46, 0 +// CHECK-NEXT: %48 = insertvalue { ptr, i1 } %47, i1 true, 1 // CHECK-NEXT: br label %_llgo_18 // CHECK-EMPTY: // CHECK-NEXT: _llgo_17: ; preds = %_llgo_7 // CHECK-NEXT: br label %_llgo_18 // CHECK-EMPTY: // CHECK-NEXT: _llgo_18: ; preds = %_llgo_17, %_llgo_16 -// CHECK-NEXT: %48 = phi { ptr, i1 } [ %47, %_llgo_16 ], [ zeroinitializer, %_llgo_17 ] -// CHECK-NEXT: %49 = extractvalue { ptr, i1 } %48, 0 -// CHECK-NEXT: %50 = extractvalue { ptr, i1 } %48, 1 -// CHECK-NEXT: br i1 %50, label %_llgo_8, label %_llgo_9 +// CHECK-NEXT: %49 = phi { ptr, i1 } [ %48, %_llgo_16 ], [ zeroinitializer, %_llgo_17 ] +// CHECK-NEXT: %50 = extractvalue { ptr, i1 } %49, 0 +// CHECK-NEXT: %51 = extractvalue { ptr, i1 } %49, 1 +// CHECK-NEXT: br i1 %51, label %_llgo_8, label %_llgo_9 // CHECK-NEXT: } // CHECK-LABEL: define void @"main.(*testingT).Errorf"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" %1, %"{{.*}}/runtime/internal/runtime.Slice" %2){{.*}} { diff --git a/cl/cgo_test.go b/cl/cgo_test.go index 8ba0838340..289b68a809 100644 --- a/cl/cgo_test.go +++ b/cl/cgo_test.go @@ -207,6 +207,47 @@ func findStaticCall(t *testing.T, fn *gossa.Function, name string) *gossa.Call { return nil } +func TestRecoverCallClassificationHelpers(t *testing.T) { + if functionUsesRecover(nil) { + t.Fatal("nil function should not report recover use") + } + + ssaPkg, _, _ := buildGoSSAPkg(t, ` +package foo + +func usesRecover() { + recover() +} + +func plain() {} +`) + usesRecover := ssaPkg.Members["usesRecover"].(*gossa.Function) + plain := ssaPkg.Members["plain"].(*gossa.Function) + ctx := &context{} + + if !functionUsesRecover(usesRecover) { + t.Fatal("usesRecover should report direct recover use") + } + if functionUsesRecover(plain) { + t.Fatal("plain should not report recover use") + } + if !ctx.callMayRecover(usesRecover) { + t.Fatal("function using recover should be recover-capable") + } + if ctx.callMayRecover(plain) { + t.Fatal("plain static function should not be recover-capable") + } + if !ctx.callMayRecover(&gossa.MakeClosure{}) { + t.Fatal("unknown closure target should conservatively be recover-capable") + } + if !ctx.callMayRecover(&gossa.Call{}) { + t.Fatal("function value returned by a call should conservatively be recover-capable") + } + if !ctx.callMayRecover(nil) { + t.Fatal("unknown call value should conservatively be recover-capable") + } +} + func TestCgoCgocall_InitArgsFromParams(t *testing.T) { ssaPkg, _, _ := buildGoSSAPkg(t, ` package foo diff --git a/cl/compile.go b/cl/compile.go index 909f89b939..43c9cf94e6 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -213,6 +213,7 @@ type context struct { pcLineSeq uint64 options Options optionsSet bool + recoverSlots map[*ssa.Alloc]none patches Patches blkInfos []blocks.Info @@ -658,12 +659,16 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun noInlineDirective := hasNoInlineDirective(f) runtimeStackNoInline := needsRuntimeStackNoInline(pkgTypes, f) pcLineNoInline := p.needsPCLineNoInline(f) - if disableInline || noInlineDirective || runtimeStackNoInline || pcLineNoInline { + usesRecover := functionUsesRecover(f) + if disableInline || noInlineDirective || runtimeStackNoInline || pcLineNoInline || usesRecover { fn.Inline(llssa.NoInline) } - if noInlineDirective || runtimeStackNoInline || pcLineNoInline { + if noInlineDirective || runtimeStackNoInline || pcLineNoInline || usesRecover { fn.DisableTailCalls() } + if functionMayRecover(f) { + fn.Expr = fn.Expr.MarkMayRecover() + } p.funcs[f] = fn isCgo := isCgoExternSymbol(f) if nblk := len(f.Blocks); nblk > 0 { @@ -701,14 +706,21 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun p.inits = append(p.inits, func() { oldFn, oldGoFn, oldMethodNilDerefChecks, oldCallerFrameMark := p.fn, p.goFn, p.methodNilDerefChecks, p.callerFrameMark oldLocalityFunction := p.locality.function + oldRecoverSlots := p.recoverSlots p.fn = fn p.goFn = f p.callerFrameMark = llssa.Nil p.locality.function = localityFunction{} p.state = state // restore pkgState when compiling funcBody + if f.Recover != nil { + p.recoverSlots = make(map[*ssa.Alloc]none) + } else { + p.recoverSlots = nil + } defer func() { p.fn, p.goFn, p.methodNilDerefChecks, p.callerFrameMark = oldFn, oldGoFn, oldMethodNilDerefChecks, oldCallerFrameMark p.locality.function = oldLocalityFunction + p.recoverSlots = oldRecoverSlots }() p.phis = nil if dbgSymsEnabled { @@ -939,6 +951,9 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do var instrs = block.Instrs[n:] var ret = fn.Block(block.Index) b.SetBlock(ret) + if block.Index == 0 && functionUsesRecover(block.Parent()) { + b.BindRecoverFrame() + } if block.Index == 0 { p.enterExportedLocalContext(b) } @@ -1221,6 +1236,29 @@ func (p *context) syntheticMakeSliceCap(v *ssa.Slice) (llssa.Expr, bool) { return p.prog.IntVal(uint64(arr.Len()), p.prog.Int()), true } +func (p *context) markRecoverSlot(v *ssa.Alloc) { + if p.recoverSlots == nil || v.Heap { + return + } + p.recoverSlots[v] = none{} +} + +func (p *context) isRecoverSlotAddr(v ssa.Value) bool { + if p.recoverSlots == nil { + return false + } + switch v := v.(type) { + case *ssa.Alloc: + _, ok := p.recoverSlots[v] + return ok + case *ssa.FieldAddr: + return p.isRecoverSlotAddr(v.X) + case *ssa.IndexAddr: + return p.isRecoverSlotAddr(v.X) + } + return false +} + func isAllocVargs(ctx *context, v *ssa.Alloc) bool { refs, ok := nonDebugReferrers(v) if !ok || len(refs) == 0 { @@ -1410,6 +1448,9 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue } } ret = b.UnOp(v.Op, x) + if v.Op == token.MUL && p.isRecoverSlotAddr(v.X) { + ret = ret.SetVolatile(true) + } } case *ssa.ChangeType: t := v.Type() @@ -1445,6 +1486,10 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue elem := p.type_(t.Elem(), llssa.InGo) ret = b.Alloc(elem, v.Heap) p.debugAlloc(b, v, ret) + p.markRecoverSlot(v) + if p.isRecoverSlotAddr(v) { + b.Store(ret, p.prog.Zero(elem)).SetVolatile(true) + } case *ssa.IndexAddr: vx := v.X if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs index @@ -1801,7 +1846,10 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) { } ptr := p.compileValue(b, va) val := p.compileValue(b, v.Val) - b.Store(ptr, val) + store := b.Store(ptr, val) + if p.isRecoverSlotAddr(va) { + store.SetVolatile(true) + } case *ssa.Jump: jmpb := p.jumpTo(v) b.Jump(jmpb) @@ -1898,6 +1946,68 @@ func (p *context) getLocalVariable(b llssa.Builder, fn *ssa.Function, v *types.V return div } +func functionUsesRecover(fn *ssa.Function) bool { + if fn == nil { + return false + } + for _, block := range fn.Blocks { + for _, instr := range block.Instrs { + call, ok := instr.(ssa.CallInstruction) + if !ok { + continue + } + builtin, ok := call.Common().Value.(*ssa.Builtin) + if ok && builtin.Name() == "recover" { + return true + } + } + } + return false +} + +func isRecoverTransparentWrapper(fn *ssa.Function) bool { + if fn == nil { + return false + } + return strings.HasPrefix(fn.Synthetic, "wrapper for ") || + strings.HasPrefix(fn.Synthetic, "thunk for ") || + strings.HasPrefix(fn.Synthetic, "bound method wrapper for ") +} + +func functionMayRecover(fn *ssa.Function) bool { + return functionMayRecoverSeen(fn, make(map[*ssa.Function]bool)) +} + +func functionMayRecoverSeen(fn *ssa.Function, seen map[*ssa.Function]bool) bool { + if fn == nil || seen[fn] { + return false + } + seen[fn] = true + if functionUsesRecover(fn) { + return true + } + if !isRecoverTransparentWrapper(fn) { + return false + } + for _, block := range fn.Blocks { + for _, instr := range block.Instrs { + call, ok := instr.(ssa.CallInstruction) + if !ok { + continue + } + common := call.Common() + if common.Method != nil { + // An interface wrapper can dispatch to a recover-capable method. + return true + } + if functionMayRecoverSeen(common.StaticCallee(), seen) { + return true + } + } + } + return false +} + func (p *context) compileFunction(v *ssa.Function) (goFn llssa.Function, pyFn llssa.PyObjRef, kind int) { // TODO(xsw) v.Pkg == nil: means auto generated function? if v.Pkg == p.goPkg || v.Pkg == nil { diff --git a/cl/instr.go b/cl/instr.go index 818e89c322..7aec85135a 100644 --- a/cl/instr.go +++ b/cl/instr.go @@ -1805,12 +1805,39 @@ func (p *context) deferStackOwner(fn *ssa.Function) llssa.Function { return owner } -func (p *context) emitDo(b llssa.Builder, act llssa.DoAction, ds *explicitDeferStack, fn llssa.Expr, buildCall func(llssa.Builder, llssa.Expr, ...llssa.Expr) llssa.Expr, args ...llssa.Expr) llssa.Expr { +func (p *context) emitDo(b llssa.Builder, act llssa.DoAction, ds *explicitDeferStack, mayRecover bool, fn llssa.Expr, buildCall func(llssa.Builder, llssa.Expr, ...llssa.Expr) llssa.Expr, args ...llssa.Expr) llssa.Expr { if ds != nil { - b.DeferTo(ds.owner, ds.stack, fn, buildCall, args...) + b.DeferToRecover(ds.owner, ds.stack, mayRecover, fn, buildCall, args...) return llssa.Nil } - return b.Do(act, fn, buildCall, args...) + switch act { + case llssa.Call, llssa.Go: + if act == llssa.Call && isRecoverTransparentWrapper(p.goFn) { + return b.CallRecoverAlias(p.fn.Expr, mayRecover, fn, buildCall, args...) + } + return b.Do(act, fn, buildCall, args...) + default: + b.DeferRecover(act, mayRecover, fn, buildCall, args...) + return llssa.Nil + } +} + +func (p *context) callMayRecover(v ssa.Value) bool { + switch v := v.(type) { + case *ssa.Builtin: + return false + case *ssa.Function: + return functionMayRecover(v) + case *ssa.MakeClosure: + if fn, ok := v.Fn.(*ssa.Function); ok { + return functionMayRecover(fn) + } + return true + case *ssa.Call: + // The deferred callee is the call result, not the factory function. + return true + } + return true } func (p *context) staticArrayLenBuiltinArg(b llssa.Builder, arg ssa.Value) (llssa.Expr, bool) { @@ -1965,6 +1992,7 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm p.recordCallerLocationForCall(b, call) p.emitPCLineLabel(b, call.Pos()) cv := call.Value + mayRecover := p.callMayRecover(cv) if mthd := call.Method; mthd != nil { reflectCheck := p.reflectTypeMethodCheck(call, mthd) o := p.compileValue(b, cv) @@ -1974,7 +2002,7 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm hasVArg = fnHasVArg } args := p.compileValues(b, call.Args, hasVArg) - ret = p.emitDo(b, act, ds, fn, llssa.Builder.Call, args...) + ret = p.emitDo(b, act, ds, true, fn, llssa.Builder.Call, args...) if reflectCheck.Kind&llssa.ReflectTypeMethodByName != 0 && reflectCheck.Name == "" { b.MarkReflectTypeMethodByNameExpr(ret, 1) } @@ -2008,7 +2036,7 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm } } args := p.compileValues(b, args, kind) - ret = p.emitDo(b, act, ds, llssa.Builtin(fn), llssa.Builder.Call, args...) + ret = p.emitDo(b, act, ds, false, llssa.Builtin(fn), llssa.Builder.Call, args...) case *ssa.Function: aFn, pyFn, ftype := p.compileFunction(cv) // TODO(xsw): check ca != llssa.Call @@ -2017,13 +2045,13 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm p.inCFunc = true args := p.compileValues(b, args, kind) p.inCFunc = false - ret = p.emitDo(b, act, ds, aFn.Expr, llssa.Builder.Call, args...) + ret = p.emitDo(b, act, ds, mayRecover, aFn.Expr, llssa.Builder.Call, args...) case goFunc: args := p.compileValues(b, args, kind) - ret = p.emitDo(b, act, ds, aFn.Expr, llssa.Builder.Call, args...) + ret = p.emitDo(b, act, ds, mayRecover, aFn.Expr, llssa.Builder.Call, args...) case pyFunc: args := p.compileValues(b, args, kind) - ret = p.emitDo(b, act, ds, pyFn.Expr, llssa.Builder.Call, args...) + ret = p.emitDo(b, act, ds, mayRecover, pyFn.Expr, llssa.Builder.Call, args...) case llgoPyList: args := p.compileValues(b, args, fnHasVArg) ret = b.PyList(args...) @@ -2102,33 +2130,33 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm b.Unreachable() case llgoAtomicLoad: args := p.compileValues(b, args, kind) - ret = p.emitDo(b, act, ds, llssa.Nil, func(b llssa.Builder, _ llssa.Expr, args ...llssa.Expr) llssa.Expr { + ret = p.emitDo(b, act, ds, false, llssa.Nil, func(b llssa.Builder, _ llssa.Expr, args ...llssa.Expr) llssa.Expr { return p.atomicLoad(b, args) }, args...) case llgoAtomicStore: args := p.compileValues(b, args, kind) - p.emitDo(b, act, ds, llssa.Nil, func(b llssa.Builder, _ llssa.Expr, args ...llssa.Expr) llssa.Expr { + p.emitDo(b, act, ds, false, llssa.Nil, func(b llssa.Builder, _ llssa.Expr, args ...llssa.Expr) llssa.Expr { return p.atomicStore(b, args) }, args...) case llgoAtomicCmpXchg: args := p.compileValues(b, args, kind) - ret = p.emitDo(b, act, ds, llssa.Nil, func(b llssa.Builder, _ llssa.Expr, args ...llssa.Expr) llssa.Expr { + ret = p.emitDo(b, act, ds, false, llssa.Nil, func(b llssa.Builder, _ llssa.Expr, args ...llssa.Expr) llssa.Expr { return p.atomicCmpXchg(b, args) }, args...) case llgoAtomicCmpXchgOK: args := p.compileValues(b, args, kind) - ret = p.emitDo(b, act, ds, llssa.Nil, func(b llssa.Builder, _ llssa.Expr, args ...llssa.Expr) llssa.Expr { + ret = p.emitDo(b, act, ds, false, llssa.Nil, func(b llssa.Builder, _ llssa.Expr, args ...llssa.Expr) llssa.Expr { return p.atomicCmpXchgOK(b, args) }, args...) case llgoAtomicAddReturnNew: args := p.compileValues(b, args, kind) - ret = p.emitDo(b, act, ds, llssa.Nil, func(b llssa.Builder, _ llssa.Expr, args ...llssa.Expr) llssa.Expr { + ret = p.emitDo(b, act, ds, false, llssa.Nil, func(b llssa.Builder, _ llssa.Expr, args ...llssa.Expr) llssa.Expr { return b.BinOp(token.ADD, p.atomic(b, llssa.OpAdd, args), args[1]) }, args...) default: if ftype >= llgoAtomicOpBase && ftype <= llgoAtomicOpLast { args := p.compileValues(b, args, kind) - ret = p.emitDo(b, act, ds, llssa.Nil, func(b llssa.Builder, _ llssa.Expr, args ...llssa.Expr) llssa.Expr { + ret = p.emitDo(b, act, ds, false, llssa.Nil, func(b llssa.Builder, _ llssa.Expr, args ...llssa.Expr) llssa.Expr { return p.atomic(b, llssa.AtomicOp(ftype-llgoAtomicOpBase), args) }, args...) } else { @@ -2138,7 +2166,7 @@ func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallComm default: fn := p.compileValue(b, cv) args := p.compileDynamicCallValues(b, call, kind) - ret = p.emitDo(b, act, ds, fn, llssa.Builder.Call, args...) + ret = p.emitDo(b, act, ds, mayRecover, fn, llssa.Builder.Call, args...) } return } diff --git a/cl/recover_activation_test.go b/cl/recover_activation_test.go new file mode 100644 index 0000000000..a1fe000412 --- /dev/null +++ b/cl/recover_activation_test.go @@ -0,0 +1,71 @@ +//go:build !llgo + +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cl_test + +import ( + "regexp" + "strings" + "testing" + + "github.com/goplus/llgo/cl/cltest" +) + +func TestRecoverUsesActivationToken(t *testing.T) { + const src = `package foo + +func recursive(depth int) any { + if depth > 0 { + return recursive(depth - 1) + } + return recover() +} +` + ir := cltest.CompileIREx(t, src, "foo.go", false, nil) + + bind := regexp.MustCompile(`BindRecoverFrame"\(ptr @foo\.recursive, ptr (%[0-9]+)\)`).FindStringSubmatch(ir) + if bind == nil { + t.Fatalf("recover function does not bind an activation token:\n%s", ir) + } + if want := `Recover"(ptr ` + bind[1] + `)`; !strings.Contains(ir, want) { + t.Fatalf("recover does not use bound activation token %s:\n%s", bind[1], ir) + } + if !strings.Contains(ir, `noinline`) || !strings.Contains(ir, `"disable-tail-calls"="true"`) { + t.Fatalf("recover function must preserve its activation frame:\n%s", ir) + } +} + +func TestRecoverInterfaceMethodIR(t *testing.T) { + const src = `package foo + +type I interface { recoverValue() } +type T int +func (T) recoverValue() { recover() } + func call(v I) { defer v.recoverValue() } +` + ir := cltest.CompileIREx(t, src, "foo.go", false, nil) + for _, want := range []string{ + `BindRecoverFrame"(ptr @foo.T.recoverValue`, + `StartRecoverFrameAlias"(ptr @"foo.(*T).recoverValue", ptr @foo.T.recoverValue)`, + `StartRecoverFrame"(ptr %`, + } { + if !strings.Contains(ir, want) { + t.Fatalf("missing recover wrapper handoff %q:\n%s", want, ir) + } + } +} diff --git a/cl/rewrite_internal_test.go b/cl/rewrite_internal_test.go index c90cdcf01e..c93112c3c9 100644 --- a/cl/rewrite_internal_test.go +++ b/cl/rewrite_internal_test.go @@ -898,8 +898,8 @@ func TestEmitDoWithExplicitDeferStack(t *testing.T) { b.SetBlockEx(owner.Block(0), llssa.BeforeLast, true) ctx := &context{} - ctx.emitDo(b, llssa.DeferInLoop, &explicitDeferStack{stack: stack, owner: owner}, callee.Expr, llssa.Builder.Call) - ctx.emitDo(b, llssa.DeferAlways, nil, callee.Expr, llssa.Builder.Call) + ctx.emitDo(b, llssa.DeferInLoop, &explicitDeferStack{stack: stack, owner: owner}, false, callee.Expr, llssa.Builder.Call) + ctx.emitDo(b, llssa.DeferAlways, nil, false, callee.Expr, llssa.Builder.Call) b.DeferStackDrain() b.RunDefers() b.Return() @@ -1090,7 +1090,7 @@ func TestEmitDoWithoutExplicitDeferStack(t *testing.T) { b := fn.MakeBody(1) ctx := &context{} - got := ctx.emitDo(b, llssa.Call, nil, callee.Expr, llssa.Builder.Call) + got := ctx.emitDo(b, llssa.Call, nil, false, callee.Expr, llssa.Builder.Call) if got.IsNil() { t.Fatal("emitDo without explicit defer stack should return direct call result") } diff --git a/runtime/internal/runtime/runtime2.go b/runtime/internal/runtime/runtime2.go index 7787c8e225..ee18851f31 100644 --- a/runtime/internal/runtime/runtime2.go +++ b/runtime/internal/runtime/runtime2.go @@ -38,10 +38,11 @@ const ( // make sense once LLGo can suspend and resume a G (saved registers, wait state, // and stack roots) belong here when those facilities are added. type g struct { - defer_ *Defer - panic_ unsafe.Pointer - panicPCs panicPCStore - m *m + defer_ *Defer + panic_ unsafe.Pointer + panicPCs panicPCStore + recoverFrame unsafe.Pointer + m *m atomicstatus uint32 goid uint64 diff --git a/runtime/internal/runtime/z_baremetal.go b/runtime/internal/runtime/z_baremetal.go index a862225852..e8bb76f386 100644 --- a/runtime/internal/runtime/z_baremetal.go +++ b/runtime/internal/runtime/z_baremetal.go @@ -21,6 +21,10 @@ func Rethrow(link *Defer) { c.Printf(c.Str("fatal error\n")) c.Exit(2) } else { + if ptr := getg().panic_; ptr != nil && link == GetThreadDefer() { + node := (*panicNode)(ptr) + node.defer_ = link + } setjmp.Longjmp((*setjmp.JmpBuf)(link.Addr), 1) } } diff --git a/runtime/internal/runtime/z_default.go b/runtime/internal/runtime/z_default.go index e73aeff206..8011ec002d 100644 --- a/runtime/internal/runtime/z_default.go +++ b/runtime/internal/runtime/z_default.go @@ -3,6 +3,8 @@ package runtime import ( + "unsafe" + c "github.com/goplus/llgo/runtime/internal/clite" "github.com/goplus/llgo/runtime/internal/clite/debug" ) @@ -18,13 +20,18 @@ func Rethrow(link *Defer) { gp := getg() if ptr := gp.panic_; ptr != nil { if link == nil { - TracePanic(*(*any)(ptr)) + node := (*panicNode)(ptr) + TracePanic(node.arg) if PanicTraceback == nil || !PanicTraceback(2) { debug.PrintStack(2) } - c.Free(ptr) + c.Free(unsafe.Pointer(node)) c.Exit(2) } else { + node := (*panicNode)(ptr) + if link == gp.defer_ { + node.defer_ = link + } c.Siglongjmp(link.Addr, 1) } } else if gp.goexit { diff --git a/runtime/internal/runtime/z_rt.go b/runtime/internal/runtime/z_rt.go index 915905e77a..db0c141980 100644 --- a/runtime/internal/runtime/z_rt.go +++ b/runtime/internal/runtime/z_rt.go @@ -35,14 +35,28 @@ type Defer struct { Args unsafe.Pointer // defer func and args links } +type panicNode struct { + prev unsafe.Pointer + arg any + defer_ *Defer +} + // Recover recovers a panic. -func Recover() (ret any) { +func Recover(token unsafe.Pointer) (ret any) { gp := getg() + if token == nil || token != gp.recoverFrame { + return nil + } ptr := gp.panic_ if ptr != nil { - gp.panic_ = nil - ret = *(*any)(ptr) - c.Free(ptr) + node := (*panicNode)(ptr) + if node.defer_ != gp.defer_ { + return nil + } + gp.panic_ = node.prev + gp.recoverFrame = nil + ret = node.arg + c.Free(unsafe.Pointer(node)) if PanicRecovered != nil { PanicRecovered() } @@ -61,6 +75,41 @@ func Recover() (ret any) { return } +// StartRecoverFrame enables direct recover calls made by the deferred function +// currently being invoked from frame. +func StartRecoverFrame(frame unsafe.Pointer) unsafe.Pointer { + gp := getg() + old := gp.recoverFrame + gp.recoverFrame = frame + return old +} + +// EndRecoverFrame restores direct recover permission after a deferred call. +func EndRecoverFrame(frame unsafe.Pointer) { + getg().recoverFrame = frame +} + +// BindRecoverFrame replaces a deferred function's code token with the unique +// stack token for this invocation. A recursive invocation of the same function +// sees the already-bound outer token and is therefore not allowed to recover. +func BindRecoverFrame(function, activation unsafe.Pointer) { + gp := getg() + if gp.recoverFrame == function { + gp.recoverFrame = activation + } +} + +// StartRecoverFrameAlias maps a direct deferred closure wrapper to the wrapped +// function while the wrapper calls into it. +func StartRecoverFrameAlias(from, to unsafe.Pointer) unsafe.Pointer { + gp := getg() + old := gp.recoverFrame + if old == from { + gp.recoverFrame = to + } + return old +} + // RecoverMark, set by the public runtime package, records the recovering // frame for panic-snapshot splicing. var RecoverMark func() @@ -80,14 +129,15 @@ func Panic(v any) { v = &PanicNilError{} } SavePanicCallerFrames() - ptr := c.Malloc(unsafe.Sizeof(v)) - *(*any)(ptr) = v gp := getg() - gp.panic_ = ptr + ptr := (*panicNode)(c.Malloc(unsafe.Sizeof(panicNode{}))) + ptr.prev = gp.panic_ + ptr.arg = v + ptr.defer_ = gp.defer_ + gp.panic_ = unsafe.Pointer(ptr) Rethrow(gp.defer_) } - func Goexit() { gp := getg() gp.goexit = true diff --git a/ssa/decl.go b/ssa/decl.go index 68087f4380..43d1a87afc 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -242,6 +242,7 @@ type aFunction struct { blks []BasicBlock defer_ *aDefer + recoverToken Expr pendingLoopCases []loopDeferCase nextDeferID uintptr recov BasicBlock diff --git a/ssa/eh.go b/ssa/eh.go index 782ffbb337..5ef41a36af 100644 --- a/ssa/eh.go +++ b/ssa/eh.go @@ -179,11 +179,12 @@ type deferTarget struct { // The id uniquely identifies the defer call site for dispatch during drain. // typ is the node struct type needed to decode the linked-list node. type loopDeferCase struct { - id Expr - typ Type - fn Expr - args []Expr - buildCall func(Builder, Expr, ...Expr) Expr + id Expr + typ Type + mayRecover bool + fn Expr + args []Expr + buildCall func(Builder, Expr, ...Expr) Expr } const ( @@ -339,6 +340,11 @@ func (b Builder) DeferStackDrain() { // Defer emits a defer instruction. func (b Builder) Defer(kind DoAction, fn Expr, buildCall func(Builder, Expr, ...Expr) Expr, args ...Expr) { + b.DeferRecover(kind, deferMayRecover(fn), fn, buildCall, args...) +} + +// DeferRecover emits a defer instruction with explicit recover capability. +func (b Builder) DeferRecover(kind DoAction, mayRecover bool, fn Expr, buildCall func(Builder, Expr, ...Expr) Expr, args ...Expr) { dbgInstrCall("Defer", fn, args) var prog Program var nextbit Expr @@ -366,14 +372,20 @@ func (b Builder) Defer(kind DoAction, fn Expr, buildCall func(Builder, Expr, ... } typ := b.saveDeferArgs(self, kind, id, fn, args) if kind == DeferInLoop { - loopCase := loopDeferCase{id: id, typ: typ, fn: fn, args: args, buildCall: buildCall} + loopCase := loopDeferCase{id: id, typ: typ, mayRecover: mayRecover, fn: fn, args: args, buildCall: buildCall} self.loopCases = append(self.loopCases, loopCase) } - b.appendDeferStmt(self, kind, typ, buildCall, fn, args, nextbit) + b.appendDeferStmt(self, kind, typ, mayRecover, buildCall, fn, args, nextbit) } // DeferTo emits a defer instruction into an explicit runtime defer stack. func (b Builder) DeferTo(owner Function, stack Expr, fn Expr, buildCall func(Builder, Expr, ...Expr) Expr, args ...Expr) { + b.DeferToRecover(owner, stack, deferMayRecover(fn), fn, buildCall, args...) +} + +// DeferToRecover emits a defer instruction into an explicit runtime defer +// stack with explicit recover capability. +func (b Builder) DeferToRecover(owner Function, stack Expr, mayRecover bool, fn Expr, buildCall func(Builder, Expr, ...Expr) Expr, args ...Expr) { if debugInstr { logCall("DeferTo", fn, args) } @@ -387,11 +399,12 @@ func (b Builder) DeferTo(owner Function, stack Expr, fn Expr, buildCall func(Bui argsPtr := b.PtrCast(b.Prog.Pointer(b.Prog.VoidPtr()), stack) typ := b.saveDeferArgsTo(argsPtr, DeferInLoop, id, fn, args) loopCase := loopDeferCase{ - id: id, - typ: typ, - fn: fn, - args: args, - buildCall: buildCall, + id: id, + typ: typ, + mayRecover: mayRecover, + fn: fn, + args: args, + buildCall: buildCall, } if self == nil { owner.pendingLoopCases = append(owner.pendingLoopCases, loopCase) @@ -400,7 +413,7 @@ func (b Builder) DeferTo(owner Function, stack Expr, fn Expr, buildCall func(Bui self.loopCases = append(self.loopCases, loopCase) } -func (b Builder) appendDeferStmt(self *aDefer, kind DoAction, typ Type, buildCall func(Builder, Expr, ...Expr) Expr, fn Expr, args []Expr, nextbit Expr) { +func (b Builder) appendDeferStmt(self *aDefer, kind DoAction, typ Type, mayRecover bool, buildCall func(Builder, Expr, ...Expr) Expr, fn Expr, args []Expr, nextbit Expr) { self.stmts = append(self.stmts, func(bits Expr, resume deferTarget) { switch kind { case DeferInCond: @@ -411,13 +424,13 @@ func (b Builder) appendDeferStmt(self *aDefer, kind DoAction, typ Type, buildCal zero := prog.Val(uintptr(0)) has := b.BinOp(token.NEQ, b.BinOp(token.AND, bits, nextbit), zero) b.IfThen(has, func() { - b.callDefer(self, typ, buildCall, fn, args) + b.callDefer(self, typ, mayRecover, buildCall, fn, args) }) case DeferAlways: // Leaving a run of loop defers; allow the next loop-defer statement // (earlier in source order) to generate its own drainer. self.loopDrainerGenerated = false - b.callDefer(self, typ, buildCall, fn, args) + b.callDefer(self, typ, mayRecover, buildCall, fn, args) case DeferInLoop: b.loopDeferDrainer(self, resume) } @@ -474,7 +487,7 @@ func (b Builder) loopDeferDrainer(self *aDefer, resume deferTarget) { b.SetBlockEx(caseBlks[i], AtEnd, true) b.storeDeferTarget(self.rethPtr, resume) - b.callDefer(self, c.typ, c.buildCall, c.fn, c.args) + b.callDefer(self, c.typ, c.mayRecover, c.buildCall, c.fn, c.args) b.Jump(condBlk) } @@ -530,9 +543,11 @@ func (b Builder) saveDeferArgsTo(argsPtr Expr, kind DoAction, id Expr, fn Expr, return typ } -func (b Builder) callDefer(self *aDefer, typ Type, buildCall func(Builder, Expr, ...Expr) Expr, fn Expr, args []Expr) { +func (b Builder) callDefer(self *aDefer, typ Type, mayRecover bool, buildCall func(Builder, Expr, ...Expr) Expr, fn Expr, args []Expr) { if typ == nil { - buildCall(b, fn, args...) + b.callRecoverScopedDefer(fn, mayRecover, func() { + buildCall(b, fn, args...) + }) return } prog := b.Prog @@ -563,10 +578,83 @@ func (b Builder) callDefer(self *aDefer, typ Type, buildCall func(Builder, Expr, args[i] = b.getField(data, i+offset) } b.Call(b.Pkg.rtFunc("FreeDeferNode"), ptr) - buildCall(b, fn, args...) + b.callRecoverScopedDefer(fn, mayRecover, func() { + buildCall(b, fn, args...) + }) }) } +func (b Builder) callRecoverScopedDefer(fn Expr, mayRecover bool, call func()) { + if fn.IsNil() || fn.impl.IsNil() || isRecoverBuiltin(fn) { + call() + return + } + token := b.recoverDeferToken(fn, mayRecover) + if token.IsNil() { + call() + return + } + prev := b.Call(b.Pkg.rtFunc("StartRecoverFrame"), token) + call() + b.Call(b.Pkg.rtFunc("EndRecoverFrame"), prev) +} + +// CallRecoverAlias invokes fn through a compiler-generated wrapper while +// preserving the wrapped function as the direct deferred call for recover. +func (b Builder) CallRecoverAlias(from Expr, mayRecover bool, fn Expr, buildCall func(Builder, Expr, ...Expr) Expr, args ...Expr) Expr { + token := b.recoverDeferToken(fn, mayRecover) + if from.IsNil() || token.IsNil() { + return buildCall(b, fn, args...) + } + prev := b.Call( + b.Pkg.rtFunc("StartRecoverFrameAlias"), + b.PtrCast(b.Prog.VoidPtr(), from), + token, + ) + ret := buildCall(b, fn, args...) + b.Call(b.Pkg.rtFunc("EndRecoverFrame"), prev) + return ret +} + +func (b Builder) recoverDeferToken(fn Expr, mayRecover bool) Expr { + switch fn.kind { + case vkClosure, vkIfaceMethod: + if !mayRecover { + return Nil + } + return b.PtrCast(b.Prog.VoidPtr(), b.Field(fn, 0)) + case vkFuncDecl: + if !mayRecover { + return Nil + } + return b.PtrCast(b.Prog.VoidPtr(), fn) + case vkFuncPtr: + return b.PtrCast(b.Prog.VoidPtr(), fn) + } + return Nil +} + +func deferMayRecover(fn Expr) bool { + if fn.IsNil() || fn.Type == nil { + return false + } + switch fn.kind { + case vkClosure, vkFuncDecl: + return fn.mayRecover() + case vkIfaceMethod, vkFuncPtr: + return true + } + return false +} + +func isRecoverBuiltin(fn Expr) bool { + if fn.IsNil() || fn.kind != vkBuiltin { + return false + } + bi, ok := fn.raw.Type.(*builtinTy) + return ok && bi.name == "recover" +} + // RunDefers emits instructions to run deferred instructions. func (b Builder) RunDefers() { self := b.getDefer(DeferInCond) @@ -680,11 +768,31 @@ func (b Builder) Unreachable() { b.impl.CreateUnreachable() } +// BindRecoverFrame gives this invocation a stack-local identity. The runtime +// replaces a pending deferred-function token with this activation token only +// when this invocation is the direct deferred call. Recursive calls to the +// same function therefore cannot recover the caller's panic. +func (b Builder) BindRecoverFrame() { + token := b.AllocaT(b.Prog.Byte()) + token = b.PtrCast(b.Prog.VoidPtr(), token) + b.Func.recoverToken = token + b.Call( + b.Pkg.rtFunc("BindRecoverFrame"), + b.PtrCast(b.Prog.VoidPtr(), b.Func.Expr), + token, + ) +} + // Recover emits a recover instruction. func (b Builder) Recover() Expr { dbgInstrln("Recover") - // TODO(xsw): recover can't be a function call in Go - return b.Call(b.Pkg.rtFunc("Recover")) + token := b.Func.recoverToken + if token.IsNil() { + // Keep the lower-level Builder API usable for callers that emit recover + // without the Go frontend's function-entry binding. + token = b.PtrCast(b.Prog.VoidPtr(), b.Func.Expr) + } + return b.Call(b.Pkg.rtFunc("Recover"), token) } // Panic emits a panic instruction. diff --git a/ssa/expr.go b/ssa/expr.go index dce7fb24c6..97d91cd852 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -48,6 +48,8 @@ type Expr struct { var Nil Expr // Zero value is a nil Expr +const mayRecoverAttr = "llgo.may-recover" + // IsNil checks if the expression is nil or not. func (v Expr) IsNil() bool { return v.Type == nil @@ -59,6 +61,33 @@ func (v Expr) SetOrdering(ordering AtomicOrdering) Expr { return v } +// SetVolatile marks a load or store as volatile. +func (v Expr) SetVolatile(volatile bool) Expr { + v.impl.SetVolatile(volatile) + return v +} + +// MarkMayRecover marks a function or closure that may call recover directly. +func (v Expr) MarkMayRecover() Expr { + if v.Type == nil || v.impl.IsNil() { + return v + } + fn := v.impl.IsAFunction() + if !fn.IsNil() && fn.GetStringAttributeAtIndex(-1, mayRecoverAttr).IsNil() { + ctx := fn.GlobalParent().Context() + fn.AddFunctionAttr(ctx.CreateStringAttribute(mayRecoverAttr, "true")) + } + return v +} + +func (v Expr) mayRecover() bool { + if v.Type == nil || v.impl.IsNil() { + return false + } + fn := v.impl.IsAFunction() + return !fn.IsNil() && !fn.GetStringAttributeAtIndex(-1, mayRecoverAttr).IsNil() +} + func (v Expr) SetName(alias string) Expr { v.impl.SetName(alias) return v diff --git a/test/go/recover_defer_fixedbugs_test.go b/test/go/recover_defer_fixedbugs_test.go new file mode 100644 index 0000000000..b76a607cc0 --- /dev/null +++ b/test/go/recover_defer_fixedbugs_test.go @@ -0,0 +1,234 @@ +package gotest + +import ( + "runtime" + "strings" + "testing" +) + +type fixedbug4066Panic struct{} + +func fixedbug4066NamedReturn() (val int) { + val = 0 + defer func() { + if x := recover(); x != nil { + _ = x.(fixedbug4066Panic) + } + }() + for { + val = 2 + fixedbug4066Throw() + } +} + +func fixedbug4066Throw() { + panic(fixedbug4066Panic{}) +} + +func TestRecoverFixedbug4066NamedReturn(t *testing.T) { + if got := fixedbug4066NamedReturn(); got != 2 { + t.Fatalf("named return after recover = %d, want 2", got) + } +} + +func TestRecoverFixedbugDirectDeferredFuncValue(t *testing.T) { + recovered := false + func() { + f := func() { + if recover() != nil { + recovered = true + } + } + defer f() + panic("direct deferred func value") + }() + if !recovered { + t.Fatal("direct deferred func value did not recover") + } +} + +func TestRecoverFixedbugNestedDeferInDeferredFuncDoesNotRecover(t *testing.T) { + nested := any("unset") + func() { + defer func() { + if r := recover(); r != "outer" { + t.Fatalf("outer recover = %v, want outer", r) + } + }() + defer func() { + defer func() { + nested = recover() + }() + }() + panic("outer") + }() + if nested != nil { + t.Fatalf("nested recover = %v, want nil", nested) + } +} + +var fixedbugReturnedRecover any + +func fixedbugReturnedRecoverFunc() func() { + return func() { + fixedbugReturnedRecover = recover() + } +} + +func TestRecoverFixedbugReturnedDeferredFuncValue(t *testing.T) { + fixedbugReturnedRecover = nil + func() { + defer fixedbugReturnedRecoverFunc()() + panic("returned deferred func value") + }() + if fixedbugReturnedRecover != "returned deferred func value" { + t.Fatalf("returned deferred recover = %v, want panic value", fixedbugReturnedRecover) + } +} + +type fixedbugRecoverMethod int + +var fixedbugMethodRecover any + +func (fixedbugRecoverMethod) recoverValue() { + fixedbugMethodRecover = recover() +} + +func TestRecoverDirectDeferredMethod(t *testing.T) { + fixedbugMethodRecover = nil + func() { + defer fixedbugRecoverMethod(0).recoverValue() + panic("direct deferred method") + }() + if fixedbugMethodRecover != "direct deferred method" { + t.Fatalf("direct deferred method recover = %v, want panic value", fixedbugMethodRecover) + } +} + +type fixedbugRecoverInterface interface { + recoverValue() +} + +func TestRecoverDirectDeferredInterfaceMethod(t *testing.T) { + fixedbugMethodRecover = nil + func() { + var v fixedbugRecoverInterface = fixedbugRecoverMethod(0) + defer v.recoverValue() + panic("direct deferred interface method") + }() + if fixedbugMethodRecover != "direct deferred interface method" { + t.Fatalf("direct deferred interface method recover = %v, want panic value", fixedbugMethodRecover) + } +} + +func TestRecoverDirectDeferredMethodValue(t *testing.T) { + fixedbugMethodRecover = nil + func() { + var v fixedbugRecoverInterface = fixedbugRecoverMethod(0) + f := v.recoverValue + defer f() + panic("direct deferred method value") + }() + if fixedbugMethodRecover != "direct deferred method value" { + t.Fatalf("direct deferred method value recover = %v, want panic value", fixedbugMethodRecover) + } +} + +var fixedbugRecursiveRecover any + +func fixedbugRecursiveDeferredRecover(depth int) { + if depth > 0 { + fixedbugRecursiveDeferredRecover(depth - 1) + return + } + fixedbugRecursiveRecover = recover() +} + +func TestRecoverRecursiveDeferredActivationDoesNotRecover(t *testing.T) { + fixedbugRecursiveRecover = "unset" + var outer any + func() { + defer func() { + outer = recover() + }() + defer fixedbugRecursiveDeferredRecover(1) + panic("recursive deferred activation") + }() + if fixedbugRecursiveRecover != nil { + t.Fatalf("recursive recover = %v, want nil", fixedbugRecursiveRecover) + } + if outer != "recursive deferred activation" { + t.Fatalf("outer recover = %v, want panic value", outer) + } +} + +var fixedbug73916Recovered bool + +func fixedbug73916CallRecover() { + if recover() != nil { + fixedbug73916Recovered = true + } +} + +func fixedbug73916Deferred(int) { + fixedbug73916CallRecover() +} + +func fixedbug73916MustPanic(t *testing.T, fn func()) any { + t.Helper() + defer func() { + if r := recover(); r == nil { + t.Fatal("deferred indirect recover swallowed panic") + } + }() + fn() + return nil +} + +func TestRecoverFixedbug73916IndirectRecoverDoesNotRecover(t *testing.T) { + skipBeforeGo126(t) + fixedbug73916Recovered = false + fixedbug73916MustPanic(t, func() { + defer fixedbug73916Deferred(1) + panic("fixedbug73916") + }) + if fixedbug73916Recovered { + t.Fatal("indirect recover returned non-nil") + } +} + +var fixedbug73916bRecovered bool + +func fixedbug73916bCallRecover() { + func() { + if recover() != nil { + fixedbug73916bRecovered = true + } + }() +} + +func fixedbug73916bDeferred() int { + fixedbug73916bCallRecover() + return 0 +} + +func TestRecoverFixedbug73916NestedRecoverDoesNotRecover(t *testing.T) { + skipBeforeGo126(t) + fixedbug73916bRecovered = false + fixedbug73916MustPanic(t, func() { + defer fixedbug73916bDeferred() + panic("fixedbug73916b") + }) + if fixedbug73916bRecovered { + t.Fatal("nested recover returned non-nil") + } +} + +func skipBeforeGo126(t *testing.T) { + t.Helper() + version := runtime.Version() + if strings.HasPrefix(version, "go1.26") || strings.HasPrefix(version, "devel") { + return + } + t.Skip("requires Go 1.26 recover semantics") +} diff --git a/test/goroot/xfail.yaml b/test/goroot/xfail.yaml index 3bfa465b68..02ceb84a6d 100644 --- a/test/goroot/xfail.yaml +++ b/test/goroot/xfail.yaml @@ -546,12 +546,6 @@ timeouts: case: fixedbugs/issue40367.go timeout: 2m reason: issue40367 run exceeds the default timeout on darwin/arm64 - - version: go1.24 - platform: darwin/arm64 - directive: run - case: fixedbugs/issue4066.go - timeout: 2m - reason: issue4066 run exceeds the default timeout on darwin/arm64 - version: go1.24 platform: darwin/arm64 directive: run @@ -900,12 +894,6 @@ timeouts: case: fixedbugs/issue40367.go timeout: 2m reason: issue40367 run exceeds the default timeout on darwin/arm64 - - version: go1.26 - platform: darwin/arm64 - directive: run - case: fixedbugs/issue4066.go - timeout: 2m - reason: issue4066 run exceeds the default timeout on darwin/arm64 - version: go1.26 platform: darwin/arm64 directive: run @@ -1385,16 +1373,6 @@ xfails: directive: runoutput case: rangegen.go reason: current main goroot runoutput failure on darwin/arm64 - - version: go1.26 - platform: darwin/arm64 - directive: run - case: fixedbugs/issue73916.go - reason: go1.26 goroot run failure on darwin/arm64 - - version: go1.26 - platform: darwin/arm64 - directive: run - case: fixedbugs/issue73916b.go - reason: go1.26 goroot run failure on darwin/arm64 - platform: darwin/arm64 directive: run case: typeparam/mdempsky/16.go @@ -1409,16 +1387,6 @@ xfails: directive: run case: typeparam/mdempsky/16.go reason: nil-interface assertion panic implements runtime.Error but the message lacks the source interface type and prints the command-line-arguments package path on linux/amd64 - - version: go1.26 - platform: linux/amd64 - directive: run - case: fixedbugs/issue73916.go - reason: go1.26 goroot run failure on linux/amd64 - - version: go1.26 - platform: linux/amd64 - directive: run - case: fixedbugs/issue73916b.go - reason: go1.26 goroot run failure on linux/amd64 - version: go1.24 platform: linux/amd64 directive: runoutput @@ -1586,16 +1554,6 @@ xfails: directive: run case: fixedbugs/issue27518b.go reason: go1.24 goroot run failure on linux/amd64 - - version: go1.24 - platform: linux/amd64 - directive: run - case: fixedbugs/issue4066.go - reason: go1.24 goroot run failure on linux/amd64 - - version: go1.24 - platform: darwin/arm64 - directive: run - case: fixedbugs/issue4066.go - reason: go1.24 goroot run failure on darwin/arm64 - version: go1.24 platform: linux/amd64 directive: run @@ -1651,16 +1609,6 @@ xfails: directive: run case: fixedbugs/issue27518b.go reason: go1.26 goroot run failure on linux/amd64 - - version: go1.26 - platform: linux/amd64 - directive: run - case: fixedbugs/issue4066.go - reason: go1.26 goroot run failure on linux/amd64 - - version: go1.26 - platform: darwin/arm64 - directive: run - case: fixedbugs/issue4066.go - reason: go1.26 goroot run failure on darwin/arm64 - version: go1.26 platform: linux/amd64 directive: run