diff --git a/cl/_testdata/embedunexport/embedunexport.go b/cl/_testdata/embedunexport/embedunexport.go index 71badffee3..385b824e75 100644 --- a/cl/_testdata/embedunexport/embedunexport.go +++ b/cl/_testdata/embedunexport/embedunexport.go @@ -17,8 +17,16 @@ type Base struct { // CHECK: define %"{{.*}}.String" @"{{.*}}.(*Base).Name"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %"{{.*}}.Base", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load %"{{.*}}.String", ptr %1, align 8 -// CHECK-NEXT: ret %"{{.*}}.String" %2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3:{{.*}}; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4:{{.*}}; preds = %_llgo_0 +// CHECK-NEXT: %5 = load %"{{.*}}.String", ptr %1, align 8 +// CHECK-NEXT: ret %"{{.*}}.String" %5 // CHECK-NEXT: } func (b *Base) Name() string { return b.name diff --git a/cl/_testdata/geometry1370/geometry.go b/cl/_testdata/geometry1370/geometry.go index 9e7faa334e..69a83624f5 100644 --- a/cl/_testdata/geometry1370/geometry.go +++ b/cl/_testdata/geometry1370/geometry.go @@ -29,11 +29,27 @@ func NewRectangle(width, height float64) *Rectangle { // CHECK-LABEL: define double @"{{.*}}/cl/_testdata/geometry1370.(*Rectangle).Area"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %"{{.*}}/cl/_testdata/geometry1370.Rectangle", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load double, ptr %1, align 8 -// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/cl/_testdata/geometry1370.Rectangle", ptr %0, i32 0, i32 1 -// CHECK-NEXT: %4 = load double, ptr %3, align 8 -// CHECK-NEXT: %5 = fmul double %2, %4 -// CHECK-NEXT: ret double %5 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load double, ptr %1, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/cl/_testdata/geometry1370.Rectangle", ptr %0, i32 0, i32 1 +// CHECK-NEXT: %7 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %7, label %8, label %9 +// CHECK-EMPTY: +// CHECK-NEXT: 8: ; preds = %4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 9: ; preds = %4 +// CHECK-NEXT: %10 = load double, ptr %6, align 8 +// CHECK-NEXT: %11 = fmul double %5, %10 +// CHECK-NEXT: ret double %11 // CHECK-NEXT: } func (r *Rectangle) Area() float64 { return r.Width * r.Height } @@ -41,8 +57,16 @@ func (r *Rectangle) Area() float64 { return r.Width * r.Height } // CHECK-LABEL: define i64 @"{{.*}}/cl/_testdata/geometry1370.(*Rectangle).GetID"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %"{{.*}}/cl/_testdata/geometry1370.Rectangle", ptr %0, i32 0, i32 2 -// CHECK-NEXT: %2 = load i64, ptr %1, align 8 -// CHECK-NEXT: ret i64 %2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load i64, ptr %1, align 8 +// CHECK-NEXT: ret i64 %5 // CHECK-NEXT: } func (r *Rectangle) GetID() int { return r.id } @@ -59,19 +83,35 @@ func (r *Rectangle) setID(id int) { r.id = id } // CHECK-LABEL: define i1 @"{{.*}}/cl/_testdata/geometry1370.(*Rectangle).validate"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %"{{.*}}/cl/_testdata/geometry1370.Rectangle", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load double, ptr %1, align 8 -// CHECK-NEXT: %3 = fcmp ogt double %2, 0.000000e+00 -// CHECK-NEXT: br i1 %3, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %6, label %7 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/cl/_testdata/geometry1370.Rectangle", ptr %0, i32 0, i32 1 -// CHECK-NEXT: %5 = load double, ptr %4, align 8 -// CHECK-NEXT: %6 = fcmp ogt double %5, 0.000000e+00 -// CHECK-NEXT: br label %_llgo_2 +// CHECK-NEXT: _llgo_1: ; preds = %7 +// CHECK-NEXT: %3 = getelementptr inbounds %"{{.*}}/cl/_testdata/geometry1370.Rectangle", ptr %0, i32 0, i32 1 +// CHECK-NEXT: %4 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %4, label %10, label %11 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 -// CHECK-NEXT: %7 = phi i1 [ false, %_llgo_0 ], [ %6, %_llgo_1 ] -// CHECK-NEXT: ret i1 %7 +// CHECK-NEXT: _llgo_2: ; preds = %11, %7 +// CHECK-NEXT: %5 = phi i1 [ false, %7 ], [ %13, %11 ] +// CHECK-NEXT: ret i1 %5 +// CHECK-EMPTY: +// CHECK-NEXT: 6: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 7: ; preds = %_llgo_0 +// CHECK-NEXT: %8 = load double, ptr %1, align 8 +// CHECK-NEXT: %9 = fcmp ogt double %8, 0.000000e+00 +// CHECK-NEXT: br i1 %9, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: 10: ; preds = %_llgo_1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 11: ; preds = %_llgo_1 +// CHECK-NEXT: %12 = load double, ptr %3, align 8 +// CHECK-NEXT: %13 = fcmp ogt double %12, 0.000000e+00 +// CHECK-NEXT: br label %_llgo_2 // CHECK-NEXT: } func (r *Rectangle) validate() bool { return r.Width > 0 && r.Height > 0 } diff --git a/cl/_testdata/print/in.go b/cl/_testdata/print/in.go index b934f989bc..4f4b829b50 100644 --- a/cl/_testdata/print/in.go +++ b/cl/_testdata/print/in.go @@ -43,19 +43,43 @@ type stringStruct struct { // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) // CHECK-NEXT: %3 = call ptr @main.stringStructOf(ptr %1) // CHECK-NEXT: %4 = getelementptr inbounds %main.stringStruct, ptr %3, i32 0, i32 0 -// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 -// CHECK-NEXT: %6 = getelementptr inbounds %main.slice, ptr %2, i32 0, i32 0 -// CHECK-NEXT: store ptr %5, ptr %6, align 8 -// CHECK-NEXT: %7 = getelementptr inbounds %main.stringStruct, ptr %3, i32 0, i32 1 -// CHECK-NEXT: %8 = load i64, ptr %7, align 8 -// CHECK-NEXT: %9 = getelementptr inbounds %main.slice, ptr %2, i32 0, i32 1 -// CHECK-NEXT: store i64 %8, ptr %9, align 8 +// CHECK-NEXT: %5 = icmp eq ptr %3, null +// CHECK-NEXT: br i1 %5, label %6, label %7 +// CHECK-EMPTY: +// CHECK-NEXT: 6: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 7: ; preds = %_llgo_0 +// CHECK-NEXT: %8 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %9 = getelementptr inbounds %main.slice, ptr %2, i32 0, i32 0 +// CHECK-NEXT: store ptr %8, ptr %9, align 8 // CHECK-NEXT: %10 = getelementptr inbounds %main.stringStruct, ptr %3, i32 0, i32 1 -// CHECK-NEXT: %11 = load i64, ptr %10, align 8 -// CHECK-NEXT: %12 = getelementptr inbounds %main.slice, ptr %2, i32 0, i32 2 -// CHECK-NEXT: store i64 %11, ptr %12, align 8 -// CHECK-NEXT: %13 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %2, align 8 -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %13 +// CHECK-NEXT: %11 = icmp eq ptr %3, null +// CHECK-NEXT: br i1 %11, label %12, label %13 +// CHECK-EMPTY: +// CHECK-NEXT: 12: ; preds = %7 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 13: ; preds = %7 +// CHECK-NEXT: %14 = load i64, ptr %10, align 8 +// CHECK-NEXT: %15 = getelementptr inbounds %main.slice, ptr %2, i32 0, i32 1 +// CHECK-NEXT: store i64 %14, ptr %15, align 8 +// CHECK-NEXT: %16 = getelementptr inbounds %main.stringStruct, ptr %3, i32 0, i32 1 +// CHECK-NEXT: %17 = icmp eq ptr %3, null +// CHECK-NEXT: br i1 %17, label %18, label %19 +// CHECK-EMPTY: +// CHECK-NEXT: 18: ; preds = %13 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 19: ; preds = %13 +// CHECK-NEXT: %20 = load i64, ptr %16, align 8 +// CHECK-NEXT: %21 = getelementptr inbounds %main.slice, ptr %2, i32 0, i32 2 +// CHECK-NEXT: store i64 %20, ptr %21, align 8 +// CHECK-NEXT: %22 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %2, align 8 +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %22 // CHECK-NEXT: } func bytes(s string) (ret []byte) { diff --git a/cl/_testdata/varinit/in.go b/cl/_testdata/varinit/in.go index 15b17d7ebd..3f3a4e1501 100644 --- a/cl/_testdata/varinit/in.go +++ b/cl/_testdata/varinit/in.go @@ -8,7 +8,6 @@ var a = 100 // CHECK-NEXT: %0 = load i64, ptr @main.a, align 8 // CHECK-NEXT: %1 = add i64 %0, 1 // CHECK-NEXT: store i64 %1, ptr @main.a, align 8 -// CHECK-NEXT: %2 = load i64, ptr @main.a, align 8 // CHECK-NEXT: ret void // CHECK-NEXT: } func main() { diff --git a/cl/_testgo/abimethod/in.go b/cl/_testgo/abimethod/in.go index fbd6f43e77..df6ed42de4 100644 --- a/cl/_testgo/abimethod/in.go +++ b/cl/_testgo/abimethod/in.go @@ -248,15 +248,31 @@ type I2 interface { // CHECK-LABEL: define i64 @"main.(*T).Demo2"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.T, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load i64, ptr %1, align 8 -// CHECK-NEXT: ret i64 %2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load i64, ptr %1, align 8 +// CHECK-NEXT: ret i64 %5 // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.(*T).demo3"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.T, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load i64, ptr %1, align 8 -// CHECK-NEXT: ret i64 %2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load i64, ptr %1, align 8 +// CHECK-NEXT: ret i64 %5 // CHECK-NEXT: } // CHECK-LABEL: define void @main.init(){{.*}} { @@ -693,7 +709,7 @@ type I2 interface { // CHECK-LABEL: define void @main.testGeneric(){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 8) -// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface${{[-A-Za-z0-9_]+}}", ptr @"*_llgo_main.Pointer[any]") +// CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.NewItab"(ptr @"_llgo_iface$uinGjIxPTfzB5e5h5gH-0VIvLl5rQdJ_yx2UsrxQqds", ptr @"*_llgo_main.Pointer[any]") // CHECK-NEXT: %2 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" undef, ptr %1, 0 // CHECK-NEXT: %3 = insertvalue %"{{.*}}/runtime/internal/runtime.iface" %2, ptr %0, 1 // CHECK-NEXT: %4 = call ptr @"main.testGeneric$1"() @@ -715,29 +731,37 @@ type I2 interface { // CHECK-NEXT: %19 = extractvalue { ptr, ptr } %18, 1 // CHECK-NEXT: %20 = extractvalue { ptr, ptr } %18, 0 // CHECK-NEXT: %21 = call ptr %20(ptr %19) -// CHECK-NEXT: %22 = load %"{{.*}}/runtime/internal/runtime.eface", ptr %21, align 8 -// CHECK-NEXT: %23 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %22, 0 -// CHECK-NEXT: %24 = icmp eq ptr %23, @_llgo_int -// CHECK-NEXT: br i1 %24, label %_llgo_3, label %_llgo_4 +// CHECK-NEXT: %22 = icmp eq ptr %21, null +// CHECK-NEXT: br i1 %22, label %25, label %26 // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_3 -// CHECK-NEXT: %25 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @[[GENERIC_ERR]], i64 17 }, ptr %25, align 8 -// CHECK-NEXT: %26 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %25, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %26) +// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @107, i64 17 }, 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: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_3 // CHECK-NEXT: ret void // CHECK-EMPTY: -// CHECK-NEXT: _llgo_3: ; preds = %_llgo_0 -// CHECK-NEXT: %27 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %22, 1 -// CHECK-NEXT: %28 = load i64, ptr %27, align 8 -// CHECK-NEXT: %29 = icmp ne i64 %28, 100 -// CHECK-NEXT: br i1 %29, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: 25: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 26: ; preds = %_llgo_0 +// CHECK-NEXT: %27 = load %"{{.*}}/runtime/internal/runtime.eface", ptr %21, align 8 +// CHECK-NEXT: %28 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %27, 0 +// CHECK-NEXT: %29 = icmp eq ptr %28, @_llgo_int +// CHECK-NEXT: br i1 %29, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %26 +// CHECK-NEXT: %30 = extractvalue %"{{.*}}/runtime/internal/runtime.eface" %27, 1 +// CHECK-NEXT: %31 = load i64, ptr %30, align 8 +// CHECK-NEXT: %32 = icmp ne i64 %31, 100 +// CHECK-NEXT: br i1 %32, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %23, %"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 3 }, %"{{.*}}/runtime/internal/runtime.String" zeroinitializer) +// CHECK-NEXT: _llgo_4: ; preds = %26 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %28, %"{{.*}}/runtime/internal/runtime.String" { ptr @5, i64 3 }, %"{{.*}}/runtime/internal/runtime.String" zeroinitializer) // CHECK-NEXT: unreachable // CHECK-NEXT: } @@ -851,31 +875,61 @@ type I2 interface { // CHECK-LABEL: define i64 @"main.*struct{m int; *main.T}.Demo1"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = icmp eq ptr %0, null -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %3) -// CHECK-NEXT: %4 = icmp eq ptr %1, null -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %4) -// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AssertNilDerefPtr"(ptr %2) -// CHECK-NEXT: %6 = load %main.T, ptr %5, align 8 -// CHECK-NEXT: %7 = call i64 @main.T.Demo1(%main.T %6) -// CHECK-NEXT: ret i64 %7 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load ptr, ptr %1, align 8 +// CHECK-NEXT: %6 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %6, label %7, label %8 +// CHECK-EMPTY: +// CHECK-NEXT: 7: ; preds = %4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 8: ; preds = %4 +// CHECK-NEXT: %9 = icmp eq ptr %1, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %9) +// CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/internal/runtime.AssertNilDerefPtr"(ptr %5) +// CHECK-NEXT: %11 = load %main.T, ptr %10, align 8 +// CHECK-NEXT: %12 = call i64 @main.T.Demo1(%main.T %11) +// CHECK-NEXT: ret i64 %12 // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.*struct{m int; *main.T}.Demo2"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call i64 @"main.(*T).Demo2"(ptr %2) -// CHECK-NEXT: ret i64 %3 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call i64 @"main.(*T).Demo2"(ptr %5) +// CHECK-NEXT: ret i64 %6 // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.*struct{m int; *main.T}.demo3"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call i64 @"main.(*T).demo3"(ptr %2) -// CHECK-NEXT: ret i64 %3 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call i64 @"main.(*T).demo3"(ptr %5) +// CHECK-NEXT: ret i64 %6 // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.struct{m int; *main.T}.Demo1"({ i64, ptr } %0){{.*}} { @@ -1000,25 +1054,47 @@ type I2 interface { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds { i64, %main.T }, ptr %0, i32 0, i32 1 // CHECK-NEXT: %2 = icmp eq ptr %0, null -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %2) -// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.AssertNilDerefPtr"(ptr %1) -// CHECK-NEXT: %4 = load %main.T, ptr %3, align 8 -// CHECK-NEXT: %5 = call i64 @main.T.Demo1(%main.T %4) -// CHECK-NEXT: ret i64 %5 +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = call ptr @"{{.*}}/runtime/internal/runtime.AssertNilDerefPtr"(ptr %1) +// CHECK-NEXT: %6 = load %main.T, ptr %5, align 8 +// CHECK-NEXT: %7 = call i64 @main.T.Demo1(%main.T %6) +// CHECK-NEXT: ret i64 %7 // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.*struct{m int; main.T}.Demo2"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, %main.T }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = call i64 @"main.(*T).Demo2"(ptr %1) -// CHECK-NEXT: ret i64 %2 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, %main.T }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = call i64 @"main.(*T).Demo2"(ptr %4) +// CHECK-NEXT: ret i64 %5 // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.*struct{m int; main.T}.demo3"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, %main.T }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = call i64 @"main.(*T).demo3"(ptr %1) -// CHECK-NEXT: ret i64 %2 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, %main.T }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = call i64 @"main.(*T).demo3"(ptr %4) +// CHECK-NEXT: ret i64 %5 // CHECK-NEXT: } // CHECK-LABEL: define linkonce i64 @"__llgo_stub.main.*struct{m int; main.T}.Demo1"(ptr %0, ptr %1){{.*}} { @@ -1047,268 +1123,484 @@ type I2 interface { // CHECK-LABEL: define i64 @"main.*struct{m int; *bytes.Buffer}.Available"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call i64 @"bytes.(*Buffer).Available"(ptr %2) -// CHECK-NEXT: ret i64 %3 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call i64 @"bytes.(*Buffer).Available"(ptr %5) +// CHECK-NEXT: ret i64 %6 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.Slice" @"main.*struct{m int; *bytes.Buffer}.AvailableBuffer"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.Slice" @"bytes.(*Buffer).AvailableBuffer"(ptr %2) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %3 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call %"{{.*}}/runtime/internal/runtime.Slice" @"bytes.(*Buffer).AvailableBuffer"(ptr %5) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %6 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.Slice" @"main.*struct{m int; *bytes.Buffer}.Bytes"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.Slice" @"bytes.(*Buffer).Bytes"(ptr %2) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %3 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call %"{{.*}}/runtime/internal/runtime.Slice" @"bytes.(*Buffer).Bytes"(ptr %5) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %6 // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.*struct{m int; *bytes.Buffer}.Cap"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call i64 @"bytes.(*Buffer).Cap"(ptr %2) -// CHECK-NEXT: ret i64 %3 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call i64 @"bytes.(*Buffer).Cap"(ptr %5) +// CHECK-NEXT: ret i64 %6 // CHECK-NEXT: } // CHECK-LABEL: define void @"main.*struct{m int; *bytes.Buffer}.Grow"(ptr %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: call void @"bytes.(*Buffer).Grow"(ptr %3, i64 %1) +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: call void @"bytes.(*Buffer).Grow"(ptr %6, i64 %1) // CHECK-NEXT: ret void // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.*struct{m int; *bytes.Buffer}.Len"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call i64 @"bytes.(*Buffer).Len"(ptr %2) -// CHECK-NEXT: ret i64 %3 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call i64 @"bytes.(*Buffer).Len"(ptr %5) +// CHECK-NEXT: ret i64 %6 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.Slice" @"main.*struct{m int; *bytes.Buffer}.Next"(ptr %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.Slice" @"bytes.(*Buffer).Next"(ptr %3, i64 %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %4 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call %"{{.*}}/runtime/internal/runtime.Slice" @"bytes.(*Buffer).Next"(ptr %6, i64 %1) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %7 // CHECK-NEXT: } // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.Read"(ptr %0, %"{{.*}}/runtime/internal/runtime.Slice" %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).Read"(ptr %3, %"{{.*}}/runtime/internal/runtime.Slice" %1) -// CHECK-NEXT: %5 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4, 0 -// CHECK-NEXT: %6 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4, 1 -// CHECK-NEXT: %7 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %5, 0 -// CHECK-NEXT: %8 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, %"{{.*}}/runtime/internal/runtime.iface" %6, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %8 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).Read"(ptr %6, %"{{.*}}/runtime/internal/runtime.Slice" %1) +// CHECK-NEXT: %8 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, 0 +// CHECK-NEXT: %9 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, 1 +// CHECK-NEXT: %10 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %8, 0 +// CHECK-NEXT: %11 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %10, %"{{.*}}/runtime/internal/runtime.iface" %9, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %11 // CHECK-NEXT: } // CHECK-LABEL: define { i8, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.ReadByte"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call { i8, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadByte"(ptr %2) -// CHECK-NEXT: %4 = extractvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } %3, 0 -// CHECK-NEXT: %5 = extractvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } %3, 1 -// CHECK-NEXT: %6 = insertvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } undef, i8 %4, 0 -// CHECK-NEXT: %7 = insertvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } %6, %"{{.*}}/runtime/internal/runtime.iface" %5, 1 -// CHECK-NEXT: ret { i8, %"{{.*}}/runtime/internal/runtime.iface" } %7 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call { i8, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadByte"(ptr %5) +// CHECK-NEXT: %7 = extractvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } %6, 0 +// CHECK-NEXT: %8 = extractvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } %6, 1 +// CHECK-NEXT: %9 = insertvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } undef, i8 %7, 0 +// CHECK-NEXT: %10 = insertvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } %9, %"{{.*}}/runtime/internal/runtime.iface" %8, 1 +// CHECK-NEXT: ret { i8, %"{{.*}}/runtime/internal/runtime.iface" } %10 // CHECK-NEXT: } // CHECK-LABEL: define { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.ReadBytes"(ptr %0, i8 %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = call { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadBytes"(ptr %3, i8 %1) -// CHECK-NEXT: %5 = extractvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %4, 0 -// CHECK-NEXT: %6 = extractvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %4, 1 -// CHECK-NEXT: %7 = insertvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } undef, %"{{.*}}/runtime/internal/runtime.Slice" %5, 0 -// CHECK-NEXT: %8 = insertvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %7, %"{{.*}}/runtime/internal/runtime.iface" %6, 1 -// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %8 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadBytes"(ptr %6, i8 %1) +// CHECK-NEXT: %8 = extractvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %7, 0 +// CHECK-NEXT: %9 = extractvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %7, 1 +// CHECK-NEXT: %10 = insertvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } undef, %"{{.*}}/runtime/internal/runtime.Slice" %8, 0 +// CHECK-NEXT: %11 = insertvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %10, %"{{.*}}/runtime/internal/runtime.iface" %9, 1 +// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %11 // CHECK-NEXT: } // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.ReadFrom"(ptr %0, %"{{.*}}/runtime/internal/runtime.iface" %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadFrom"(ptr %3, %"{{.*}}/runtime/internal/runtime.iface" %1) -// CHECK-NEXT: %5 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4, 0 -// CHECK-NEXT: %6 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4, 1 -// CHECK-NEXT: %7 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %5, 0 -// CHECK-NEXT: %8 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, %"{{.*}}/runtime/internal/runtime.iface" %6, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %8 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadFrom"(ptr %6, %"{{.*}}/runtime/internal/runtime.iface" %1) +// CHECK-NEXT: %8 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, 0 +// CHECK-NEXT: %9 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, 1 +// CHECK-NEXT: %10 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %8, 0 +// CHECK-NEXT: %11 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %10, %"{{.*}}/runtime/internal/runtime.iface" %9, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %11 // CHECK-NEXT: } // CHECK-LABEL: define { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.ReadRune"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadRune"(ptr %2) -// CHECK-NEXT: %4 = extractvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %3, 0 -// CHECK-NEXT: %5 = extractvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %3, 1 -// CHECK-NEXT: %6 = extractvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %3, 2 -// CHECK-NEXT: %7 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i32 %4, 0 -// CHECK-NEXT: %8 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, i64 %5, 1 -// CHECK-NEXT: %9 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %8, %"{{.*}}/runtime/internal/runtime.iface" %6, 2 -// CHECK-NEXT: ret { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %9 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadRune"(ptr %5) +// CHECK-NEXT: %7 = extractvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %6, 0 +// CHECK-NEXT: %8 = extractvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %6, 1 +// CHECK-NEXT: %9 = extractvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %6, 2 +// CHECK-NEXT: %10 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i32 %7, 0 +// CHECK-NEXT: %11 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %10, i64 %8, 1 +// CHECK-NEXT: %12 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %11, %"{{.*}}/runtime/internal/runtime.iface" %9, 2 +// CHECK-NEXT: ret { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %12 // CHECK-NEXT: } // CHECK-LABEL: define { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.ReadString"(ptr %0, i8 %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = call { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadString"(ptr %3, i8 %1) -// CHECK-NEXT: %5 = extractvalue { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } %4, 0 -// CHECK-NEXT: %6 = extractvalue { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } %4, 1 -// CHECK-NEXT: %7 = insertvalue { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } undef, %"{{.*}}/runtime/internal/runtime.String" %5, 0 -// CHECK-NEXT: %8 = insertvalue { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } %7, %"{{.*}}/runtime/internal/runtime.iface" %6, 1 -// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } %8 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).ReadString"(ptr %6, i8 %1) +// CHECK-NEXT: %8 = extractvalue { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } %7, 0 +// CHECK-NEXT: %9 = extractvalue { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } %7, 1 +// CHECK-NEXT: %10 = insertvalue { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } undef, %"{{.*}}/runtime/internal/runtime.String" %8, 0 +// CHECK-NEXT: %11 = insertvalue { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } %10, %"{{.*}}/runtime/internal/runtime.iface" %9, 1 +// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.String", %"{{.*}}/runtime/internal/runtime.iface" } %11 // CHECK-NEXT: } // CHECK-LABEL: define void @"main.*struct{m int; *bytes.Buffer}.Reset"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: call void @"bytes.(*Buffer).Reset"(ptr %2) +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: call void @"bytes.(*Buffer).Reset"(ptr %5) // CHECK-NEXT: ret void // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @"main.*struct{m int; *bytes.Buffer}.String"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.String" @"bytes.(*Buffer).String"(ptr %2) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %3 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call %"{{.*}}/runtime/internal/runtime.String" @"bytes.(*Buffer).String"(ptr %5) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %6 // CHECK-NEXT: } // CHECK-LABEL: define void @"main.*struct{m int; *bytes.Buffer}.Truncate"(ptr %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: call void @"bytes.(*Buffer).Truncate"(ptr %3, i64 %1) +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: call void @"bytes.(*Buffer).Truncate"(ptr %6, i64 %1) // CHECK-NEXT: ret void // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @"main.*struct{m int; *bytes.Buffer}.UnreadByte"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.iface" @"bytes.(*Buffer).UnreadByte"(ptr %2) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %3 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call %"{{.*}}/runtime/internal/runtime.iface" @"bytes.(*Buffer).UnreadByte"(ptr %5) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %6 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @"main.*struct{m int; *bytes.Buffer}.UnreadRune"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.iface" @"bytes.(*Buffer).UnreadRune"(ptr %2) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %3 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call %"{{.*}}/runtime/internal/runtime.iface" @"bytes.(*Buffer).UnreadRune"(ptr %5) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %6 // CHECK-NEXT: } // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.Write"(ptr %0, %"{{.*}}/runtime/internal/runtime.Slice" %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).Write"(ptr %3, %"{{.*}}/runtime/internal/runtime.Slice" %1) -// CHECK-NEXT: %5 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4, 0 -// CHECK-NEXT: %6 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4, 1 -// CHECK-NEXT: %7 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %5, 0 -// CHECK-NEXT: %8 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, %"{{.*}}/runtime/internal/runtime.iface" %6, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %8 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).Write"(ptr %6, %"{{.*}}/runtime/internal/runtime.Slice" %1) +// CHECK-NEXT: %8 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, 0 +// CHECK-NEXT: %9 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, 1 +// CHECK-NEXT: %10 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %8, 0 +// CHECK-NEXT: %11 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %10, %"{{.*}}/runtime/internal/runtime.iface" %9, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %11 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @"main.*struct{m int; *bytes.Buffer}.WriteByte"(ptr %0, i8 %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = call %"{{.*}}/runtime/internal/runtime.iface" @"bytes.(*Buffer).WriteByte"(ptr %3, i8 %1) -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %4 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call %"{{.*}}/runtime/internal/runtime.iface" @"bytes.(*Buffer).WriteByte"(ptr %6, i8 %1) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %7 // CHECK-NEXT: } // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.WriteRune"(ptr %0, i32 %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).WriteRune"(ptr %3, i32 %1) -// CHECK-NEXT: %5 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4, 0 -// CHECK-NEXT: %6 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4, 1 -// CHECK-NEXT: %7 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %5, 0 -// CHECK-NEXT: %8 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, %"{{.*}}/runtime/internal/runtime.iface" %6, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %8 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).WriteRune"(ptr %6, i32 %1) +// CHECK-NEXT: %8 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, 0 +// CHECK-NEXT: %9 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, 1 +// CHECK-NEXT: %10 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %8, 0 +// CHECK-NEXT: %11 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %10, %"{{.*}}/runtime/internal/runtime.iface" %9, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %11 // CHECK-NEXT: } // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.WriteString"(ptr %0, %"{{.*}}/runtime/internal/runtime.String" %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).WriteString"(ptr %3, %"{{.*}}/runtime/internal/runtime.String" %1) -// CHECK-NEXT: %5 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4, 0 -// CHECK-NEXT: %6 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4, 1 -// CHECK-NEXT: %7 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %5, 0 -// CHECK-NEXT: %8 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, %"{{.*}}/runtime/internal/runtime.iface" %6, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %8 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).WriteString"(ptr %6, %"{{.*}}/runtime/internal/runtime.String" %1) +// CHECK-NEXT: %8 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, 0 +// CHECK-NEXT: %9 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, 1 +// CHECK-NEXT: %10 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %8, 0 +// CHECK-NEXT: %11 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %10, %"{{.*}}/runtime/internal/runtime.iface" %9, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %11 // CHECK-NEXT: } // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.WriteTo"(ptr %0, %"{{.*}}/runtime/internal/runtime.iface" %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).WriteTo"(ptr %3, %"{{.*}}/runtime/internal/runtime.iface" %1) -// CHECK-NEXT: %5 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4, 0 -// CHECK-NEXT: %6 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %4, 1 -// CHECK-NEXT: %7 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %5, 0 -// CHECK-NEXT: %8 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, %"{{.*}}/runtime/internal/runtime.iface" %6, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %8 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).WriteTo"(ptr %6, %"{{.*}}/runtime/internal/runtime.iface" %1) +// CHECK-NEXT: %8 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, 0 +// CHECK-NEXT: %9 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %7, 1 +// CHECK-NEXT: %10 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %8, 0 +// CHECK-NEXT: %11 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %10, %"{{.*}}/runtime/internal/runtime.iface" %9, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %11 // CHECK-NEXT: } // CHECK-LABEL: define i1 @"main.*struct{m int; *bytes.Buffer}.empty"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call i1 @"bytes.(*Buffer).empty"(ptr %2) -// CHECK-NEXT: ret i1 %3 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call i1 @"bytes.(*Buffer).empty"(ptr %5) +// CHECK-NEXT: ret i1 %6 // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.*struct{m int; *bytes.Buffer}.grow"(ptr %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = call i64 @"bytes.(*Buffer).grow"(ptr %3, i64 %1) -// CHECK-NEXT: ret i64 %4 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call i64 @"bytes.(*Buffer).grow"(ptr %6, i64 %1) +// CHECK-NEXT: ret i64 %7 // CHECK-NEXT: } // CHECK-LABEL: define { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"main.*struct{m int; *bytes.Buffer}.readSlice"(ptr %0, i8 %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = call { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).readSlice"(ptr %3, i8 %1) -// CHECK-NEXT: %5 = extractvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %4, 0 -// CHECK-NEXT: %6 = extractvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %4, 1 -// CHECK-NEXT: %7 = insertvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } undef, %"{{.*}}/runtime/internal/runtime.Slice" %5, 0 -// CHECK-NEXT: %8 = insertvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %7, %"{{.*}}/runtime/internal/runtime.iface" %6, 1 -// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %8 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } @"bytes.(*Buffer).readSlice"(ptr %6, i8 %1) +// CHECK-NEXT: %8 = extractvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %7, 0 +// CHECK-NEXT: %9 = extractvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %7, 1 +// CHECK-NEXT: %10 = insertvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } undef, %"{{.*}}/runtime/internal/runtime.Slice" %8, 0 +// CHECK-NEXT: %11 = insertvalue { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %10, %"{{.*}}/runtime/internal/runtime.iface" %9, 1 +// CHECK-NEXT: ret { %"{{.*}}/runtime/internal/runtime.Slice", %"{{.*}}/runtime/internal/runtime.iface" } %11 // CHECK-NEXT: } // CHECK-LABEL: define { i64, i1 } @"main.*struct{m int; *bytes.Buffer}.tryGrowByReslice"(ptr %0, i64 %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = call { i64, i1 } @"bytes.(*Buffer).tryGrowByReslice"(ptr %3, i64 %1) -// CHECK-NEXT: %5 = extractvalue { i64, i1 } %4, 0 -// CHECK-NEXT: %6 = extractvalue { i64, i1 } %4, 1 -// CHECK-NEXT: %7 = insertvalue { i64, i1 } undef, i64 %5, 0 -// CHECK-NEXT: %8 = insertvalue { i64, i1 } %7, i1 %6, 1 -// CHECK-NEXT: ret { i64, i1 } %8 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds { i64, ptr }, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: %7 = call { i64, i1 } @"bytes.(*Buffer).tryGrowByReslice"(ptr %6, i64 %1) +// CHECK-NEXT: %8 = extractvalue { i64, i1 } %7, 0 +// CHECK-NEXT: %9 = extractvalue { i64, i1 } %7, 1 +// CHECK-NEXT: %10 = insertvalue { i64, i1 } undef, i64 %8, 0 +// CHECK-NEXT: %11 = insertvalue { i64, i1 } %10, i1 %9, 1 +// CHECK-NEXT: ret { i64, i1 } %11 // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.struct{m int; *bytes.Buffer}.Available"({ i64, ptr } %0){{.*}} { diff --git a/cl/_testgo/alias/in.go b/cl/_testgo/alias/in.go index 20d91abba6..b38e30ae8c 100644 --- a/cl/_testgo/alias/in.go +++ b/cl/_testgo/alias/in.go @@ -11,16 +11,33 @@ type MyPoint = Point // CHECK-LABEL: define void @"main.(*Point).Move"(ptr %0, double %1, double %2){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %3 = getelementptr inbounds %main.Point, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %4 = load double, ptr %3, align 8 -// CHECK-NEXT: %5 = fadd double %4, %1 -// CHECK-NEXT: %6 = getelementptr inbounds %main.Point, ptr %0, i32 0, i32 0 -// CHECK-NEXT: store double %5, ptr %6, align 8 -// CHECK-NEXT: %7 = getelementptr inbounds %main.Point, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %8 = load double, ptr %7, align 8 -// CHECK-NEXT: %9 = fadd double %8, %2 +// CHECK-NEXT: %4 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %4, label %5, label %6 +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 6: ; preds = %_llgo_0 +// CHECK-NEXT: %7 = load double, ptr %3, align 8 +// CHECK-NEXT: %8 = fadd double %7, %1 +// CHECK-NEXT: %9 = getelementptr inbounds %main.Point, ptr %0, i32 0, i32 0 +// CHECK-NEXT: store double %8, ptr %9, align 8 // CHECK-NEXT: %10 = getelementptr inbounds %main.Point, ptr %0, i32 0, i32 1 -// CHECK-NEXT: store double %9, ptr %10, align 8 +// CHECK-NEXT: %11 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %11, label %12, label %13 +// CHECK-EMPTY: +// CHECK-NEXT: 12: ; preds = %6 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 13: ; preds = %6 +// CHECK-NEXT: %14 = load double, ptr %10, align 8 +// CHECK-NEXT: %15 = fadd double %14, %2 +// CHECK-NEXT: %16 = getelementptr inbounds %main.Point, ptr %0, i32 0, i32 1 +// CHECK-NEXT: store double %15, ptr %16, align 8 // CHECK-NEXT: ret void +// CHECK-NEXT: } func (p *MyPoint) Move(dx, dy float64) { p.x += dx p.y += dy @@ -29,16 +46,33 @@ func (p *MyPoint) Move(dx, dy float64) { // CHECK-LABEL: define void @"main.(*Point).Scale"(ptr %0, double %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = getelementptr inbounds %main.Point, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %3 = load double, ptr %2, align 8 -// CHECK-NEXT: %4 = fmul double %3, %1 -// CHECK-NEXT: %5 = getelementptr inbounds %main.Point, ptr %0, i32 0, i32 0 -// CHECK-NEXT: store double %4, ptr %5, align 8 -// CHECK-NEXT: %6 = getelementptr inbounds %main.Point, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %7 = load double, ptr %6, align 8 -// CHECK-NEXT: %8 = fmul double %7, %1 +// CHECK-NEXT: %3 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %3, label %4, label %5 +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = load double, ptr %2, align 8 +// CHECK-NEXT: %7 = fmul double %6, %1 +// CHECK-NEXT: %8 = getelementptr inbounds %main.Point, ptr %0, i32 0, i32 0 +// CHECK-NEXT: store double %7, ptr %8, align 8 // CHECK-NEXT: %9 = getelementptr inbounds %main.Point, ptr %0, i32 0, i32 1 -// CHECK-NEXT: store double %8, ptr %9, align 8 +// CHECK-NEXT: %10 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %10, label %11, label %12 +// CHECK-EMPTY: +// CHECK-NEXT: 11: ; preds = %5 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 12: ; preds = %5 +// CHECK-NEXT: %13 = load double, ptr %9, align 8 +// CHECK-NEXT: %14 = fmul double %13, %1 +// CHECK-NEXT: %15 = getelementptr inbounds %main.Point, ptr %0, i32 0, i32 1 +// CHECK-NEXT: store double %14, ptr %15, align 8 // CHECK-NEXT: ret void +// CHECK-NEXT: } func (p *Point) Scale(factor float64) { p.x *= factor p.y *= factor diff --git a/cl/_testgo/cgobasic/cgobasic.go b/cl/_testgo/cgobasic/cgobasic.go index 8017d92376..4badd42664 100644 --- a/cl/_testgo/cgobasic/cgobasic.go +++ b/cl/_testgo/cgobasic/cgobasic.go @@ -143,12 +143,20 @@ func main() { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %2 = extractvalue { ptr } %1, 0 -// CHECK-NEXT: %3 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %2, align 8 -// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %3, ptr %4, align 8 -// CHECK-NEXT: %5 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %4, 1 -// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.CBytes"(%"{{.*}}/runtime/internal/runtime.Slice" %3) -// CHECK-NEXT: ret ptr %6 +// CHECK-NEXT: %3 = icmp eq ptr %2, null +// CHECK-NEXT: br i1 %3, label %4, label %5 +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %2, align 8 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 24) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %6, ptr %7, align 8 +// CHECK-NEXT: %8 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"[]_llgo_uint8", ptr undef }, ptr %7, 1 +// CHECK-NEXT: %9 = call ptr @"{{.*}}/runtime/internal/runtime.CBytes"(%"{{.*}}/runtime/internal/runtime.Slice" %6) +// CHECK-NEXT: ret ptr %9 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.Slice" @"main.main$2"(ptr %0){{.*}} { diff --git a/cl/_testgo/closure/in.go b/cl/_testgo/closure/in.go index eabccf6e81..b5730bc645 100644 --- a/cl/_testgo/closure/in.go +++ b/cl/_testgo/closure/in.go @@ -28,14 +28,23 @@ func main() { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = load { ptr }, ptr %0, align 8 // CHECK-NEXT: %3 = extractvalue { ptr } %2, 0 - // CHECK-NEXT: %4 = load %"{{.*}}String", ptr %3, align 8 - // CHECK-NEXT: call void @"{{.*}}PrintString"(%"{{.*}}String" { ptr @2, i64 7 }) - // CHECK-NEXT: call void @"{{.*}}PrintByte"(i8 32) - // CHECK-NEXT: call void @"{{.*}}PrintInt"(i64 %1) - // CHECK-NEXT: call void @"{{.*}}PrintByte"(i8 32) - // CHECK-NEXT: call void @"{{.*}}PrintString"(%"{{.*}}String" %4) - // CHECK-NEXT: call void @"{{.*}}PrintByte"(i8 10) + // CHECK-NEXT: %4 = icmp eq ptr %3, null + // CHECK-NEXT: br i1 %4, label %5, label %6 + // CHECK-EMPTY: + // CHECK-NEXT: 5: ; preds = %_llgo_0 + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) + // CHECK-NEXT: unreachable + // CHECK-EMPTY: + // CHECK-NEXT: 6: ; preds = %_llgo_0 + // CHECK-NEXT: %7 = load %"{{.*}}/runtime/internal/runtime.String", ptr %3, align 8 + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 7 }) + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %1) + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) + // 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: ret void + // CHECK-NEXT: } println("closure", i, env) } v1(100) diff --git a/cl/_testgo/closureall/in.go b/cl/_testgo/closureall/in.go index 185b4f7854..df6c707338 100644 --- a/cl/_testgo/closureall/in.go +++ b/cl/_testgo/closureall/in.go @@ -43,9 +43,17 @@ func (s S) Inc(x int) int { // 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: %3 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %3, label %4, label %5 +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = load i64, ptr %2, align 8 +// CHECK-NEXT: %7 = add i64 %6, %1 +// CHECK-NEXT: ret i64 %7 // CHECK-NEXT: } func (s *S) Add(x int) int { diff --git a/cl/_testgo/cursor/in.go b/cl/_testgo/cursor/in.go index d0a2fc24bf..1cdd7f72fe 100644 --- a/cl/_testgo/cursor/in.go +++ b/cl/_testgo/cursor/in.go @@ -83,144 +83,180 @@ func (c Cursor) Node() ast.Node { // CHECK-NEXT: %32 = getelementptr inbounds %main.Cursor, ptr %2, i32 0, i32 0 // CHECK-NEXT: %33 = load ptr, ptr %32, align 8 // CHECK-NEXT: %34 = getelementptr inbounds %main.Inspector, ptr %33, i32 0, i32 0 -// CHECK-NEXT: %35 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %34, align 8 -// CHECK-NEXT: %36 = load %main.Cursor, ptr %2, align 8 -// CHECK-NEXT: %37 = call { i32, i32 } @main.Cursor.indices(%main.Cursor %36) -// CHECK-NEXT: %38 = extractvalue { i32, i32 } %37, 0 -// CHECK-NEXT: %39 = extractvalue { i32, i32 } %37, 1 -// CHECK-NEXT: br label %_llgo_9 +// CHECK-NEXT: %35 = icmp eq ptr %33, null +// CHECK-NEXT: br i1 %35, label %102, label %103 // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_7, %_llgo_6 // CHECK-NEXT: store %main.Cursor zeroinitializer, ptr %4, align 8 // CHECK-NEXT: store i1 false, ptr %5, align 1 -// CHECK-NEXT: %40 = load %main.Cursor, ptr %4, align 8 -// CHECK-NEXT: %41 = load i1, ptr %5, align 1 -// CHECK-NEXT: %42 = insertvalue { %main.Cursor, i1 } undef, %main.Cursor %40, 0 -// CHECK-NEXT: %43 = insertvalue { %main.Cursor, i1 } %42, i1 %41, 1 -// CHECK-NEXT: ret { %main.Cursor, i1 } %43 +// CHECK-NEXT: %36 = load %main.Cursor, ptr %4, align 8 +// CHECK-NEXT: %37 = load i1, ptr %5, align 1 +// CHECK-NEXT: %38 = insertvalue { %main.Cursor, i1 } undef, %main.Cursor %36, 0 +// CHECK-NEXT: %39 = insertvalue { %main.Cursor, i1 } %38, i1 %37, 1 +// CHECK-NEXT: ret { %main.Cursor, i1 } %39 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_1 -// CHECK-NEXT: %44 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 36 }, ptr %44, align 8 -// CHECK-NEXT: %45 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %44, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %45) +// CHECK-NEXT: %40 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 36 }, ptr %40, align 8 +// CHECK-NEXT: %41 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %40, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %41) // CHECK-NEXT: unreachable // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_1 -// CHECK-NEXT: %46 = icmp eq i64 %23, 0 -// CHECK-NEXT: br i1 %46, label %_llgo_6, label %_llgo_7 +// CHECK-NEXT: %42 = icmp eq i64 %23, 0 +// CHECK-NEXT: br i1 %42, label %_llgo_6, label %_llgo_7 // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_5 // CHECK-NEXT: store i64 -2, ptr %14, align 8 // CHECK-NEXT: br label %_llgo_3 // CHECK-EMPTY: // CHECK-NEXT: _llgo_7: ; preds = %_llgo_5 -// CHECK-NEXT: %47 = icmp eq i64 %23, 1 -// CHECK-NEXT: br i1 %47, label %_llgo_8, label %_llgo_3 +// CHECK-NEXT: %43 = icmp eq i64 %23, 1 +// CHECK-NEXT: br i1 %43, label %_llgo_8, label %_llgo_3 // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_7 -// CHECK-NEXT: %48 = load %main.Cursor, ptr %4, align 8 -// CHECK-NEXT: %49 = load i1, ptr %5, align 1 -// CHECK-NEXT: %50 = insertvalue { %main.Cursor, i1 } undef, %main.Cursor %48, 0 -// CHECK-NEXT: %51 = insertvalue { %main.Cursor, i1 } %50, i1 %49, 1 -// CHECK-NEXT: ret { %main.Cursor, i1 } %51 +// CHECK-NEXT: %44 = load %main.Cursor, ptr %4, align 8 +// CHECK-NEXT: %45 = load i1, ptr %5, align 1 +// CHECK-NEXT: %46 = insertvalue { %main.Cursor, i1 } undef, %main.Cursor %44, 0 +// CHECK-NEXT: %47 = insertvalue { %main.Cursor, i1 } %46, i1 %45, 1 +// CHECK-NEXT: ret { %main.Cursor, i1 } %47 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_9: ; preds = %_llgo_13, %_llgo_2 -// CHECK-NEXT: %52 = phi i32 [ %38, %_llgo_2 ], [ %75, %_llgo_13 ] -// CHECK-NEXT: %53 = icmp slt i32 %52, %39 -// CHECK-NEXT: br i1 %53, label %_llgo_10, label %_llgo_11 +// CHECK-NEXT: _llgo_9: ; preds = %_llgo_13, %103 +// CHECK-NEXT: %48 = phi i32 [ %107, %103 ], [ %68, %_llgo_13 ] +// CHECK-NEXT: %49 = icmp slt i32 %48, %108 +// CHECK-NEXT: br i1 %49, label %_llgo_10, label %_llgo_11 // CHECK-EMPTY: // CHECK-NEXT: _llgo_10: ; preds = %_llgo_9 -// CHECK-NEXT: %54 = alloca %main.event, align 8 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %54, i8 0, i64 32, i1 false) -// CHECK-NEXT: %55 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %35, 0 -// CHECK-NEXT: %56 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %35, 1 -// CHECK-NEXT: %57 = sext i32 %52 to i64 -// CHECK-NEXT: %58 = icmp slt i64 %57, 0 -// CHECK-NEXT: %59 = icmp uge i64 %57, %56 -// CHECK-NEXT: %60 = or i1 %59, %58 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %60, i64 %57, i1 true, i64 %56) -// CHECK-NEXT: %61 = getelementptr inbounds %main.event, ptr %55, i64 %57 -// CHECK-NEXT: %62 = load %main.event, ptr %61, align 8 -// CHECK-NEXT: store %main.event %62, ptr %54, align 8 -// CHECK-NEXT: %63 = getelementptr inbounds %main.event, ptr %54, i32 0, i32 2 -// CHECK-NEXT: %64 = load i32, ptr %63, align 4 -// CHECK-NEXT: %65 = icmp sgt i32 %64, %52 -// CHECK-NEXT: br i1 %65, label %_llgo_12, label %_llgo_13 +// CHECK-NEXT: %50 = alloca %main.event, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %50, i8 0, i64 32, i1 false) +// CHECK-NEXT: %51 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %104, 0 +// CHECK-NEXT: %52 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %104, 1 +// CHECK-NEXT: %53 = sext i32 %48 to i64 +// CHECK-NEXT: %54 = icmp slt i64 %53, 0 +// CHECK-NEXT: %55 = icmp uge i64 %53, %52 +// CHECK-NEXT: %56 = or i1 %55, %54 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %56, i64 %53, i1 true, i64 %52) +// CHECK-NEXT: %57 = getelementptr inbounds %main.event, ptr %51, i64 %53 +// CHECK-NEXT: %58 = icmp eq ptr %33, null +// CHECK-NEXT: br i1 %58, label %109, label %110 // CHECK-EMPTY: // CHECK-NEXT: _llgo_11: ; preds = %_llgo_9 // CHECK-NEXT: store %main.Cursor zeroinitializer, ptr %4, align 8 // CHECK-NEXT: store i1 false, ptr %5, align 1 -// CHECK-NEXT: %66 = load %main.Cursor, ptr %4, align 8 -// CHECK-NEXT: %67 = load i1, ptr %5, align 1 -// CHECK-NEXT: %68 = insertvalue { %main.Cursor, i1 } undef, %main.Cursor %66, 0 -// CHECK-NEXT: %69 = insertvalue { %main.Cursor, i1 } %68, i1 %67, 1 -// CHECK-NEXT: ret { %main.Cursor, i1 } %69 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_12: ; preds = %_llgo_10 -// CHECK-NEXT: %70 = getelementptr inbounds %main.event, ptr %54, i32 0, i32 1 -// CHECK-NEXT: %71 = load i64, ptr %70, align 8 -// CHECK-NEXT: %72 = and i64 %71, %31 -// CHECK-NEXT: %73 = icmp ne i64 %72, 0 -// CHECK-NEXT: br i1 %73, label %_llgo_16, label %_llgo_15 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_13: ; preds = %_llgo_17, %_llgo_15, %_llgo_10 -// CHECK-NEXT: %74 = phi i32 [ %52, %_llgo_10 ], [ %52, %_llgo_15 ], [ %87, %_llgo_17 ] -// CHECK-NEXT: %75 = add i32 %74, 1 +// CHECK-NEXT: %59 = load %main.Cursor, ptr %4, align 8 +// CHECK-NEXT: %60 = load i1, ptr %5, align 1 +// CHECK-NEXT: %61 = insertvalue { %main.Cursor, i1 } undef, %main.Cursor %59, 0 +// CHECK-NEXT: %62 = insertvalue { %main.Cursor, i1 } %61, i1 %60, 1 +// CHECK-NEXT: ret { %main.Cursor, i1 } %62 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %110 +// CHECK-NEXT: %63 = getelementptr inbounds %main.event, ptr %50, i32 0, i32 1 +// CHECK-NEXT: %64 = load i64, ptr %63, align 8 +// CHECK-NEXT: %65 = and i64 %64, %31 +// CHECK-NEXT: %66 = icmp ne i64 %65, 0 +// CHECK-NEXT: br i1 %66, label %_llgo_16, label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_13: ; preds = %_llgo_17, %121, %110 +// CHECK-NEXT: %67 = phi i32 [ %48, %110 ], [ %48, %121 ], [ %80, %_llgo_17 ] +// CHECK-NEXT: %68 = add i32 %67, 1 // CHECK-NEXT: br label %_llgo_9 // CHECK-EMPTY: // CHECK-NEXT: _llgo_14: ; preds = %_llgo_16 -// CHECK-NEXT: %76 = alloca %main.Cursor, align 8 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %76, i8 0, i64 16, i1 false) -// CHECK-NEXT: %77 = getelementptr inbounds %main.Cursor, ptr %76, i32 0, i32 0 -// CHECK-NEXT: %78 = getelementptr inbounds %main.Cursor, ptr %2, i32 0, i32 0 -// CHECK-NEXT: %79 = load ptr, ptr %78, align 8 -// CHECK-NEXT: %80 = getelementptr inbounds %main.Cursor, ptr %76, i32 0, i32 1 -// CHECK-NEXT: store ptr %79, ptr %77, align 8 -// CHECK-NEXT: store i32 %52, ptr %80, align 4 -// CHECK-NEXT: %81 = load %main.Cursor, ptr %76, align 8 -// CHECK-NEXT: store %main.Cursor %81, ptr %4, align 8 +// CHECK-NEXT: %69 = alloca %main.Cursor, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %69, i8 0, i64 16, i1 false) +// CHECK-NEXT: %70 = getelementptr inbounds %main.Cursor, ptr %69, i32 0, i32 0 +// CHECK-NEXT: %71 = getelementptr inbounds %main.Cursor, ptr %2, i32 0, i32 0 +// CHECK-NEXT: %72 = load ptr, ptr %71, align 8 +// CHECK-NEXT: %73 = getelementptr inbounds %main.Cursor, ptr %69, i32 0, i32 1 +// CHECK-NEXT: store ptr %72, ptr %70, align 8 +// CHECK-NEXT: store i32 %48, ptr %73, align 4 +// CHECK-NEXT: %74 = load %main.Cursor, ptr %69, align 8 +// CHECK-NEXT: store %main.Cursor %74, ptr %4, align 8 // CHECK-NEXT: store i1 true, ptr %5, align 1 -// CHECK-NEXT: %82 = load %main.Cursor, ptr %4, align 8 -// CHECK-NEXT: %83 = load i1, ptr %5, align 1 -// CHECK-NEXT: %84 = insertvalue { %main.Cursor, i1 } undef, %main.Cursor %82, 0 -// CHECK-NEXT: %85 = insertvalue { %main.Cursor, i1 } %84, i1 %83, 1 -// CHECK-NEXT: ret { %main.Cursor, i1 } %85 +// CHECK-NEXT: %75 = load %main.Cursor, ptr %4, align 8 +// CHECK-NEXT: %76 = load i1, ptr %5, align 1 +// CHECK-NEXT: %77 = insertvalue { %main.Cursor, i1 } undef, %main.Cursor %75, 0 +// CHECK-NEXT: %78 = insertvalue { %main.Cursor, i1 } %77, i1 %76, 1 +// CHECK-NEXT: ret { %main.Cursor, i1 } %78 // CHECK-EMPTY: // CHECK-NEXT: _llgo_15: ; preds = %_llgo_16, %_llgo_12 -// CHECK-NEXT: %86 = getelementptr inbounds %main.event, ptr %54, i32 0, i32 2 -// CHECK-NEXT: %87 = load i32, ptr %86, align 4 -// CHECK-NEXT: %88 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %35, 0 -// CHECK-NEXT: %89 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %35, 1 -// CHECK-NEXT: %90 = sext i32 %87 to i64 -// CHECK-NEXT: %91 = icmp slt i64 %90, 0 -// CHECK-NEXT: %92 = icmp uge i64 %90, %89 -// CHECK-NEXT: %93 = or i1 %92, %91 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %93, i64 %90, i1 true, i64 %89) -// CHECK-NEXT: %94 = getelementptr inbounds %main.event, ptr %88, i64 %90 -// CHECK-NEXT: %95 = getelementptr inbounds %main.event, ptr %94, i32 0, i32 1 -// CHECK-NEXT: %96 = load i64, ptr %95, align 8 -// CHECK-NEXT: %97 = and i64 %96, %31 -// CHECK-NEXT: %98 = icmp eq i64 %97, 0 -// CHECK-NEXT: br i1 %98, label %_llgo_17, label %_llgo_13 +// CHECK-NEXT: %79 = getelementptr inbounds %main.event, ptr %50, i32 0, i32 2 +// CHECK-NEXT: %80 = load i32, ptr %79, align 4 +// CHECK-NEXT: %81 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %104, 0 +// CHECK-NEXT: %82 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %104, 1 +// CHECK-NEXT: %83 = sext i32 %80 to i64 +// CHECK-NEXT: %84 = icmp slt i64 %83, 0 +// CHECK-NEXT: %85 = icmp uge i64 %83, %82 +// CHECK-NEXT: %86 = or i1 %85, %84 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %86, i64 %83, i1 true, i64 %82) +// CHECK-NEXT: %87 = getelementptr inbounds %main.event, ptr %81, i64 %83 +// CHECK-NEXT: %88 = getelementptr inbounds %main.event, ptr %87, i32 0, i32 1 +// CHECK-NEXT: %89 = icmp eq ptr %33, null +// CHECK-NEXT: br i1 %89, label %116, label %117 // CHECK-EMPTY: // CHECK-NEXT: _llgo_16: ; preds = %_llgo_12 -// CHECK-NEXT: %99 = getelementptr inbounds %main.event, ptr %54, i32 0, i32 0 -// CHECK-NEXT: %100 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %99, align 8 -// CHECK-NEXT: %101 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %3, align 8 -// CHECK-NEXT: %102 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %100) -// CHECK-NEXT: %103 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %100, 1 -// CHECK-NEXT: %104 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %102, 0 -// CHECK-NEXT: %105 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %104, ptr %103, 1 -// CHECK-NEXT: %106 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %101) -// CHECK-NEXT: %107 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %101, 1 -// CHECK-NEXT: %108 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %106, 0 -// CHECK-NEXT: %109 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %108, ptr %107, 1 -// CHECK-NEXT: %110 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %105, %"{{.*}}/runtime/internal/runtime.eface" %109) -// CHECK-NEXT: br i1 %110, label %_llgo_14, label %_llgo_15 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_17: ; preds = %_llgo_15 +// CHECK-NEXT: %90 = getelementptr inbounds %main.event, ptr %50, i32 0, i32 0 +// CHECK-NEXT: %91 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %90, align 8 +// CHECK-NEXT: %92 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %3, align 8 +// CHECK-NEXT: %93 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %91) +// CHECK-NEXT: %94 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %91, 1 +// CHECK-NEXT: %95 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %93, 0 +// CHECK-NEXT: %96 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %95, ptr %94, 1 +// CHECK-NEXT: %97 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %92) +// CHECK-NEXT: %98 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %92, 1 +// CHECK-NEXT: %99 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %97, 0 +// CHECK-NEXT: %100 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %99, ptr %98, 1 +// CHECK-NEXT: %101 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %96, %"{{.*}}/runtime/internal/runtime.eface" %100) +// CHECK-NEXT: br i1 %101, label %_llgo_14, label %_llgo_15 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_17: ; preds = %121 // CHECK-NEXT: br label %_llgo_13 +// CHECK-EMPTY: +// CHECK-NEXT: 102: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 103: ; preds = %_llgo_2 +// CHECK-NEXT: %104 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %34, align 8 +// CHECK-NEXT: %105 = load %main.Cursor, ptr %2, align 8 +// CHECK-NEXT: %106 = call { i32, i32 } @main.Cursor.indices(%main.Cursor %105) +// CHECK-NEXT: %107 = extractvalue { i32, i32 } %106, 0 +// CHECK-NEXT: %108 = extractvalue { i32, i32 } %106, 1 +// CHECK-NEXT: br label %_llgo_9 +// CHECK-EMPTY: +// CHECK-NEXT: 109: ; preds = %_llgo_10 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 110: ; preds = %_llgo_10 +// CHECK-NEXT: %111 = icmp eq ptr %34, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %111) +// CHECK-NEXT: %112 = load %main.event, ptr %57, align 8 +// CHECK-NEXT: store %main.event %112, ptr %50, align 8 +// CHECK-NEXT: %113 = getelementptr inbounds %main.event, ptr %50, i32 0, i32 2 +// CHECK-NEXT: %114 = load i32, ptr %113, align 4 +// CHECK-NEXT: %115 = icmp sgt i32 %114, %48 +// CHECK-NEXT: br i1 %115, label %_llgo_12, label %_llgo_13 +// CHECK-EMPTY: +// CHECK-NEXT: 116: ; preds = %_llgo_15 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 117: ; preds = %_llgo_15 +// CHECK-NEXT: %118 = icmp eq ptr %34, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %118) +// CHECK-NEXT: %119 = icmp eq ptr %87, null +// CHECK-NEXT: br i1 %119, label %120, label %121 +// CHECK-EMPTY: +// CHECK-NEXT: 120: ; preds = %117 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 121: ; preds = %117 +// CHECK-NEXT: %122 = load i64, ptr %88, align 8 +// CHECK-NEXT: %123 = and i64 %122, %31 +// CHECK-NEXT: %124 = icmp eq i64 %123, 0 +// CHECK-NEXT: br i1 %124, label %_llgo_17, label %_llgo_13 // CHECK-NEXT: } func (c Cursor) FindNode(n ast.Node) (Cursor, bool) { @@ -510,38 +546,46 @@ const ( // CHECK-NEXT: store i64 -1, ptr %6, align 8 // CHECK-NEXT: %7 = call %"{{.*}}/runtime/internal/runtime.iface" @main.Cursor.Node(%main.Cursor %1) // CHECK-NEXT: %8 = extractvalue { ptr, ptr, ptr, ptr } %2, 1 -// CHECK-NEXT: %9 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %8, align 8 -// CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %7) -// CHECK-NEXT: %11 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %7, 1 -// CHECK-NEXT: %12 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %10, 0 -// CHECK-NEXT: %13 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %12, ptr %11, 1 -// CHECK-NEXT: %14 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %9) -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %9, 1 -// CHECK-NEXT: %16 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %14, 0 -// CHECK-NEXT: %17 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %16, ptr %15, 1 -// CHECK-NEXT: %18 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %13, %"{{.*}}/runtime/internal/runtime.eface" %17) -// CHECK-NEXT: br i1 %18, label %_llgo_3, label %_llgo_4 +// CHECK-NEXT: %9 = icmp eq ptr %8, null +// CHECK-NEXT: br i1 %9, label %16, label %17 // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %19 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 43 }, 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: %10 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 43 }, ptr %10, align 8 +// CHECK-NEXT: %11 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %10, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %11) // CHECK-NEXT: unreachable // CHECK-EMPTY: -// CHECK-NEXT: _llgo_3: ; preds = %_llgo_1 -// CHECK-NEXT: %21 = extractvalue { ptr, ptr, ptr, ptr } %2, 2 -// CHECK-NEXT: store %main.Cursor %1, ptr %21, align 8 -// CHECK-NEXT: %22 = extractvalue { ptr, ptr, ptr, ptr } %2, 3 -// CHECK-NEXT: store i1 true, ptr %22, align 1 -// CHECK-NEXT: %23 = extractvalue { ptr, ptr, ptr, ptr } %2, 0 -// CHECK-NEXT: store i64 1, ptr %23, align 8 +// CHECK-NEXT: _llgo_3: ; preds = %17 +// CHECK-NEXT: %12 = extractvalue { ptr, ptr, ptr, ptr } %2, 2 +// CHECK-NEXT: store %main.Cursor %1, ptr %12, align 8 +// CHECK-NEXT: %13 = extractvalue { ptr, ptr, ptr, ptr } %2, 3 +// CHECK-NEXT: store i1 true, ptr %13, align 1 +// CHECK-NEXT: %14 = extractvalue { ptr, ptr, ptr, ptr } %2, 0 +// CHECK-NEXT: store i64 1, ptr %14, align 8 // CHECK-NEXT: ret i1 false // CHECK-EMPTY: -// CHECK-NEXT: _llgo_4: ; preds = %_llgo_1 -// CHECK-NEXT: %24 = extractvalue { ptr, ptr, ptr, ptr } %2, 0 -// CHECK-NEXT: store i64 0, ptr %24, align 8 +// CHECK-NEXT: _llgo_4: ; preds = %17 +// CHECK-NEXT: %15 = extractvalue { ptr, ptr, ptr, ptr } %2, 0 +// CHECK-NEXT: store i64 0, ptr %15, align 8 // CHECK-NEXT: ret i1 true +// CHECK-EMPTY: +// CHECK-NEXT: 16: ; preds = %_llgo_1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 17: ; preds = %_llgo_1 +// CHECK-NEXT: %18 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %8, align 8 +// CHECK-NEXT: %19 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %7) +// CHECK-NEXT: %20 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %7, 1 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %19, 0 +// CHECK-NEXT: %22 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %21, ptr %20, 1 +// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %18) +// CHECK-NEXT: %24 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %18, 1 +// CHECK-NEXT: %25 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %23, 0 +// CHECK-NEXT: %26 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %25, ptr %24, 1 +// CHECK-NEXT: %27 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %22, %"{{.*}}/runtime/internal/runtime.eface" %26) +// CHECK-NEXT: br i1 %27, label %_llgo_3, label %_llgo_4 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @main.Cursor.Node(%main.Cursor %0){{.*}} { @@ -561,20 +605,46 @@ const ( // CHECK-NEXT: %5 = getelementptr inbounds %main.Cursor, ptr %1, i32 0, i32 0 // CHECK-NEXT: %6 = load ptr, ptr %5, align 8 // CHECK-NEXT: %7 = getelementptr inbounds %main.Inspector, ptr %6, i32 0, i32 0 -// CHECK-NEXT: %8 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %7, align 8 -// CHECK-NEXT: %9 = getelementptr inbounds %main.Cursor, ptr %1, i32 0, i32 1 -// CHECK-NEXT: %10 = load i32, ptr %9, align 4 -// CHECK-NEXT: %11 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %8, 0 -// CHECK-NEXT: %12 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %8, 1 -// CHECK-NEXT: %13 = sext i32 %10 to i64 -// CHECK-NEXT: %14 = icmp slt i64 %13, 0 -// CHECK-NEXT: %15 = icmp uge i64 %13, %12 -// CHECK-NEXT: %16 = or i1 %15, %14 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %16, i64 %13, i1 true, i64 %12) -// CHECK-NEXT: %17 = getelementptr inbounds %main.event, ptr %11, i64 %13 -// CHECK-NEXT: %18 = getelementptr inbounds %main.event, ptr %17, i32 0, i32 0 -// CHECK-NEXT: %19 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %18, align 8 -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %19 +// CHECK-NEXT: %8 = icmp eq ptr %6, null +// CHECK-NEXT: br i1 %8, label %9, label %10 +// CHECK-EMPTY: +// CHECK-NEXT: 9: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 10: ; preds = %_llgo_2 +// CHECK-NEXT: %11 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %7, align 8 +// CHECK-NEXT: %12 = getelementptr inbounds %main.Cursor, ptr %1, i32 0, i32 1 +// CHECK-NEXT: %13 = load i32, ptr %12, align 4 +// CHECK-NEXT: %14 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %11, 0 +// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %11, 1 +// CHECK-NEXT: %16 = sext i32 %13 to i64 +// CHECK-NEXT: %17 = icmp slt i64 %16, 0 +// CHECK-NEXT: %18 = icmp uge i64 %16, %15 +// CHECK-NEXT: %19 = or i1 %18, %17 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %19, i64 %16, i1 true, i64 %15) +// CHECK-NEXT: %20 = getelementptr inbounds %main.event, ptr %14, i64 %16 +// CHECK-NEXT: %21 = getelementptr inbounds %main.event, ptr %20, i32 0, i32 0 +// CHECK-NEXT: %22 = icmp eq ptr %6, null +// CHECK-NEXT: br i1 %22, label %23, label %24 +// CHECK-EMPTY: +// CHECK-NEXT: 23: ; preds = %10 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 24: ; preds = %10 +// CHECK-NEXT: %25 = icmp eq ptr %7, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %25) +// CHECK-NEXT: %26 = icmp eq ptr %20, null +// CHECK-NEXT: br i1 %26, label %27, label %28 +// CHECK-EMPTY: +// CHECK-NEXT: 27: ; preds = %24 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 28: ; preds = %24 +// CHECK-NEXT: %29 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %21, align 8 +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %29 // CHECK-NEXT: } // CHECK-LABEL: define %"iter.Seq[main.Cursor]" @main.Cursor.Preorder(%main.Cursor %0, %"{{.*}}/runtime/internal/runtime.Slice" %1){{.*}} { @@ -601,94 +671,181 @@ const ( // CHECK-NEXT: %2 = load { ptr, ptr }, ptr %0, align 8 // CHECK-NEXT: %3 = extractvalue { ptr, ptr } %2, 0 // CHECK-NEXT: %4 = getelementptr inbounds %main.Cursor, ptr %3, i32 0, i32 0 -// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 -// CHECK-NEXT: %6 = getelementptr inbounds %main.Inspector, ptr %5, i32 0, i32 0 -// CHECK-NEXT: %7 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %6, align 8 -// CHECK-NEXT: %8 = extractvalue { ptr, ptr } %2, 0 -// CHECK-NEXT: %9 = call ptr @"{{.*}}/runtime/internal/runtime.AssertNilDerefPtr"(ptr %8) -// CHECK-NEXT: %10 = load %main.Cursor, ptr %9, align 8 -// CHECK-NEXT: %11 = call { i32, i32 } @main.Cursor.indices(%main.Cursor %10) -// CHECK-NEXT: %12 = extractvalue { i32, i32 } %11, 0 -// CHECK-NEXT: %13 = extractvalue { i32, i32 } %11, 1 -// CHECK-NEXT: br label %_llgo_1 +// CHECK-NEXT: %5 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %6 = icmp eq ptr %5, null +// CHECK-NEXT: br i1 %6, label %45, label %46 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_5, %_llgo_8, %_llgo_0 -// CHECK-NEXT: %14 = phi i32 [ %12, %_llgo_0 ], [ %60, %_llgo_8 ], [ %34, %_llgo_5 ] -// CHECK-NEXT: %15 = icmp slt i32 %14, %13 -// CHECK-NEXT: br i1 %15, label %_llgo_2, label %_llgo_3 +// CHECK-NEXT: _llgo_1: ; preds = %_llgo_5, %_llgo_8, %56 +// CHECK-NEXT: %7 = phi i32 [ %62, %56 ], [ %44, %_llgo_8 ], [ %25, %_llgo_5 ] +// CHECK-NEXT: %8 = icmp slt i32 %7, %63 +// CHECK-NEXT: br i1 %8, label %_llgo_2, label %_llgo_3 // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_1 -// CHECK-NEXT: %16 = alloca %main.event, align 8 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %16, i8 0, i64 32, i1 false) -// CHECK-NEXT: %17 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %7, 0 -// CHECK-NEXT: %18 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %7, 1 -// CHECK-NEXT: %19 = sext i32 %14 to i64 -// CHECK-NEXT: %20 = icmp slt i64 %19, 0 -// CHECK-NEXT: %21 = icmp uge i64 %19, %18 -// CHECK-NEXT: %22 = or i1 %21, %20 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %22, i64 %19, i1 true, i64 %18) -// CHECK-NEXT: %23 = getelementptr inbounds %main.event, ptr %17, i64 %19 -// CHECK-NEXT: %24 = load %main.event, ptr %23, align 8 -// CHECK-NEXT: store %main.event %24, ptr %16, align 8 -// CHECK-NEXT: %25 = getelementptr inbounds %main.event, ptr %16, i32 0, i32 2 -// CHECK-NEXT: %26 = load i32, ptr %25, align 4 -// CHECK-NEXT: %27 = icmp sgt i32 %26, %14 -// CHECK-NEXT: br i1 %27, label %_llgo_4, label %_llgo_5 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_3: ; preds = %_llgo_7, %_llgo_1 +// CHECK-NEXT: %9 = alloca %main.event, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %9, i8 0, i64 32, i1 false) +// CHECK-NEXT: %10 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %57, 0 +// CHECK-NEXT: %11 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %57, 1 +// CHECK-NEXT: %12 = sext i32 %7 to i64 +// CHECK-NEXT: %13 = icmp slt i64 %12, 0 +// CHECK-NEXT: %14 = icmp uge i64 %12, %11 +// CHECK-NEXT: %15 = or i1 %14, %13 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %15, i64 %12, i1 true, i64 %11) +// CHECK-NEXT: %16 = getelementptr inbounds %main.event, ptr %10, i64 %12 +// CHECK-NEXT: %17 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %18 = icmp eq ptr %17, null +// CHECK-NEXT: br i1 %18, label %64, label %65 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %76, %_llgo_1 // CHECK-NEXT: ret void // CHECK-EMPTY: -// CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 -// CHECK-NEXT: %28 = getelementptr inbounds %main.event, ptr %16, i32 0, i32 1 -// CHECK-NEXT: %29 = load i64, ptr %28, align 8 -// CHECK-NEXT: %30 = extractvalue { ptr, ptr } %2, 1 -// CHECK-NEXT: %31 = load i64, ptr %30, align 8 -// CHECK-NEXT: %32 = and i64 %29, %31 -// CHECK-NEXT: %33 = icmp ne i64 %32, 0 -// CHECK-NEXT: br i1 %33, label %_llgo_7, label %_llgo_6 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_5: ; preds = %_llgo_6, %_llgo_2 -// CHECK-NEXT: %34 = add i32 %14, 1 +// CHECK-NEXT: _llgo_4: ; preds = %69 +// CHECK-NEXT: %19 = getelementptr inbounds %main.event, ptr %9, i32 0, i32 1 +// CHECK-NEXT: %20 = load i64, ptr %19, align 8 +// CHECK-NEXT: %21 = extractvalue { ptr, ptr } %2, 1 +// CHECK-NEXT: %22 = load i64, ptr %21, align 8 +// CHECK-NEXT: %23 = and i64 %20, %22 +// CHECK-NEXT: %24 = icmp ne i64 %23, 0 +// CHECK-NEXT: br i1 %24, label %_llgo_7, label %_llgo_6 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %92, %69 +// CHECK-NEXT: %25 = add i32 %7, 1 // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_6: ; preds = %_llgo_7, %_llgo_4 -// CHECK-NEXT: %35 = getelementptr inbounds %main.event, ptr %16, i32 0, i32 2 -// CHECK-NEXT: %36 = load i32, ptr %35, align 4 -// CHECK-NEXT: %37 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %7, 0 -// CHECK-NEXT: %38 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %7, 1 -// CHECK-NEXT: %39 = sext i32 %36 to i64 -// CHECK-NEXT: %40 = icmp slt i64 %39, 0 -// CHECK-NEXT: %41 = icmp uge i64 %39, %38 -// CHECK-NEXT: %42 = or i1 %41, %40 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %42, i64 %39, i1 true, i64 %38) -// CHECK-NEXT: %43 = getelementptr inbounds %main.event, ptr %37, i64 %39 -// CHECK-NEXT: %44 = getelementptr inbounds %main.event, ptr %43, i32 0, i32 1 -// CHECK-NEXT: %45 = load i64, ptr %44, align 8 -// CHECK-NEXT: %46 = extractvalue { ptr, ptr } %2, 1 -// CHECK-NEXT: %47 = load i64, ptr %46, align 8 -// CHECK-NEXT: %48 = and i64 %45, %47 -// CHECK-NEXT: %49 = icmp eq i64 %48, 0 -// CHECK-NEXT: br i1 %49, label %_llgo_8, label %_llgo_5 +// CHECK-NEXT: _llgo_6: ; preds = %76, %_llgo_4 +// CHECK-NEXT: %26 = getelementptr inbounds %main.event, ptr %9, i32 0, i32 2 +// CHECK-NEXT: %27 = load i32, ptr %26, align 4 +// CHECK-NEXT: %28 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %57, 0 +// CHECK-NEXT: %29 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %57, 1 +// CHECK-NEXT: %30 = sext i32 %27 to i64 +// CHECK-NEXT: %31 = icmp slt i64 %30, 0 +// CHECK-NEXT: %32 = icmp uge i64 %30, %29 +// CHECK-NEXT: %33 = or i1 %32, %31 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %33, i64 %30, i1 true, i64 %29) +// CHECK-NEXT: %34 = getelementptr inbounds %main.event, ptr %28, i64 %30 +// CHECK-NEXT: %35 = getelementptr inbounds %main.event, ptr %34, i32 0, i32 1 +// CHECK-NEXT: %36 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %37 = icmp eq ptr %36, null +// CHECK-NEXT: br i1 %37, label %83, label %84 // CHECK-EMPTY: // CHECK-NEXT: _llgo_7: ; preds = %_llgo_4 -// CHECK-NEXT: %50 = alloca %main.Cursor, align 8 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %50, i8 0, i64 16, i1 false) -// CHECK-NEXT: %51 = getelementptr inbounds %main.Cursor, ptr %50, i32 0, i32 0 -// CHECK-NEXT: %52 = extractvalue { ptr, ptr } %2, 0 -// CHECK-NEXT: %53 = getelementptr inbounds %main.Cursor, ptr %52, i32 0, i32 0 -// CHECK-NEXT: %54 = load ptr, ptr %53, align 8 -// CHECK-NEXT: %55 = getelementptr inbounds %main.Cursor, ptr %50, i32 0, i32 1 -// CHECK-NEXT: store ptr %54, ptr %51, align 8 -// CHECK-NEXT: store i32 %14, ptr %55, align 4 -// CHECK-NEXT: %56 = load %main.Cursor, ptr %50, align 8 -// CHECK-NEXT: %57 = extractvalue { ptr, ptr } %1, 1 -// CHECK-NEXT: %58 = extractvalue { ptr, ptr } %1, 0 -// CHECK-NEXT: %59 = call i1 %58(ptr %57, %main.Cursor %56) -// CHECK-NEXT: br i1 %59, label %_llgo_6, label %_llgo_3 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_8: ; preds = %_llgo_6 -// CHECK-NEXT: %60 = add i32 %36, 1 +// CHECK-NEXT: %38 = alloca %main.Cursor, align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %38, i8 0, i64 16, i1 false) +// CHECK-NEXT: %39 = getelementptr inbounds %main.Cursor, ptr %38, i32 0, i32 0 +// CHECK-NEXT: %40 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %41 = getelementptr inbounds %main.Cursor, ptr %40, i32 0, i32 0 +// CHECK-NEXT: %42 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %43 = icmp eq ptr %42, null +// CHECK-NEXT: br i1 %43, label %75, label %76 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %92 +// CHECK-NEXT: %44 = add i32 %27, 1 +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: 45: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 46: ; preds = %_llgo_0 +// CHECK-NEXT: %47 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %48 = getelementptr inbounds %main.Inspector, ptr %47, i32 0, i32 0 +// CHECK-NEXT: %49 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %50 = icmp eq ptr %49, null +// CHECK-NEXT: br i1 %50, label %51, label %52 +// CHECK-EMPTY: +// CHECK-NEXT: 51: ; preds = %46 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 52: ; preds = %46 +// CHECK-NEXT: %53 = icmp eq ptr %4, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %53) +// CHECK-NEXT: %54 = icmp eq ptr %47, null +// CHECK-NEXT: br i1 %54, label %55, label %56 +// CHECK-EMPTY: +// CHECK-NEXT: 55: ; preds = %52 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 56: ; preds = %52 +// CHECK-NEXT: %57 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %48, align 8 +// CHECK-NEXT: %58 = extractvalue { ptr, ptr } %2, 0 +// CHECK-NEXT: %59 = call ptr @"{{.*}}/runtime/internal/runtime.AssertNilDerefPtr"(ptr %58) +// CHECK-NEXT: %60 = load %main.Cursor, ptr %59, align 8 +// CHECK-NEXT: %61 = call { i32, i32 } @main.Cursor.indices(%main.Cursor %60) +// CHECK-NEXT: %62 = extractvalue { i32, i32 } %61, 0 +// CHECK-NEXT: %63 = extractvalue { i32, i32 } %61, 1 // CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: 64: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 65: ; preds = %_llgo_2 +// CHECK-NEXT: %66 = icmp eq ptr %4, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %66) +// CHECK-NEXT: %67 = icmp eq ptr %47, null +// CHECK-NEXT: br i1 %67, label %68, label %69 +// CHECK-EMPTY: +// CHECK-NEXT: 68: ; preds = %65 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 69: ; preds = %65 +// CHECK-NEXT: %70 = icmp eq ptr %48, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %70) +// CHECK-NEXT: %71 = load %main.event, ptr %16, align 8 +// CHECK-NEXT: store %main.event %71, ptr %9, align 8 +// CHECK-NEXT: %72 = getelementptr inbounds %main.event, ptr %9, i32 0, i32 2 +// CHECK-NEXT: %73 = load i32, ptr %72, align 4 +// CHECK-NEXT: %74 = icmp sgt i32 %73, %7 +// CHECK-NEXT: br i1 %74, label %_llgo_4, label %_llgo_5 +// CHECK-EMPTY: +// CHECK-NEXT: 75: ; preds = %_llgo_7 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 76: ; preds = %_llgo_7 +// CHECK-NEXT: %77 = load ptr, ptr %41, align 8 +// CHECK-NEXT: %78 = getelementptr inbounds %main.Cursor, ptr %38, i32 0, i32 1 +// CHECK-NEXT: store ptr %77, ptr %39, align 8 +// CHECK-NEXT: store i32 %7, ptr %78, align 4 +// CHECK-NEXT: %79 = load %main.Cursor, ptr %38, align 8 +// CHECK-NEXT: %80 = extractvalue { ptr, ptr } %1, 1 +// CHECK-NEXT: %81 = extractvalue { ptr, ptr } %1, 0 +// CHECK-NEXT: %82 = call i1 %81(ptr %80, %main.Cursor %79) +// CHECK-NEXT: br i1 %82, label %_llgo_6, label %_llgo_3 +// CHECK-EMPTY: +// CHECK-NEXT: 83: ; preds = %_llgo_6 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 84: ; preds = %_llgo_6 +// CHECK-NEXT: %85 = icmp eq ptr %4, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %85) +// CHECK-NEXT: %86 = icmp eq ptr %47, null +// CHECK-NEXT: br i1 %86, label %87, label %88 +// CHECK-EMPTY: +// CHECK-NEXT: 87: ; preds = %84 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 88: ; preds = %84 +// CHECK-NEXT: %89 = icmp eq ptr %48, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %89) +// CHECK-NEXT: %90 = icmp eq ptr %34, null +// CHECK-NEXT: br i1 %90, label %91, label %92 +// CHECK-EMPTY: +// CHECK-NEXT: 91: ; preds = %88 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 92: ; preds = %88 +// CHECK-NEXT: %93 = load i64, ptr %35, align 8 +// CHECK-NEXT: %94 = extractvalue { ptr, ptr } %2, 1 +// CHECK-NEXT: %95 = load i64, ptr %94, align 8 +// CHECK-NEXT: %96 = and i64 %93, %95 +// CHECK-NEXT: %97 = icmp eq i64 %96, 0 +// CHECK-NEXT: br i1 %97, label %_llgo_8, label %_llgo_5 // CHECK-NEXT: } // CHECK-LABEL: define { i32, i32 } @main.Cursor.indices(%main.Cursor %0){{.*}} { @@ -705,35 +862,69 @@ const ( // CHECK-NEXT: %5 = getelementptr inbounds %main.Cursor, ptr %1, i32 0, i32 0 // CHECK-NEXT: %6 = load ptr, ptr %5, align 8 // CHECK-NEXT: %7 = getelementptr inbounds %main.Inspector, ptr %6, i32 0, i32 0 -// CHECK-NEXT: %8 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %7, align 8 -// CHECK-NEXT: %9 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %8, 1 -// CHECK-NEXT: %10 = trunc i64 %9 to i32 -// CHECK-NEXT: %11 = insertvalue { i32, i32 } { i32 0, i32 undef }, i32 %10, 1 -// CHECK-NEXT: ret { i32, i32 } %11 +// CHECK-NEXT: %8 = icmp eq ptr %6, null +// CHECK-NEXT: br i1 %8, label %15, label %16 // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %12 = getelementptr inbounds %main.Cursor, ptr %1, i32 0, i32 1 -// CHECK-NEXT: %13 = load i32, ptr %12, align 4 -// CHECK-NEXT: %14 = getelementptr inbounds %main.Cursor, ptr %1, i32 0, i32 0 -// CHECK-NEXT: %15 = load ptr, ptr %14, align 8 -// CHECK-NEXT: %16 = getelementptr inbounds %main.Inspector, ptr %15, i32 0, i32 0 -// CHECK-NEXT: %17 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %16, align 8 -// CHECK-NEXT: %18 = getelementptr inbounds %main.Cursor, ptr %1, i32 0, i32 1 -// CHECK-NEXT: %19 = load i32, ptr %18, align 4 -// CHECK-NEXT: %20 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %17, 0 -// CHECK-NEXT: %21 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %17, 1 -// CHECK-NEXT: %22 = sext i32 %19 to i64 -// CHECK-NEXT: %23 = icmp slt i64 %22, 0 -// CHECK-NEXT: %24 = icmp uge i64 %22, %21 -// CHECK-NEXT: %25 = or i1 %24, %23 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %25, i64 %22, i1 true, i64 %21) -// CHECK-NEXT: %26 = getelementptr inbounds %main.event, ptr %20, i64 %22 -// CHECK-NEXT: %27 = getelementptr inbounds %main.event, ptr %26, i32 0, i32 2 -// CHECK-NEXT: %28 = load i32, ptr %27, align 4 -// CHECK-NEXT: %29 = add i32 %28, 1 -// CHECK-NEXT: %30 = insertvalue { i32, i32 } undef, i32 %13, 0 -// CHECK-NEXT: %31 = insertvalue { i32, i32 } %30, i32 %29, 1 -// CHECK-NEXT: ret { i32, i32 } %31 +// CHECK-NEXT: %9 = getelementptr inbounds %main.Cursor, ptr %1, i32 0, i32 1 +// CHECK-NEXT: %10 = load i32, ptr %9, align 4 +// CHECK-NEXT: %11 = getelementptr inbounds %main.Cursor, ptr %1, i32 0, i32 0 +// CHECK-NEXT: %12 = load ptr, ptr %11, align 8 +// CHECK-NEXT: %13 = getelementptr inbounds %main.Inspector, ptr %12, i32 0, i32 0 +// CHECK-NEXT: %14 = icmp eq ptr %12, null +// CHECK-NEXT: br i1 %14, label %21, label %22 +// CHECK-EMPTY: +// CHECK-NEXT: 15: ; preds = %_llgo_1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 16: ; preds = %_llgo_1 +// CHECK-NEXT: %17 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %7, align 8 +// CHECK-NEXT: %18 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %17, 1 +// CHECK-NEXT: %19 = trunc i64 %18 to i32 +// CHECK-NEXT: %20 = insertvalue { i32, i32 } { i32 0, i32 undef }, i32 %19, 1 +// CHECK-NEXT: ret { i32, i32 } %20 +// CHECK-EMPTY: +// CHECK-NEXT: 21: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 22: ; preds = %_llgo_2 +// CHECK-NEXT: %23 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %13, align 8 +// CHECK-NEXT: %24 = getelementptr inbounds %main.Cursor, ptr %1, i32 0, i32 1 +// CHECK-NEXT: %25 = load i32, ptr %24, align 4 +// CHECK-NEXT: %26 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %23, 0 +// CHECK-NEXT: %27 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %23, 1 +// CHECK-NEXT: %28 = sext i32 %25 to i64 +// CHECK-NEXT: %29 = icmp slt i64 %28, 0 +// CHECK-NEXT: %30 = icmp uge i64 %28, %27 +// CHECK-NEXT: %31 = or i1 %30, %29 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %31, i64 %28, i1 true, i64 %27) +// CHECK-NEXT: %32 = getelementptr inbounds %main.event, ptr %26, i64 %28 +// CHECK-NEXT: %33 = getelementptr inbounds %main.event, ptr %32, i32 0, i32 2 +// CHECK-NEXT: %34 = icmp eq ptr %12, null +// CHECK-NEXT: br i1 %34, label %35, label %36 +// CHECK-EMPTY: +// CHECK-NEXT: 35: ; preds = %22 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 36: ; preds = %22 +// CHECK-NEXT: %37 = icmp eq ptr %13, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %37) +// CHECK-NEXT: %38 = icmp eq ptr %32, null +// CHECK-NEXT: br i1 %38, label %39, label %40 +// CHECK-EMPTY: +// CHECK-NEXT: 39: ; preds = %36 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 40: ; preds = %36 +// CHECK-NEXT: %41 = load i32, ptr %33, align 4 +// CHECK-NEXT: %42 = add i32 %41, 1 +// CHECK-NEXT: %43 = insertvalue { i32, i32 } undef, i32 %10, 0 +// CHECK-NEXT: %44 = insertvalue { i32, i32 } %43, i32 %42, 1 +// CHECK-NEXT: ret { i32, i32 } %44 // CHECK-NEXT: } // CHECK-LABEL: define { %main.Cursor, i1 } @"main.(*Cursor).FindNode"(ptr %0, %"{{.*}}/runtime/internal/runtime.iface" %1){{.*}} { diff --git a/cl/_testgo/embedunexport-1598/in.go b/cl/_testgo/embedunexport-1598/in.go index 4f9a0b9568..503eb3d9de 100644 --- a/cl/_testgo/embedunexport-1598/in.go +++ b/cl/_testgo/embedunexport-1598/in.go @@ -30,17 +30,35 @@ type Wrapped struct { // CHECK-LABEL: define %"{{.*}}String" @"main.(*Wrapped).Name"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds %main.Wrapped, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call %"{{.*}}String" @"{{.*}}embedunexport.(*Base).Name"(ptr %2) -// CHECK-NEXT: ret %"{{.*}}String" %3 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds %main.Wrapped, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/cl/_testdata/embedunexport.(*Base).Name"(ptr %5) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %6 +// CHECK-NEXT: } // CHECK-LABEL: define void @"main.(*Wrapped).setName"(ptr %0, %"{{.*}}String" %1){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %2 = getelementptr inbounds %main.Wrapped, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: call void @"{{.*}}embedunexport.(*Base).setName"(ptr %3, %"{{.*}}String" %1) +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = getelementptr inbounds %main.Wrapped, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %6 = load ptr, ptr %5, align 8 +// CHECK-NEXT: call void @"{{.*}}/cl/_testdata/embedunexport.(*Base).setName"(ptr %6, %"{{.*}}/runtime/internal/runtime.String" %1) // CHECK-NEXT: ret void +// CHECK-NEXT: } // CHECK-LABEL: define void @main.main(){{.*}} { func main() { diff --git a/cl/_testgo/errors/in.go b/cl/_testgo/errors/in.go index 01af262dcb..b720c46f74 100644 --- a/cl/_testgo/errors/in.go +++ b/cl/_testgo/errors/in.go @@ -24,8 +24,17 @@ type errorString struct { // CHECK-LABEL: define %"{{.*}}String" @"main.(*errorString).Error"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.errorString, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load %"{{.*}}String", ptr %1, align 8 -// CHECK-NEXT: ret %"{{.*}}String" %2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load %"{{.*}}/runtime/internal/runtime.String", ptr %1, align 8 +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %5 +// CHECK-NEXT: } func (e *errorString) Error() string { return e.s } diff --git a/cl/_testgo/genericembediface/in.go b/cl/_testgo/genericembediface/in.go index 3ac1e4ccef..0dfc2415f2 100644 --- a/cl/_testgo/genericembediface/in.go +++ b/cl/_testgo/genericembediface/in.go @@ -142,17 +142,25 @@ func main() { // CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/cl/_testgo/genericembediface/streamlib.(*GenericServerStream[main.Request,main.Response]).Context"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %"{{.*}}/cl/_testgo/genericembediface/streamlib.GenericServerStream[main.Request,main.Response]", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %1, align 8 -// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: %4 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %2, 0 -// CHECK-NEXT: %5 = getelementptr ptr, ptr %4, i64 3 -// 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: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %1, align 8 +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %5) +// CHECK-NEXT: %7 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %5, 0 +// CHECK-NEXT: %8 = getelementptr ptr, ptr %7, i64 3 +// CHECK-NEXT: %9 = load ptr, ptr %8, align 8 +// CHECK-NEXT: %10 = insertvalue { ptr, ptr } undef, ptr %9, 0 +// CHECK-NEXT: %11 = insertvalue { ptr, ptr } %10, ptr %6, 1 +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %11, 1 +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %11, 0 +// CHECK-NEXT: %14 = call %"{{.*}}/runtime/internal/runtime.String" %13(ptr %12) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %14 // 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){{.*}} { diff --git a/cl/_testgo/ifaceprom/in.go b/cl/_testgo/ifaceprom/in.go index b75d561191..981b00dc55 100644 --- a/cl/_testgo/ifaceprom/in.go +++ b/cl/_testgo/ifaceprom/in.go @@ -107,33 +107,49 @@ func main() { // CHECK-LABEL: define i64 @"main.(*S).one"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.S, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %1, align 8 -// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: %4 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %2, 0 -// CHECK-NEXT: %5 = getelementptr ptr, ptr %4, i64 3 -// 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: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %1, align 8 +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %5) +// CHECK-NEXT: %7 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %5, 0 +// CHECK-NEXT: %8 = getelementptr ptr, ptr %7, i64 3 +// CHECK-NEXT: %9 = load ptr, ptr %8, align 8 +// CHECK-NEXT: %10 = insertvalue { ptr, ptr } undef, ptr %9, 0 +// CHECK-NEXT: %11 = insertvalue { ptr, ptr } %10, ptr %6, 1 +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %11, 1 +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %11, 0 +// CHECK-NEXT: %14 = call i64 %13(ptr %12) +// CHECK-NEXT: ret i64 %14 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @"main.(*S).two"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.S, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %1, align 8 -// CHECK-NEXT: %3 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %2) -// CHECK-NEXT: %4 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %2, 0 -// CHECK-NEXT: %5 = getelementptr ptr, ptr %4, i64 4 -// 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: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %1, align 8 +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %5) +// CHECK-NEXT: %7 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %5, 0 +// CHECK-NEXT: %8 = getelementptr ptr, ptr %7, i64 4 +// CHECK-NEXT: %9 = load ptr, ptr %8, align 8 +// CHECK-NEXT: %10 = insertvalue { ptr, ptr } undef, ptr %9, 0 +// CHECK-NEXT: %11 = insertvalue { ptr, ptr } %10, ptr %6, 1 +// CHECK-NEXT: %12 = extractvalue { ptr, ptr } %11, 1 +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %11, 0 +// CHECK-NEXT: %14 = call %"{{.*}}/runtime/internal/runtime.String" %13(ptr %12) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %14 // CHECK-NEXT: } // CHECK-LABEL: define i64 @main.impl.one(%main.impl %0){{.*}} { diff --git a/cl/_testgo/invoke/in.go b/cl/_testgo/invoke/in.go index e48e4ea7f5..a03f51f239 100644 --- a/cl/_testgo/invoke/in.go +++ b/cl/_testgo/invoke/in.go @@ -210,12 +210,18 @@ type M interface { // CHECK-LABEL: define i64 @"main.(*T3).Invoke"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = icmp eq ptr %0, null -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %1) -// CHECK-NEXT: %2 = load i8, ptr %0, align 1 +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = load i8, ptr %0, align 1 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @7, i64 7 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: %3 = sext i8 %2 to i64 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %3) +// CHECK-NEXT: %5 = sext i8 %4 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %5) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret i64 3 // CHECK-NEXT: } diff --git a/cl/_testgo/reader/in.go b/cl/_testgo/reader/in.go index bf9d1c0934..0113a15a9a 100644 --- a/cl/_testgo/reader/in.go +++ b/cl/_testgo/reader/in.go @@ -505,8 +505,16 @@ type errorString struct { // 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 -// CHECK-NEXT: %2 = load %"{{.*}}/runtime/internal/runtime.String", ptr %1, align 8 -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load %"{{.*}}/runtime/internal/runtime.String", ptr %1, align 8 +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %5 // CHECK-NEXT: } // CHECK-LABEL: define void @main.init(){{.*}} { @@ -612,21 +620,29 @@ func main() { // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*nopCloser).Read"(ptr %0, %"{{.*}}/runtime/internal/runtime.Slice" %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = getelementptr inbounds %main.nopCloser, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %3 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %2, align 8 -// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %3) -// CHECK-NEXT: %5 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %3, 0 -// CHECK-NEXT: %6 = getelementptr ptr, ptr %5, i64 3 -// 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: %3 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %3, label %4, label %5 +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %2, align 8 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %6) +// CHECK-NEXT: %8 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %6, 0 +// CHECK-NEXT: %9 = getelementptr ptr, ptr %8, i64 3 +// CHECK-NEXT: %10 = load ptr, ptr %9, align 8 +// CHECK-NEXT: %11 = insertvalue { ptr, ptr } undef, ptr %10, 0 +// CHECK-NEXT: %12 = insertvalue { ptr, ptr } %11, ptr %7, 1 +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %12, 1 +// CHECK-NEXT: %14 = extractvalue { ptr, ptr } %12, 0 +// CHECK-NEXT: %15 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } %14(ptr %13, %"{{.*}}/runtime/internal/runtime.Slice" %1) +// 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.nopCloserWriterTo.Close(%main.nopCloserWriterTo %0){{.*}} { @@ -705,21 +721,29 @@ func main() { // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*nopCloserWriterTo).Read"(ptr %0, %"{{.*}}/runtime/internal/runtime.Slice" %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = getelementptr inbounds %main.nopCloserWriterTo, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %3 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %2, align 8 -// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %3) -// CHECK-NEXT: %5 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %3, 0 -// CHECK-NEXT: %6 = getelementptr ptr, ptr %5, i64 3 -// 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: %3 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %3, label %4, label %5 +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = load %"{{.*}}/runtime/internal/runtime.iface", ptr %2, align 8 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.IfacePtrData"(%"{{.*}}/runtime/internal/runtime.iface" %6) +// CHECK-NEXT: %8 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %6, 0 +// CHECK-NEXT: %9 = getelementptr ptr, ptr %8, i64 3 +// CHECK-NEXT: %10 = load ptr, ptr %9, align 8 +// CHECK-NEXT: %11 = insertvalue { ptr, ptr } undef, ptr %10, 0 +// CHECK-NEXT: %12 = insertvalue { ptr, ptr } %11, ptr %7, 1 +// CHECK-NEXT: %13 = extractvalue { ptr, ptr } %12, 1 +// CHECK-NEXT: %14 = extractvalue { ptr, ptr } %12, 0 +// CHECK-NEXT: %15 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } %14(ptr %13, %"{{.*}}/runtime/internal/runtime.Slice" %1) +// 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"(ptr %0, %"{{.*}}/runtime/internal/runtime.iface" %1){{.*}} { @@ -738,61 +762,133 @@ func main() { // CHECK-LABEL: define i64 @"main.(*stringReader).Len"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load i64, ptr %1, align 8 -// CHECK-NEXT: %3 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %4 = load %"{{.*}}/runtime/internal/runtime.String", ptr %3, align 8 -// CHECK-NEXT: %5 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %4, 1 -// CHECK-NEXT: %6 = icmp sge i64 %2, %5 -// CHECK-NEXT: br i1 %6, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %5, label %6 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: _llgo_1: ; preds = %11 // CHECK-NEXT: ret i64 0 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %7 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %8 = load %"{{.*}}/runtime/internal/runtime.String", ptr %7, align 8 -// CHECK-NEXT: %9 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %8, 1 -// CHECK-NEXT: %10 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %11 = load i64, ptr %10, align 8 -// CHECK-NEXT: %12 = sub i64 %9, %11 -// CHECK-NEXT: ret i64 %12 +// CHECK-NEXT: _llgo_2: ; preds = %11 +// CHECK-NEXT: %3 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %4 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %4, label %15, label %16 +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 6: ; preds = %_llgo_0 +// CHECK-NEXT: %7 = load i64, ptr %1, align 8 +// CHECK-NEXT: %8 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %9 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %9, label %10, label %11 +// CHECK-EMPTY: +// CHECK-NEXT: 10: ; preds = %6 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 11: ; preds = %6 +// CHECK-NEXT: %12 = load %"{{.*}}/runtime/internal/runtime.String", ptr %8, align 8 +// CHECK-NEXT: %13 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %12, 1 +// CHECK-NEXT: %14 = icmp sge i64 %7, %13 +// CHECK-NEXT: br i1 %14, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: 15: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 16: ; preds = %_llgo_2 +// CHECK-NEXT: %17 = load %"{{.*}}/runtime/internal/runtime.String", ptr %3, align 8 +// CHECK-NEXT: %18 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %17, 1 +// CHECK-NEXT: %19 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %20 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %20, label %21, label %22 +// CHECK-EMPTY: +// CHECK-NEXT: 21: ; preds = %16 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 22: ; preds = %16 +// CHECK-NEXT: %23 = load i64, ptr %19, align 8 +// CHECK-NEXT: %24 = sub i64 %18, %23 +// CHECK-NEXT: ret i64 %24 // CHECK-NEXT: } // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*stringReader).Read"(ptr %0, %"{{.*}}/runtime/internal/runtime.Slice" %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load i64, ptr %2, align 8 -// CHECK-NEXT: %4 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %5 = load %"{{.*}}/runtime/internal/runtime.String", ptr %4, align 8 -// CHECK-NEXT: %6 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %5, 1 -// CHECK-NEXT: %7 = icmp sge i64 %3, %6 -// CHECK-NEXT: br i1 %7, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %3 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %3, label %9, label %10 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %8 = load %"{{.*}}/runtime/internal/runtime.iface", ptr @main.EOF, align 8 -// CHECK-NEXT: %9 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } { i64 0, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %8, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %9 +// CHECK-NEXT: _llgo_1: ; preds = %15 +// CHECK-NEXT: %4 = load %"{{.*}}/runtime/internal/runtime.iface", ptr @main.EOF, align 8 +// 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: -// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %10 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 -// CHECK-NEXT: store i64 -1, ptr %10, align 8 -// CHECK-NEXT: %11 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %12 = load %"{{.*}}/runtime/internal/runtime.String", ptr %11, align 8 -// CHECK-NEXT: %13 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %14 = load i64, ptr %13, align 8 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %12, 1 -// CHECK-NEXT: %16 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringSlice2"(%"{{.*}}/runtime/internal/runtime.String" %12, i64 %14, i64 %15, i1 true, i1 true) -// CHECK-NEXT: %17 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %16, 0 -// CHECK-NEXT: %18 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %16, 1 -// CHECK-NEXT: %19 = call i64 @"{{.*}}/runtime/internal/runtime.SliceCopy"(%"{{.*}}/runtime/internal/runtime.Slice" %1, ptr %17, i64 %18, i64 1) -// CHECK-NEXT: %20 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %21 = load i64, ptr %20, align 8 -// CHECK-NEXT: %22 = add i64 %21, %19 -// CHECK-NEXT: %23 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: store i64 %22, ptr %23, align 8 -// CHECK-NEXT: %24 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %19, 0 -// CHECK-NEXT: %25 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %24, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %25 +// CHECK-NEXT: _llgo_2: ; preds = %15 +// CHECK-NEXT: %6 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 +// CHECK-NEXT: store i64 -1, ptr %6, align 8 +// CHECK-NEXT: %7 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %8 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %8, label %19, label %20 +// CHECK-EMPTY: +// CHECK-NEXT: 9: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 10: ; preds = %_llgo_0 +// CHECK-NEXT: %11 = load i64, ptr %2, align 8 +// CHECK-NEXT: %12 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %13 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %13, label %14, label %15 +// CHECK-EMPTY: +// CHECK-NEXT: 14: ; preds = %10 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 15: ; preds = %10 +// CHECK-NEXT: %16 = load %"{{.*}}/runtime/internal/runtime.String", ptr %12, align 8 +// CHECK-NEXT: %17 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %16, 1 +// CHECK-NEXT: %18 = icmp sge i64 %11, %17 +// CHECK-NEXT: br i1 %18, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: 19: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 20: ; preds = %_llgo_2 +// CHECK-NEXT: %21 = load %"{{.*}}/runtime/internal/runtime.String", ptr %7, align 8 +// CHECK-NEXT: %22 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %23 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %23, label %24, label %25 +// CHECK-EMPTY: +// CHECK-NEXT: 24: ; preds = %20 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 25: ; preds = %20 +// CHECK-NEXT: %26 = load i64, ptr %22, align 8 +// CHECK-NEXT: %27 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %21, 1 +// CHECK-NEXT: %28 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringSlice2"(%"{{.*}}/runtime/internal/runtime.String" %21, i64 %26, i64 %27, i1 true, i1 true) +// CHECK-NEXT: %29 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %28, 0 +// CHECK-NEXT: %30 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %28, 1 +// CHECK-NEXT: %31 = call i64 @"{{.*}}/runtime/internal/runtime.SliceCopy"(%"{{.*}}/runtime/internal/runtime.Slice" %1, ptr %29, i64 %30, i64 1) +// CHECK-NEXT: %32 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %33 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %33, label %34, label %35 +// CHECK-EMPTY: +// CHECK-NEXT: 34: ; preds = %25 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 35: ; preds = %25 +// CHECK-NEXT: %36 = load i64, ptr %32, align 8 +// CHECK-NEXT: %37 = add i64 %36, %31 +// CHECK-NEXT: %38 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: store i64 %37, ptr %38, align 8 +// CHECK-NEXT: %39 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %31, 0 +// CHECK-NEXT: %40 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %39, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %40 // CHECK-NEXT: } // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*stringReader).ReadAt"(ptr %0, %"{{.*}}/runtime/internal/runtime.Slice" %1, i64 %2){{.*}} { @@ -807,37 +903,53 @@ func main() { // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 // CHECK-NEXT: %6 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %7 = load %"{{.*}}/runtime/internal/runtime.String", ptr %6, align 8 -// CHECK-NEXT: %8 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %7, 1 -// CHECK-NEXT: %9 = icmp sge i64 %2, %8 -// CHECK-NEXT: br i1 %9, label %_llgo_3, label %_llgo_4 +// CHECK-NEXT: %7 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %7, label %16, label %17 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %17 +// CHECK-NEXT: %8 = load %"{{.*}}/runtime/internal/runtime.iface", ptr @main.EOF, align 8 +// CHECK-NEXT: %9 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } { i64 0, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %8, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %9 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 -// CHECK-NEXT: %10 = load %"{{.*}}/runtime/internal/runtime.iface", ptr @main.EOF, align 8 -// CHECK-NEXT: %11 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } { i64 0, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %10, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %11 +// CHECK-NEXT: _llgo_4: ; preds = %17 +// CHECK-NEXT: %10 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %11 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %11, label %21, label %22 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 -// CHECK-NEXT: %12 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %13 = load %"{{.*}}/runtime/internal/runtime.String", ptr %12, align 8 -// CHECK-NEXT: %14 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %13, 1 -// CHECK-NEXT: %15 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringSlice2"(%"{{.*}}/runtime/internal/runtime.String" %13, i64 %2, i64 %14, i1 true, i1 true) -// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %15, 0 -// CHECK-NEXT: %17 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %15, 1 -// CHECK-NEXT: %18 = call i64 @"{{.*}}/runtime/internal/runtime.SliceCopy"(%"{{.*}}/runtime/internal/runtime.Slice" %1, ptr %16, i64 %17, i64 1) -// CHECK-NEXT: %19 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 1 -// CHECK-NEXT: %20 = icmp slt i64 %18, %19 -// CHECK-NEXT: br i1 %20, label %_llgo_5, label %_llgo_6 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_5: ; preds = %_llgo_4 -// CHECK-NEXT: %21 = load %"{{.*}}/runtime/internal/runtime.iface", ptr @main.EOF, align 8 +// CHECK-NEXT: _llgo_5: ; preds = %22 +// CHECK-NEXT: %12 = load %"{{.*}}/runtime/internal/runtime.iface", ptr @main.EOF, align 8 // CHECK-NEXT: br label %_llgo_6 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_6: ; preds = %_llgo_5, %_llgo_4 -// CHECK-NEXT: %22 = phi %"{{.*}}/runtime/internal/runtime.iface" [ zeroinitializer, %_llgo_4 ], [ %21, %_llgo_5 ] -// CHECK-NEXT: %23 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %18, 0 -// CHECK-NEXT: %24 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %23, %"{{.*}}/runtime/internal/runtime.iface" %22, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %24 +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_5, %22 +// CHECK-NEXT: %13 = phi %"{{.*}}/runtime/internal/runtime.iface" [ zeroinitializer, %22 ], [ %12, %_llgo_5 ] +// CHECK-NEXT: %14 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %28, 0 +// CHECK-NEXT: %15 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %14, %"{{.*}}/runtime/internal/runtime.iface" %13, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %15 +// CHECK-EMPTY: +// CHECK-NEXT: 16: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 17: ; preds = %_llgo_2 +// CHECK-NEXT: %18 = load %"{{.*}}/runtime/internal/runtime.String", ptr %6, align 8 +// CHECK-NEXT: %19 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %18, 1 +// CHECK-NEXT: %20 = icmp sge i64 %2, %19 +// CHECK-NEXT: br i1 %20, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: 21: ; preds = %_llgo_4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 22: ; preds = %_llgo_4 +// CHECK-NEXT: %23 = load %"{{.*}}/runtime/internal/runtime.String", ptr %10, align 8 +// CHECK-NEXT: %24 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %23, 1 +// CHECK-NEXT: %25 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringSlice2"(%"{{.*}}/runtime/internal/runtime.String" %23, i64 %2, i64 %24, i1 true, i1 true) +// CHECK-NEXT: %26 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %25, 0 +// CHECK-NEXT: %27 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %25, 1 +// CHECK-NEXT: %28 = call i64 @"{{.*}}/runtime/internal/runtime.SliceCopy"(%"{{.*}}/runtime/internal/runtime.Slice" %1, ptr %26, i64 %27, i64 1) +// CHECK-NEXT: %29 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 1 +// CHECK-NEXT: %30 = icmp slt i64 %28, %29 +// CHECK-NEXT: br i1 %30, label %_llgo_5, label %_llgo_6 // CHECK-NEXT: } // CHECK-LABEL: define { i8, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*stringReader).ReadByte"(ptr %0){{.*}} { @@ -845,109 +957,221 @@ func main() { // CHECK-NEXT: %1 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 // CHECK-NEXT: store i64 -1, ptr %1, align 8 // CHECK-NEXT: %2 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %3 = load i64, ptr %2, align 8 -// CHECK-NEXT: %4 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %5 = load %"{{.*}}/runtime/internal/runtime.String", ptr %4, align 8 -// CHECK-NEXT: %6 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %5, 1 -// CHECK-NEXT: %7 = icmp sge i64 %3, %6 -// CHECK-NEXT: br i1 %7, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %3 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %3, label %8, label %9 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %8 = load %"{{.*}}/runtime/internal/runtime.iface", ptr @main.EOF, align 8 -// CHECK-NEXT: %9 = insertvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } { i8 0, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %8, 1 -// CHECK-NEXT: ret { i8, %"{{.*}}/runtime/internal/runtime.iface" } %9 +// CHECK-NEXT: _llgo_1: ; preds = %14 +// CHECK-NEXT: %4 = load %"{{.*}}/runtime/internal/runtime.iface", ptr @main.EOF, align 8 +// CHECK-NEXT: %5 = insertvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } { i8 0, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %4, 1 +// CHECK-NEXT: ret { i8, %"{{.*}}/runtime/internal/runtime.iface" } %5 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %10 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %11 = load i64, ptr %10, align 8 -// CHECK-NEXT: %12 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %13 = load %"{{.*}}/runtime/internal/runtime.String", ptr %12, align 8 -// CHECK-NEXT: %14 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %13, 0 -// CHECK-NEXT: %15 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %13, 1 -// CHECK-NEXT: %16 = icmp slt i64 %11, 0 -// CHECK-NEXT: %17 = icmp uge i64 %11, %15 -// CHECK-NEXT: %18 = or i1 %17, %16 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %18, i64 %11, i1 true, i64 %15) -// CHECK-NEXT: %19 = getelementptr inbounds i8, ptr %14, i64 %11 -// CHECK-NEXT: %20 = load i8, ptr %19, align 1 -// CHECK-NEXT: %21 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %22 = load i64, ptr %21, align 8 -// CHECK-NEXT: %23 = add i64 %22, 1 -// CHECK-NEXT: %24 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: store i64 %23, ptr %24, align 8 -// CHECK-NEXT: %25 = insertvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } undef, i8 %20, 0 -// CHECK-NEXT: %26 = insertvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } %25, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer, 1 -// CHECK-NEXT: ret { i8, %"{{.*}}/runtime/internal/runtime.iface" } %26 +// CHECK-NEXT: _llgo_2: ; preds = %14 +// CHECK-NEXT: %6 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %7 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %7, label %18, label %19 +// CHECK-EMPTY: +// CHECK-NEXT: 8: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 9: ; preds = %_llgo_0 +// CHECK-NEXT: %10 = load i64, ptr %2, align 8 +// CHECK-NEXT: %11 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %12 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %12, label %13, label %14 +// CHECK-EMPTY: +// CHECK-NEXT: 13: ; preds = %9 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 14: ; preds = %9 +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.String", ptr %11, align 8 +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %15, 1 +// CHECK-NEXT: %17 = icmp sge i64 %10, %16 +// CHECK-NEXT: br i1 %17, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: 18: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 19: ; preds = %_llgo_2 +// CHECK-NEXT: %20 = load i64, ptr %6, align 8 +// CHECK-NEXT: %21 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %22 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %22, label %23, label %24 +// CHECK-EMPTY: +// CHECK-NEXT: 23: ; preds = %19 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 24: ; preds = %19 +// CHECK-NEXT: %25 = load %"{{.*}}/runtime/internal/runtime.String", ptr %21, align 8 +// CHECK-NEXT: %26 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %25, 0 +// CHECK-NEXT: %27 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %25, 1 +// CHECK-NEXT: %28 = icmp slt i64 %20, 0 +// CHECK-NEXT: %29 = icmp uge i64 %20, %27 +// CHECK-NEXT: %30 = or i1 %29, %28 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %30, i64 %20, i1 true, i64 %27) +// CHECK-NEXT: %31 = getelementptr inbounds i8, ptr %26, i64 %20 +// CHECK-NEXT: %32 = load i8, ptr %31, align 1 +// CHECK-NEXT: %33 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %34 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %34, label %35, label %36 +// CHECK-EMPTY: +// CHECK-NEXT: 35: ; preds = %24 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 36: ; preds = %24 +// CHECK-NEXT: %37 = load i64, ptr %33, align 8 +// CHECK-NEXT: %38 = add i64 %37, 1 +// CHECK-NEXT: %39 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: store i64 %38, ptr %39, align 8 +// CHECK-NEXT: %40 = insertvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } undef, i8 %32, 0 +// CHECK-NEXT: %41 = insertvalue { i8, %"{{.*}}/runtime/internal/runtime.iface" } %40, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer, 1 +// CHECK-NEXT: ret { i8, %"{{.*}}/runtime/internal/runtime.iface" } %41 // CHECK-NEXT: } // CHECK-LABEL: define { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*stringReader).ReadRune"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load i64, ptr %1, align 8 -// CHECK-NEXT: %3 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %4 = load %"{{.*}}/runtime/internal/runtime.String", ptr %3, align 8 -// CHECK-NEXT: %5 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %4, 1 -// CHECK-NEXT: %6 = icmp sge i64 %2, %5 -// CHECK-NEXT: br i1 %6, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %12, label %13 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %7 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 -// CHECK-NEXT: store i64 -1, ptr %7, align 8 -// CHECK-NEXT: %8 = load %"{{.*}}/runtime/internal/runtime.iface", ptr @main.EOF, align 8 -// CHECK-NEXT: %9 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } { i32 0, i64 0, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %8, 2 -// CHECK-NEXT: ret { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %9 +// CHECK-NEXT: _llgo_1: ; preds = %18 +// CHECK-NEXT: %3 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 +// CHECK-NEXT: store i64 -1, ptr %3, align 8 +// CHECK-NEXT: %4 = load %"{{.*}}/runtime/internal/runtime.iface", ptr @main.EOF, align 8 +// CHECK-NEXT: %5 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } { i32 0, i64 0, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %4, 2 +// CHECK-NEXT: ret { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %5 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %10 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %11 = load i64, ptr %10, align 8 -// CHECK-NEXT: %12 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 -// CHECK-NEXT: store i64 %11, ptr %12, align 8 -// CHECK-NEXT: %13 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %14 = load i64, ptr %13, align 8 +// CHECK-NEXT: _llgo_2: ; preds = %18 +// CHECK-NEXT: %6 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %7 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %7, label %22, label %23 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %34 +// CHECK-NEXT: %8 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %9 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %9, label %44, label %45 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %34 +// CHECK-NEXT: %10 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %11 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %11, label %53, label %54 +// CHECK-EMPTY: +// CHECK-NEXT: 12: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 13: ; preds = %_llgo_0 +// CHECK-NEXT: %14 = load i64, ptr %1, align 8 // CHECK-NEXT: %15 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %16 = load %"{{.*}}/runtime/internal/runtime.String", ptr %15, align 8 -// CHECK-NEXT: %17 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %16, 0 -// CHECK-NEXT: %18 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %16, 1 -// CHECK-NEXT: %19 = icmp slt i64 %14, 0 -// CHECK-NEXT: %20 = icmp uge i64 %14, %18 -// CHECK-NEXT: %21 = or i1 %20, %19 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %21, i64 %14, i1 true, i64 %18) -// CHECK-NEXT: %22 = getelementptr inbounds i8, ptr %17, i64 %14 -// CHECK-NEXT: %23 = load i8, ptr %22, align 1 -// CHECK-NEXT: %24 = icmp ult i8 %23, -128 -// CHECK-NEXT: br i1 %24, label %_llgo_3, label %_llgo_4 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 -// CHECK-NEXT: %25 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %26 = load i64, ptr %25, align 8 -// CHECK-NEXT: %27 = add i64 %26, 1 -// CHECK-NEXT: %28 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: store i64 %27, ptr %28, align 8 -// CHECK-NEXT: %29 = zext i8 %23 to i32 -// CHECK-NEXT: %30 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i32 %29, 0 -// CHECK-NEXT: %31 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %30, i64 1, 1 -// CHECK-NEXT: %32 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %31, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer, 2 -// CHECK-NEXT: ret { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %32 +// CHECK-NEXT: %16 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %16, label %17, label %18 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 -// CHECK-NEXT: %33 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %34 = load %"{{.*}}/runtime/internal/runtime.String", ptr %33, align 8 -// CHECK-NEXT: %35 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %36 = load i64, ptr %35, align 8 -// CHECK-NEXT: %37 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %34, 1 -// CHECK-NEXT: %38 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringSlice2"(%"{{.*}}/runtime/internal/runtime.String" %34, i64 %36, i64 %37, i1 true, i1 true) -// CHECK-NEXT: %39 = call { i32, i64 } @"unicode/utf8.DecodeRuneInString"(%"{{.*}}/runtime/internal/runtime.String" %38) -// CHECK-NEXT: %40 = extractvalue { i32, i64 } %39, 0 -// CHECK-NEXT: %41 = extractvalue { i32, i64 } %39, 1 -// CHECK-NEXT: %42 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %43 = load i64, ptr %42, align 8 -// CHECK-NEXT: %44 = add i64 %43, %41 -// CHECK-NEXT: %45 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: store i64 %44, ptr %45, align 8 -// CHECK-NEXT: %46 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i32 %40, 0 -// CHECK-NEXT: %47 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %46, i64 %41, 1 -// CHECK-NEXT: %48 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %47, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer, 2 -// CHECK-NEXT: ret { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %48 +// CHECK-NEXT: 17: ; preds = %13 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 18: ; preds = %13 +// CHECK-NEXT: %19 = load %"{{.*}}/runtime/internal/runtime.String", ptr %15, align 8 +// CHECK-NEXT: %20 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %19, 1 +// CHECK-NEXT: %21 = icmp sge i64 %14, %20 +// CHECK-NEXT: br i1 %21, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: 22: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 23: ; preds = %_llgo_2 +// CHECK-NEXT: %24 = load i64, ptr %6, align 8 +// CHECK-NEXT: %25 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 +// CHECK-NEXT: store i64 %24, ptr %25, align 8 +// CHECK-NEXT: %26 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %27 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %27, label %28, label %29 +// CHECK-EMPTY: +// CHECK-NEXT: 28: ; preds = %23 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 29: ; preds = %23 +// CHECK-NEXT: %30 = load i64, ptr %26, align 8 +// CHECK-NEXT: %31 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %32 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %32, label %33, label %34 +// CHECK-EMPTY: +// CHECK-NEXT: 33: ; preds = %29 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 34: ; preds = %29 +// CHECK-NEXT: %35 = load %"{{.*}}/runtime/internal/runtime.String", ptr %31, align 8 +// CHECK-NEXT: %36 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %35, 0 +// CHECK-NEXT: %37 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %35, 1 +// CHECK-NEXT: %38 = icmp slt i64 %30, 0 +// CHECK-NEXT: %39 = icmp uge i64 %30, %37 +// CHECK-NEXT: %40 = or i1 %39, %38 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %40, i64 %30, i1 true, i64 %37) +// CHECK-NEXT: %41 = getelementptr inbounds i8, ptr %36, i64 %30 +// CHECK-NEXT: %42 = load i8, ptr %41, align 1 +// CHECK-NEXT: %43 = icmp ult i8 %42, -128 +// CHECK-NEXT: br i1 %43, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: 44: ; preds = %_llgo_3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 45: ; preds = %_llgo_3 +// CHECK-NEXT: %46 = load i64, ptr %8, align 8 +// CHECK-NEXT: %47 = add i64 %46, 1 +// CHECK-NEXT: %48 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: store i64 %47, ptr %48, align 8 +// CHECK-NEXT: %49 = zext i8 %42 to i32 +// CHECK-NEXT: %50 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i32 %49, 0 +// CHECK-NEXT: %51 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %50, i64 1, 1 +// CHECK-NEXT: %52 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %51, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer, 2 +// CHECK-NEXT: ret { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %52 +// CHECK-EMPTY: +// CHECK-NEXT: 53: ; preds = %_llgo_4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 54: ; preds = %_llgo_4 +// CHECK-NEXT: %55 = load %"{{.*}}/runtime/internal/runtime.String", ptr %10, align 8 +// CHECK-NEXT: %56 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %57 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %57, label %58, label %59 +// CHECK-EMPTY: +// CHECK-NEXT: 58: ; preds = %54 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 59: ; preds = %54 +// CHECK-NEXT: %60 = load i64, ptr %56, align 8 +// CHECK-NEXT: %61 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %55, 1 +// CHECK-NEXT: %62 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringSlice2"(%"{{.*}}/runtime/internal/runtime.String" %55, i64 %60, i64 %61, i1 true, i1 true) +// CHECK-NEXT: %63 = call { i32, i64 } @"unicode/utf8.DecodeRuneInString"(%"{{.*}}/runtime/internal/runtime.String" %62) +// CHECK-NEXT: %64 = extractvalue { i32, i64 } %63, 0 +// CHECK-NEXT: %65 = extractvalue { i32, i64 } %63, 1 +// CHECK-NEXT: %66 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %67 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %67, label %68, label %69 +// CHECK-EMPTY: +// CHECK-NEXT: 68: ; preds = %59 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 69: ; preds = %59 +// CHECK-NEXT: %70 = load i64, ptr %66, align 8 +// CHECK-NEXT: %71 = add i64 %70, %65 +// CHECK-NEXT: %72 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: store i64 %71, ptr %72, align 8 +// CHECK-NEXT: %73 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i32 %64, 0 +// CHECK-NEXT: %74 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %73, i64 %65, 1 +// CHECK-NEXT: %75 = insertvalue { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %74, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer, 2 +// CHECK-NEXT: ret { i32, i64, %"{{.*}}/runtime/internal/runtime.iface" } %75 // CHECK-NEXT: } // CHECK-LABEL: define { i64, %"{{.*}}/runtime/internal/runtime.iface" } @"main.(*stringReader).Seek"(ptr %0, i64 %1, i64 %2){{.*}} { @@ -957,8 +1181,8 @@ func main() { // CHECK-NEXT: %4 = icmp eq i64 %2, 0 // CHECK-NEXT: br i1 %4, label %_llgo_2, label %_llgo_4 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_5, %_llgo_3, %_llgo_2 -// CHECK-NEXT: %5 = phi i64 [ %1, %_llgo_2 ], [ %9, %_llgo_3 ], [ %14, %_llgo_5 ] +// CHECK-NEXT: _llgo_1: ; preds = %25, %21, %_llgo_2 +// CHECK-NEXT: %5 = phi i64 [ %1, %_llgo_2 ], [ %23, %21 ], [ %28, %25 ] // CHECK-NEXT: %6 = icmp slt i64 %5, 0 // CHECK-NEXT: br i1 %6, label %_llgo_8, label %_llgo_9 // CHECK-EMPTY: @@ -967,101 +1191,165 @@ func main() { // CHECK-EMPTY: // CHECK-NEXT: _llgo_3: ; preds = %_llgo_4 // CHECK-NEXT: %7 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %8 = load i64, ptr %7, align 8 -// CHECK-NEXT: %9 = add i64 %8, %1 -// CHECK-NEXT: br label %_llgo_1 +// CHECK-NEXT: %8 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %8, label %20, label %21 // CHECK-EMPTY: // CHECK-NEXT: _llgo_4: ; preds = %_llgo_0 -// CHECK-NEXT: %10 = icmp eq i64 %2, 1 -// CHECK-NEXT: br i1 %10, label %_llgo_3, label %_llgo_6 +// CHECK-NEXT: %9 = icmp eq i64 %2, 1 +// CHECK-NEXT: br i1 %9, label %_llgo_3, label %_llgo_6 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_6 -// CHECK-NEXT: %11 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %12 = load %"{{.*}}/runtime/internal/runtime.String", ptr %11, align 8 -// CHECK-NEXT: %13 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %12, 1 -// CHECK-NEXT: %14 = add i64 %13, %1 -// CHECK-NEXT: br label %_llgo_1 +// CHECK-NEXT: %10 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %11 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %11, label %24, label %25 // CHECK-EMPTY: // CHECK-NEXT: _llgo_6: ; preds = %_llgo_4 -// CHECK-NEXT: %15 = icmp eq i64 %2, 2 -// CHECK-NEXT: br i1 %15, label %_llgo_5, label %_llgo_7 +// CHECK-NEXT: %12 = icmp eq i64 %2, 2 +// CHECK-NEXT: br i1 %12, 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: %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-NEXT: %13 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @57, i64 34 }) +// CHECK-NEXT: %14 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } { i64 0, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %13, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %14 // 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: %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-NEXT: %15 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @58, i64 37 }) +// CHECK-NEXT: %16 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } { i64 0, %"{{.*}}/runtime/internal/runtime.iface" undef }, %"{{.*}}/runtime/internal/runtime.iface" %15, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %16 // CHECK-EMPTY: // CHECK-NEXT: _llgo_9: ; preds = %_llgo_1 -// CHECK-NEXT: %20 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: store i64 %5, ptr %20, align 8 -// CHECK-NEXT: %21 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %5, 0 -// CHECK-NEXT: %22 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %21, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %22 +// CHECK-NEXT: %17 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: store i64 %5, ptr %17, align 8 +// CHECK-NEXT: %18 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %5, 0 +// CHECK-NEXT: %19 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %18, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %19 +// CHECK-EMPTY: +// CHECK-NEXT: 20: ; preds = %_llgo_3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 21: ; preds = %_llgo_3 +// CHECK-NEXT: %22 = load i64, ptr %7, align 8 +// CHECK-NEXT: %23 = add i64 %22, %1 +// CHECK-NEXT: br label %_llgo_1 +// CHECK-EMPTY: +// CHECK-NEXT: 24: ; preds = %_llgo_5 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 25: ; preds = %_llgo_5 +// CHECK-NEXT: %26 = load %"{{.*}}/runtime/internal/runtime.String", ptr %10, align 8 +// CHECK-NEXT: %27 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %26, 1 +// CHECK-NEXT: %28 = add i64 %27, %1 +// CHECK-NEXT: br label %_llgo_1 // CHECK-NEXT: } // CHECK-LABEL: define i64 @"main.(*stringReader).Size"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load %"{{.*}}/runtime/internal/runtime.String", ptr %1, align 8 -// CHECK-NEXT: %3 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %2, 1 -// CHECK-NEXT: ret i64 %3 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load %"{{.*}}/runtime/internal/runtime.String", ptr %1, align 8 +// CHECK-NEXT: %6 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %5, 1 +// CHECK-NEXT: ret i64 %6 // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @"main.(*stringReader).UnreadByte"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load i64, ptr %1, align 8 -// CHECK-NEXT: %3 = icmp sle i64 %2, 0 -// CHECK-NEXT: br i1 %3, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %7, label %8 // 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: ret %"{{.*}}/runtime/internal/runtime.iface" %4 +// CHECK-NEXT: _llgo_1: ; preds = %8 +// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @59, i64 48 }) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %3 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %5 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 -// CHECK-NEXT: store i64 -1, ptr %5, align 8 -// CHECK-NEXT: %6 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %7 = load i64, ptr %6, align 8 -// CHECK-NEXT: %8 = sub i64 %7, 1 -// CHECK-NEXT: %9 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: store i64 %8, ptr %9, align 8 +// CHECK-NEXT: _llgo_2: ; preds = %8 +// CHECK-NEXT: %4 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 +// CHECK-NEXT: store i64 -1, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %6 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %6, label %11, label %12 +// CHECK-EMPTY: +// CHECK-NEXT: 7: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 8: ; preds = %_llgo_0 +// CHECK-NEXT: %9 = load i64, ptr %1, align 8 +// CHECK-NEXT: %10 = icmp sle i64 %9, 0 +// CHECK-NEXT: br i1 %10, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: 11: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 12: ; preds = %_llgo_2 +// CHECK-NEXT: %13 = load i64, ptr %5, align 8 +// CHECK-NEXT: %14 = sub i64 %13, 1 +// CHECK-NEXT: %15 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: store i64 %14, ptr %15, align 8 // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer // CHECK-NEXT: } // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.iface" @"main.(*stringReader).UnreadRune"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load i64, ptr %1, align 8 -// CHECK-NEXT: %3 = icmp sle i64 %2, 0 -// CHECK-NEXT: br i1 %3, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %9, label %10 // 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: ret %"{{.*}}/runtime/internal/runtime.iface" %4 +// CHECK-NEXT: _llgo_1: ; preds = %10 +// CHECK-NEXT: %3 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @60, i64 49 }) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %3 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %5 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 -// CHECK-NEXT: %6 = load i64, ptr %5, align 8 -// CHECK-NEXT: %7 = icmp slt i64 %6, 0 -// CHECK-NEXT: br i1 %7, label %_llgo_3, label %_llgo_4 +// CHECK-NEXT: _llgo_2: ; preds = %10 +// CHECK-NEXT: %4 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 +// CHECK-NEXT: %5 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %5, label %13, label %14 // 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: ret %"{{.*}}/runtime/internal/runtime.iface" %8 +// CHECK-NEXT: _llgo_3: ; preds = %14 +// CHECK-NEXT: %6 = call %"{{.*}}/runtime/internal/runtime.iface" @main.newError(%"{{.*}}/runtime/internal/runtime.String" { ptr @61, i64 62 }) +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" %6 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 -// CHECK-NEXT: %9 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 -// CHECK-NEXT: %10 = load i64, ptr %9, align 8 -// CHECK-NEXT: %11 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: store i64 %10, ptr %11, align 8 -// CHECK-NEXT: %12 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 -// CHECK-NEXT: store i64 -1, ptr %12, align 8 +// CHECK-NEXT: _llgo_4: ; preds = %14 +// CHECK-NEXT: %7 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 +// CHECK-NEXT: %8 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %8, label %17, label %18 +// CHECK-EMPTY: +// CHECK-NEXT: 9: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 10: ; preds = %_llgo_0 +// CHECK-NEXT: %11 = load i64, ptr %1, align 8 +// CHECK-NEXT: %12 = icmp sle i64 %11, 0 +// CHECK-NEXT: br i1 %12, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: 13: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 14: ; preds = %_llgo_2 +// CHECK-NEXT: %15 = load i64, ptr %4, align 8 +// CHECK-NEXT: %16 = icmp slt i64 %15, 0 +// CHECK-NEXT: br i1 %16, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: 17: ; preds = %_llgo_4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 18: ; preds = %_llgo_4 +// CHECK-NEXT: %19 = load i64, ptr %7, align 8 +// CHECK-NEXT: %20 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: store i64 %19, ptr %20, align 8 +// CHECK-NEXT: %21 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 +// CHECK-NEXT: store i64 -1, ptr %21, align 8 // CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer // CHECK-NEXT: } @@ -1070,67 +1358,107 @@ func main() { // CHECK-NEXT: %2 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 2 // CHECK-NEXT: store i64 -1, ptr %2, align 8 // CHECK-NEXT: %3 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %4 = load i64, ptr %3, align 8 -// CHECK-NEXT: %5 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %6 = load %"{{.*}}/runtime/internal/runtime.String", ptr %5, align 8 -// CHECK-NEXT: %7 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %6, 1 -// CHECK-NEXT: %8 = icmp sge i64 %4, %7 -// CHECK-NEXT: br i1 %8, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %4 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %4, label %23, label %24 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: _llgo_1: ; preds = %29 // CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } zeroinitializer // CHECK-EMPTY: -// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %9 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %10 = load %"{{.*}}/runtime/internal/runtime.String", ptr %9, align 8 -// CHECK-NEXT: %11 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %12 = load i64, ptr %11, align 8 -// CHECK-NEXT: %13 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %10, 1 -// CHECK-NEXT: %14 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringSlice2"(%"{{.*}}/runtime/internal/runtime.String" %10, i64 %12, i64 %13, i1 true, i1 true) -// CHECK-NEXT: %15 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @main.WriteString(%"{{.*}}/runtime/internal/runtime.iface" %1, %"{{.*}}/runtime/internal/runtime.String" %14) -// 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 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %14, 1 -// CHECK-NEXT: %19 = icmp sgt i64 %16, %18 -// CHECK-NEXT: br i1 %19, label %_llgo_3, label %_llgo_4 -// 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: %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: _llgo_2: ; preds = %29 +// CHECK-NEXT: %5 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %6 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %6, label %33, label %34 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %39 +// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @62, i64 48 }, 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: unreachable // CHECK-EMPTY: -// CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 -// CHECK-NEXT: %22 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %23 = load i64, ptr %22, align 8 -// CHECK-NEXT: %24 = add i64 %23, %16 -// CHECK-NEXT: %25 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 -// CHECK-NEXT: store i64 %24, ptr %25, align 8 -// CHECK-NEXT: %26 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %14, 1 -// CHECK-NEXT: %27 = icmp ne i64 %16, %26 -// CHECK-NEXT: br i1 %27, label %_llgo_7, label %_llgo_6 +// CHECK-NEXT: _llgo_4: ; preds = %39 +// CHECK-NEXT: %9 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %10 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %10, label %48, label %49 // CHECK-EMPTY: // CHECK-NEXT: _llgo_5: ; preds = %_llgo_7 -// CHECK-NEXT: %28 = load %"{{.*}}/runtime/internal/runtime.iface", ptr @main.ErrShortWrite, align 8 +// CHECK-NEXT: %11 = load %"{{.*}}/runtime/internal/runtime.iface", ptr @main.ErrShortWrite, align 8 // CHECK-NEXT: br label %_llgo_6 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_6: ; preds = %_llgo_5, %_llgo_7, %_llgo_4 -// CHECK-NEXT: %29 = phi %"{{.*}}/runtime/internal/runtime.iface" [ %17, %_llgo_4 ], [ %17, %_llgo_7 ], [ %28, %_llgo_5 ] -// CHECK-NEXT: %30 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %16, 0 -// CHECK-NEXT: %31 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %30, %"{{.*}}/runtime/internal/runtime.iface" %29, 1 -// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %31 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_7: ; preds = %_llgo_4 -// CHECK-NEXT: %32 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %17) -// CHECK-NEXT: %33 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %17, 1 -// CHECK-NEXT: %34 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %32, 0 -// CHECK-NEXT: %35 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %34, ptr %33, 1 -// CHECK-NEXT: %36 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" zeroinitializer) -// CHECK-NEXT: %37 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %36, 0 -// CHECK-NEXT: %38 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %37, ptr null, 1 -// CHECK-NEXT: %39 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %35, %"{{.*}}/runtime/internal/runtime.eface" %38) -// CHECK-NEXT: br i1 %39, label %_llgo_5, label %_llgo_6 +// CHECK-NEXT: _llgo_6: ; preds = %_llgo_5, %_llgo_7, %49 +// CHECK-NEXT: %12 = phi %"{{.*}}/runtime/internal/runtime.iface" [ %45, %49 ], [ %45, %_llgo_7 ], [ %11, %_llgo_5 ] +// CHECK-NEXT: %13 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } undef, i64 %44, 0 +// CHECK-NEXT: %14 = insertvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %13, %"{{.*}}/runtime/internal/runtime.iface" %12, 1 +// CHECK-NEXT: ret { i64, %"{{.*}}/runtime/internal/runtime.iface" } %14 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %49 +// CHECK-NEXT: %15 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" %45) +// CHECK-NEXT: %16 = extractvalue %"{{.*}}/runtime/internal/runtime.iface" %45, 1 +// CHECK-NEXT: %17 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %15, 0 +// CHECK-NEXT: %18 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %17, ptr %16, 1 +// CHECK-NEXT: %19 = call ptr @"{{.*}}/runtime/internal/runtime.IfaceType"(%"{{.*}}/runtime/internal/runtime.iface" zeroinitializer) +// CHECK-NEXT: %20 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" undef, ptr %19, 0 +// CHECK-NEXT: %21 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" %20, ptr null, 1 +// CHECK-NEXT: %22 = call i1 @"{{.*}}/runtime/internal/runtime.EfaceEqual"(%"{{.*}}/runtime/internal/runtime.eface" %18, %"{{.*}}/runtime/internal/runtime.eface" %21) +// CHECK-NEXT: br i1 %22, label %_llgo_5, label %_llgo_6 +// CHECK-EMPTY: +// CHECK-NEXT: 23: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 24: ; preds = %_llgo_0 +// CHECK-NEXT: %25 = load i64, ptr %3, align 8 +// CHECK-NEXT: %26 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %27 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %27, label %28, label %29 +// CHECK-EMPTY: +// CHECK-NEXT: 28: ; preds = %24 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 29: ; preds = %24 +// CHECK-NEXT: %30 = load %"{{.*}}/runtime/internal/runtime.String", ptr %26, align 8 +// CHECK-NEXT: %31 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %30, 1 +// CHECK-NEXT: %32 = icmp sge i64 %25, %31 +// CHECK-NEXT: br i1 %32, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: 33: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 34: ; preds = %_llgo_2 +// CHECK-NEXT: %35 = load %"{{.*}}/runtime/internal/runtime.String", ptr %5, align 8 +// CHECK-NEXT: %36 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %37 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %37, label %38, label %39 +// CHECK-EMPTY: +// CHECK-NEXT: 38: ; preds = %34 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 39: ; preds = %34 +// CHECK-NEXT: %40 = load i64, ptr %36, align 8 +// CHECK-NEXT: %41 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %35, 1 +// CHECK-NEXT: %42 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringSlice2"(%"{{.*}}/runtime/internal/runtime.String" %35, i64 %40, i64 %41, i1 true, i1 true) +// CHECK-NEXT: %43 = call { i64, %"{{.*}}/runtime/internal/runtime.iface" } @main.WriteString(%"{{.*}}/runtime/internal/runtime.iface" %1, %"{{.*}}/runtime/internal/runtime.String" %42) +// CHECK-NEXT: %44 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %43, 0 +// CHECK-NEXT: %45 = extractvalue { i64, %"{{.*}}/runtime/internal/runtime.iface" } %43, 1 +// CHECK-NEXT: %46 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %42, 1 +// CHECK-NEXT: %47 = icmp sgt i64 %44, %46 +// CHECK-NEXT: br i1 %47, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: 48: ; preds = %_llgo_4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 49: ; preds = %_llgo_4 +// CHECK-NEXT: %50 = load i64, ptr %9, align 8 +// CHECK-NEXT: %51 = add i64 %50, %44 +// CHECK-NEXT: %52 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1 +// CHECK-NEXT: store i64 %51, ptr %52, align 8 +// CHECK-NEXT: %53 = extractvalue %"{{.*}}/runtime/internal/runtime.String" %42, 1 +// CHECK-NEXT: %54 = icmp ne i64 %44, %53 +// CHECK-NEXT: br i1 %54, label %_llgo_7, label %_llgo_6 // CHECK-NEXT: } // CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.interequal"(ptr %0, ptr %1, ptr %2){{.*}} { diff --git a/cl/_testgo/reflect/in.go b/cl/_testgo/reflect/in.go index ea6dd78c61..bd5fd7059f 100644 --- a/cl/_testgo/reflect/in.go +++ b/cl/_testgo/reflect/in.go @@ -94,13 +94,29 @@ type T struct { // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 11 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: %2 = getelementptr inbounds %main.T, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %3 = load i64, ptr %2, align 8 -// CHECK-NEXT: %4 = add i64 %3, %1 -// CHECK-NEXT: %5 = getelementptr inbounds %main.T, ptr %0, i32 0, i32 0 -// CHECK-NEXT: store i64 %4, ptr %5, align 8 -// CHECK-NEXT: %6 = getelementptr inbounds %main.T, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %7 = load i64, ptr %6, align 8 -// CHECK-NEXT: ret i64 %7 +// CHECK-NEXT: %3 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %3, label %4, label %5 +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = load i64, ptr %2, align 8 +// CHECK-NEXT: %7 = add i64 %6, %1 +// CHECK-NEXT: %8 = getelementptr inbounds %main.T, ptr %0, i32 0, i32 0 +// CHECK-NEXT: store i64 %7, ptr %8, align 8 +// CHECK-NEXT: %9 = getelementptr inbounds %main.T, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %10 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %10, label %11, label %12 +// CHECK-EMPTY: +// CHECK-NEXT: 11: ; preds = %5 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 12: ; preds = %5 +// CHECK-NEXT: %13 = load i64, ptr %9, align 8 +// CHECK-NEXT: ret i64 %13 // CHECK-NEXT: } // CHECK-LABEL: define void @main.callClosure(){{.*}} { diff --git a/cl/_testgo/returnorder/in.go b/cl/_testgo/returnorder/in.go index de98fd2b9b..395eb9d34c 100644 --- a/cl/_testgo/returnorder/in.go +++ b/cl/_testgo/returnorder/in.go @@ -46,8 +46,17 @@ func returnStateAndMut() (state, int) { // CHECK-NEXT: %2 = getelementptr inbounds %main.state, ptr %0, i32 0, i32 0 // CHECK-NEXT: store i64 %1, ptr %2, align 8 // CHECK-NEXT: %3 = getelementptr inbounds %main.state, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %4 = load i64, ptr %3, align 8 -// CHECK-NEXT: ret i64 %4 +// CHECK-NEXT: %4 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %4, label %5, label %6 +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 6: ; preds = %_llgo_0 +// CHECK-NEXT: %7 = load i64, ptr %3, align 8 +// CHECK-NEXT: ret i64 %7 +// CHECK-NEXT: } func (s *state) mutate(next int) int { s.v = next return s.v diff --git a/cl/_testgo/tpinst/main.go b/cl/_testgo/tpinst/main.go index fdd41ff1f2..0f0c32b935 100644 --- a/cl/_testgo/tpinst/main.go +++ b/cl/_testgo/tpinst/main.go @@ -157,15 +157,31 @@ func (pt *M[T]) value() T { // CHECK-LABEL: define linkonce i64 @"main.(*M[int]).Value"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %"main.M[int]", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load i64, ptr %1, align 8 -// CHECK-NEXT: ret i64 %2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load i64, ptr %1, align 8 +// CHECK-NEXT: ret i64 %5 // CHECK-NEXT: } // CHECK-LABEL: define linkonce i64 @"main.(*M[int]).value"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %"main.M[int]", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load i64, ptr %1, align 8 -// CHECK-NEXT: ret i64 %2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load i64, ptr %1, align 8 +// CHECK-NEXT: ret i64 %5 // CHECK-NEXT: } // CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} { @@ -195,15 +211,31 @@ func (pt *M[T]) value() T { // CHECK-LABEL: define linkonce double @"main.(*M[float64]).Value"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %"main.M[float64]", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load double, ptr %1, align 8 -// CHECK-NEXT: ret double %2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load double, ptr %1, align 8 +// CHECK-NEXT: ret double %5 // CHECK-NEXT: } // CHECK-LABEL: define linkonce double @"main.(*M[float64]).value"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %"main.M[float64]", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load double, ptr %1, align 8 -// CHECK-NEXT: ret double %2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load double, ptr %1, align 8 +// CHECK-NEXT: ret double %5 // CHECK-NEXT: } // CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.f64equal"(ptr %0, ptr %1, ptr %2){{.*}} { diff --git a/cl/_testgo/tprecurfn/in.go b/cl/_testgo/tprecurfn/in.go index de9928916d..1e2acabe53 100644 --- a/cl/_testgo/tprecurfn/in.go +++ b/cl/_testgo/tprecurfn/in.go @@ -6,29 +6,51 @@ type My[T any] struct { next *My[T] } -// CHECK-LABEL: define void @main.main(){{.*}} { func main() { - // CHECK: %0 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) - // CHECK-NEXT: %1 = getelementptr inbounds %"main.My[int]", ptr %0, i32 0, i32 1 - // CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) - // CHECK-NEXT: %3 = getelementptr inbounds %"main.My[int]", ptr %2, i32 0, i32 0 - // CHECK-NEXT: store { ptr, ptr } { ptr @"__llgo_stub.main.main$1", ptr null }, ptr %3, align 8 - // CHECK-NEXT: store ptr %2, ptr %1, align 8 - // CHECK-NEXT: %4 = getelementptr inbounds %"main.My[int]", ptr %0, i32 0, i32 1 - // CHECK-NEXT: %5 = load ptr, ptr %4, align 8 - // CHECK-NEXT: %6 = getelementptr inbounds %"main.My[int]", ptr %5, i32 0, i32 0 - // CHECK-NEXT: %7 = load { ptr, ptr }, ptr %6, align 8 - // CHECK-NEXT: %8 = extractvalue { ptr, ptr } %7, 1 - // CHECK-NEXT: %9 = extractvalue { ptr, ptr } %7, 0 - // CHECK-NEXT: call void %9(ptr %8, i64 100) - // CHECK-NEXT: ret void - // CHECK-NEXT:} m := &My[int]{next: &My[int]{fn: func(n int) { println(n) }}} m.next.fn(100) } +// 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: 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 24) +// CHECK-NEXT: %1 = getelementptr inbounds %"main.My[int]", ptr %0, i32 0, i32 1 +// CHECK-NEXT: %2 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 24) +// CHECK-NEXT: %3 = getelementptr inbounds %"main.My[int]", ptr %2, i32 0, i32 0 +// CHECK-NEXT: store { ptr, ptr } { ptr @"__llgo_stub.main.main$1", ptr null }, ptr %3, align 8 +// CHECK-NEXT: store ptr %2, ptr %1, align 8 +// CHECK-NEXT: %4 = getelementptr inbounds %"main.My[int]", ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"main.My[int]", ptr %5, i32 0, i32 0 +// CHECK-NEXT: %7 = load { ptr, ptr }, ptr %6, align 8 +// CHECK-NEXT: %8 = extractvalue { ptr, ptr } %7, 1 +// CHECK-NEXT: %9 = extractvalue { ptr, ptr } %7, 0 +// CHECK-NEXT: call void %9(ptr %8, i64 100) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + // CHECK-LABEL: define void @"main.main$1"(i64 %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: call void @"{{.*}}PrintInt"(i64 %0) -// CHECK-NEXT: call void @"{{.*}}PrintByte"(i8 10) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %0) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define linkonce void @"__llgo_stub.main.main$1"(ptr %0, i64 %1){{.*}} { +// CHECK-NEXT: _llgo_0: +// CHECK-NEXT: tail call void @"main.main$1"(i64 %1) // CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/cl/_testgo/tptypes/in.go b/cl/_testgo/tptypes/in.go index c6130848bd..edd09f67eb 100644 --- a/cl/_testgo/tptypes/in.go +++ b/cl/_testgo/tptypes/in.go @@ -139,7 +139,7 @@ type ( // CHECK-NEXT: %53 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %52, 0 // CHECK-NEXT: %54 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %52, 1 // CHECK-NEXT: %55 = icmp uge i64 0, %54 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %55, {{.*}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %55, i64 0, i1 true, i64 %54) // CHECK-NEXT: %56 = getelementptr inbounds i64, ptr %53, i64 0 // CHECK-NEXT: %57 = load i64, ptr %56, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintSlice"(%"{{.*}}/runtime/internal/runtime.Slice" %50) @@ -153,7 +153,7 @@ type ( // CHECK-NEXT: %62 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %61, 0 // CHECK-NEXT: %63 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %61, 1 // CHECK-NEXT: %64 = icmp uge i64 0, %63 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %64, {{.*}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %64, i64 0, i1 true, i64 %63) // CHECK-NEXT: %65 = getelementptr inbounds %"{{.*}}/runtime/internal/runtime.String", ptr %62, i64 0 // CHECK-NEXT: %66 = load %"{{.*}}/runtime/internal/runtime.String", ptr %65, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintSlice"(%"{{.*}}/runtime/internal/runtime.Slice" %59) @@ -167,7 +167,7 @@ type ( // CHECK-NEXT: %71 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %70, 0 // CHECK-NEXT: %72 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %70, 1 // CHECK-NEXT: %73 = icmp uge i64 0, %72 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %73, {{.*}}) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %73, i64 0, i1 true, i64 %72) // CHECK-NEXT: %74 = getelementptr inbounds i64, ptr %71, i64 0 // CHECK-NEXT: %75 = load i64, ptr %74, align 8 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintSlice"(%"{{.*}}/runtime/internal/runtime.Slice" %68) @@ -205,41 +205,89 @@ func main() { // CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.Slice" @"main.(*Slice{{\[\[\]int,int\]}}).Append"(ptr %0, %"{{.*}}/runtime/internal/runtime.Slice" %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = getelementptr inbounds %"main.Slice{{\[\[\]int,int\]}}", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %3 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %2, align 8 -// CHECK-NEXT: %4 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 0 -// CHECK-NEXT: %5 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 1 -// CHECK-NEXT: %6 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.SliceAppend"(%"{{.*}}/runtime/internal/runtime.Slice" %3, ptr %4, i64 %5, i64 8) -// CHECK-NEXT: %7 = getelementptr inbounds %"main.Slice{{\[\[\]int,int\]}}", ptr %0, i32 0, i32 0 -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %6, ptr %7, align 8 -// CHECK-NEXT: %8 = getelementptr inbounds %"main.Slice{{\[\[\]int,int\]}}", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %9 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %8, align 8 -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %9 +// CHECK-NEXT: %3 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %3, label %4, label %5 +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %2, align 8 +// CHECK-NEXT: %7 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 0 +// CHECK-NEXT: %8 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 1 +// CHECK-NEXT: %9 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.SliceAppend"(%"{{.*}}/runtime/internal/runtime.Slice" %6, ptr %7, i64 %8, i64 8) +// CHECK-NEXT: %10 = getelementptr inbounds %"main.Slice{{\[\[\]int,int\]}}", ptr %0, i32 0, i32 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %9, ptr %10, align 8 +// CHECK-NEXT: %11 = getelementptr inbounds %"main.Slice{{\[\[\]int,int\]}}", ptr %0, i32 0, i32 0 +// CHECK-NEXT: %12 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %12, label %13, label %14 +// CHECK-EMPTY: +// CHECK-NEXT: 13: ; preds = %5 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 14: ; preds = %5 +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %11, align 8 +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %15 // CHECK-NEXT: } // CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.Slice" @"main.(*Slice{{\[\[\]string,string\]}}).Append"(ptr %0, %"{{.*}}/runtime/internal/runtime.Slice" %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = getelementptr inbounds %"main.Slice{{\[\[\]string,string\]}}", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %3 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %2, align 8 -// CHECK-NEXT: %4 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 0 -// CHECK-NEXT: %5 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 1 -// CHECK-NEXT: %6 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.SliceAppend"(%"{{.*}}/runtime/internal/runtime.Slice" %3, ptr %4, i64 %5, i64 16) -// CHECK-NEXT: %7 = getelementptr inbounds %"main.Slice{{\[\[\]string,string\]}}", ptr %0, i32 0, i32 0 -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %6, ptr %7, align 8 -// CHECK-NEXT: %8 = getelementptr inbounds %"main.Slice{{\[\[\]string,string\]}}", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %9 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %8, align 8 -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %9 +// CHECK-NEXT: %3 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %3, label %4, label %5 +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %2, align 8 +// CHECK-NEXT: %7 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 0 +// CHECK-NEXT: %8 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 1 +// CHECK-NEXT: %9 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.SliceAppend"(%"{{.*}}/runtime/internal/runtime.Slice" %6, ptr %7, i64 %8, i64 16) +// CHECK-NEXT: %10 = getelementptr inbounds %"main.Slice{{\[\[\]string,string\]}}", ptr %0, i32 0, i32 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %9, ptr %10, align 8 +// CHECK-NEXT: %11 = getelementptr inbounds %"main.Slice{{\[\[\]string,string\]}}", ptr %0, i32 0, i32 0 +// CHECK-NEXT: %12 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %12, label %13, label %14 +// CHECK-EMPTY: +// CHECK-NEXT: 13: ; preds = %5 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 14: ; preds = %5 +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %11, align 8 +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %15 // CHECK-NEXT: } // CHECK-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.Slice" @"main.(*Slice{{\[\[\]int,int\]}}).Append2"(ptr %0, %"{{.*}}/runtime/internal/runtime.Slice" %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = getelementptr inbounds %"main.Slice{{\[\[\]int,int\]}}", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %3 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %2, align 8 -// CHECK-NEXT: %4 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 0 -// CHECK-NEXT: %5 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 1 -// CHECK-NEXT: %6 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.SliceAppend"(%"{{.*}}/runtime/internal/runtime.Slice" %3, ptr %4, i64 %5, i64 8) -// CHECK-NEXT: %7 = getelementptr inbounds %"main.Slice{{\[\[\]int,int\]}}", ptr %0, i32 0, i32 0 -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %6, ptr %7, align 8 -// CHECK-NEXT: %8 = getelementptr inbounds %"main.Slice{{\[\[\]int,int\]}}", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %9 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %8, align 8 -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %9 +// CHECK-NEXT: %3 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %3, label %4, label %5 +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %2, align 8 +// CHECK-NEXT: %7 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 0 +// CHECK-NEXT: %8 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %1, 1 +// CHECK-NEXT: %9 = call %"{{.*}}/runtime/internal/runtime.Slice" @"{{.*}}/runtime/internal/runtime.SliceAppend"(%"{{.*}}/runtime/internal/runtime.Slice" %6, ptr %7, i64 %8, i64 8) +// CHECK-NEXT: %10 = getelementptr inbounds %"main.Slice{{\[\[\]int,int\]}}", ptr %0, i32 0, i32 0 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.Slice" %9, ptr %10, align 8 +// CHECK-NEXT: %11 = getelementptr inbounds %"main.Slice{{\[\[\]int,int\]}}", ptr %0, i32 0, i32 0 +// CHECK-NEXT: %12 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %12, label %13, label %14 +// CHECK-EMPTY: +// CHECK-NEXT: 13: ; preds = %5 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 14: ; preds = %5 +// CHECK-NEXT: %15 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %11, align 8 +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.Slice" %15 // CHECK-NEXT: } diff --git a/cl/_testgo/typerecur/in.go b/cl/_testgo/typerecur/in.go index 247cb793df..c7c20cee58 100644 --- a/cl/_testgo/typerecur/in.go +++ b/cl/_testgo/typerecur/in.go @@ -12,15 +12,61 @@ type counter struct { // CHECK-LABEL: define %main.stateFn @main.countState(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.counter, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load i64, ptr %1, align 8 -// CHECK-NEXT: %3 = add i64 %2, 1 -// CHECK-NEXT: %4 = getelementptr inbounds %main.counter, ptr %0, i32 0, i32 0 -// CHECK-NEXT: store i64 %3, ptr %4, align 8 -// CHECK: call void @"{{.*}}PrintString"(%"{{.*}}String" { ptr @0, i64 6 }) -// CHECK: call void @"{{.*}}PrintInt"(i64 %6) -// CHECK: icmp sge i64 %8, %10 -// CHECK: ret %main.stateFn zeroinitializer -// CHECK: ret %main.stateFn { ptr @__llgo_stub.main.countState, ptr null } +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %21 +// CHECK-NEXT: ret %main.stateFn zeroinitializer +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %21 +// CHECK-NEXT: ret %main.stateFn { ptr @__llgo_stub.main.countState, ptr null } +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load i64, ptr %1, align 8 +// CHECK-NEXT: %6 = add i64 %5, 1 +// CHECK-NEXT: %7 = getelementptr inbounds %main.counter, ptr %0, i32 0, i32 0 +// CHECK-NEXT: store i64 %6, ptr %7, align 8 +// CHECK-NEXT: %8 = getelementptr inbounds %main.counter, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %9 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %9, label %10, label %11 +// CHECK-EMPTY: +// CHECK-NEXT: 10: ; preds = %4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 11: ; preds = %4 +// CHECK-NEXT: %12 = load i64, ptr %8, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 6 }) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %12) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %13 = getelementptr inbounds %main.counter, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %14 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %14, label %15, label %16 +// CHECK-EMPTY: +// CHECK-NEXT: 15: ; preds = %11 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 16: ; preds = %11 +// CHECK-NEXT: %17 = load i64, ptr %13, align 8 +// CHECK-NEXT: %18 = getelementptr inbounds %main.counter, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %19 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %19, label %20, label %21 +// CHECK-EMPTY: +// CHECK-NEXT: 20: ; preds = %16 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 21: ; preds = %16 +// CHECK-NEXT: %22 = load i64, ptr %18, align 8 +// CHECK-NEXT: %23 = icmp sge i64 %17, %22 +// CHECK-NEXT: br i1 %23, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: } func countState(c *counter) stateFn { c.value++ println("count:", c.value) diff --git a/cl/_testmeta/interface_generic/meta-expect.txt b/cl/_testmeta/interface_generic/meta-expect.txt index ced57b7874..96a575c437 100644 --- a/cl/_testmeta/interface_generic/meta-expect.txt +++ b/cl/_testmeta/interface_generic/meta-expect.txt @@ -53,6 +53,8 @@ _llgo_main.Box[int]: github.com/goplus/llgo/runtime/internal/runtime.structequal github.com/goplus/llgo/cl/_testmeta/interface_generic.struct$lOhriNu2BrWBR2Mh8k-KggMYlAw0Wx-2ftE2_gNyubg$fields: _llgo_int +main.(*Box[int]).Value: + github.com/goplus/llgo/runtime/internal/runtime.AssertNilDeref main.init: main.init$guard main.main: diff --git a/cl/_testmeta/interface_generic_crosspkg/meta-expect.txt b/cl/_testmeta/interface_generic_crosspkg/meta-expect.txt index e042029796..f755b1d807 100644 --- a/cl/_testmeta/interface_generic_crosspkg/meta-expect.txt +++ b/cl/_testmeta/interface_generic_crosspkg/meta-expect.txt @@ -94,10 +94,14 @@ github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]) _llgo_string github.com/goplus/llgo/runtime/internal/runtime.AllocU github.com/goplus/llgo/runtime/internal/runtime.Panic +github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[int]).Value: + github.com/goplus/llgo/runtime/internal/runtime.AssertNilDeref github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Drop: _llgo_string github.com/goplus/llgo/runtime/internal/runtime.AllocU github.com/goplus/llgo/runtime/internal/runtime.Panic +github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.(*Box[string]).Value: + github.com/goplus/llgo/runtime/internal/runtime.AssertNilDeref github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.struct$XNpHe-3-A25gBmHjYdF74H8M4k3Eik680huOzY6OtaU$fields: _llgo_string github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.struct$lOhriNu2BrWBR2Mh8k-KggMYlAw0Wx-2ftE2_gNyubg$fields: diff --git a/cl/_testmeta/interface_generic_crosspkg/model/meta-expect.txt b/cl/_testmeta/interface_generic_crosspkg/model/meta-expect.txt index 094b8c759e..d0293bc8e8 100644 --- a/cl/_testmeta/interface_generic_crosspkg/model/meta-expect.txt +++ b/cl/_testmeta/interface_generic_crosspkg/model/meta-expect.txt @@ -3,6 +3,8 @@ github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.NewIntBox: github.com/goplus/llgo/runtime/internal/runtime.AllocZ github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.NewStringBox: github.com/goplus/llgo/runtime/internal/runtime.AllocZ +github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.UseStringBox: + github.com/goplus/llgo/runtime/internal/runtime.AssertNilDeref github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.init: github.com/goplus/llgo/cl/_testmeta/interface_generic_crosspkg/model.init$guard diff --git a/cl/_testrt/abinamed/in.go b/cl/_testrt/abinamed/in.go index 88b0b7e136..b22929c232 100644 --- a/cl/_testrt/abinamed/in.go +++ b/cl/_testrt/abinamed/in.go @@ -18,189 +18,471 @@ import ( // CHECK-NEXT: %4 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @"_llgo_{{.*}}/runtime/abi.Type", ptr undef }, ptr %3, 1 // CHECK-NEXT: %5 = call ptr @main.toEface(%"{{.*}}/runtime/internal/runtime.eface" %4) // CHECK-NEXT: %6 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 -// CHECK-NEXT: %7 = load ptr, ptr %6, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %7) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %8 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 -// CHECK-NEXT: %9 = load ptr, ptr %8, align 8 -// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %9, i32 0, i32 10 +// CHECK-NEXT: %7 = icmp eq ptr %2, null +// CHECK-NEXT: br i1 %7, label %36, label %37 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %107 +// CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @121, i64 13 }, 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 = %107 +// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %72, i32 0, i32 1 // CHECK-NEXT: %11 = load ptr, ptr %10, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %11) +// CHECK-NEXT: %12 = call ptr @"{{.*}}/runtime/abi.(*Type).Elem"(ptr %11) +// CHECK-NEXT: %13 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 +// CHECK-NEXT: %14 = icmp eq ptr %2, null +// CHECK-NEXT: br i1 %14, label %110, label %111 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %111 +// CHECK-NEXT: %15 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @122, i64 18 }, ptr %15, align 8 +// CHECK-NEXT: %16 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %15, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %16) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %111 +// CHECK-NEXT: %17 = alloca %"{{.*}}/runtime/abi.StructField", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %17, i8 0, i64 56, i1 false) +// CHECK-NEXT: %18 = icmp eq ptr %2, null +// CHECK-NEXT: br i1 %18, label %114, label %115 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %147 +// CHECK-NEXT: %19 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @123, 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: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_6: ; preds = %147 +// CHECK-NEXT: %21 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %17, i32 0, i32 1 +// CHECK-NEXT: %22 = load ptr, ptr %21, align 8 +// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/abi.(*Type).Elem"(ptr %22) +// CHECK-NEXT: %24 = getelementptr inbounds %main.eface, ptr %5, i32 0, i32 0 +// CHECK-NEXT: %25 = icmp eq ptr %5, null +// CHECK-NEXT: br i1 %25, label %150, label %151 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_7: ; preds = %151 +// CHECK-NEXT: %26 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @124, i64 18 }, 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: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_8: ; preds = %151 +// CHECK-NEXT: %28 = alloca %"{{.*}}/runtime/abi.StructField", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %28, i8 0, i64 56, i1 false) +// CHECK-NEXT: %29 = icmp eq ptr %2, null +// CHECK-NEXT: br i1 %29, label %154, label %155 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_9: ; preds = %197 +// CHECK-NEXT: %30 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @125, i64 13 }, ptr %30, align 8 +// CHECK-NEXT: %31 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %30, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %31) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_10: ; preds = %197 +// CHECK-NEXT: %32 = alloca %"{{.*}}/runtime/abi.StructField", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %32, i8 0, i64 56, i1 false) +// CHECK-NEXT: %33 = icmp eq ptr %2, null +// CHECK-NEXT: br i1 %33, label %200, label %201 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_11: ; preds = %225 +// CHECK-NEXT: %34 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @126, i64 13 }, ptr %34, align 8 +// CHECK-NEXT: %35 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %34, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %35) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_12: ; preds = %225 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: 36: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 37: ; preds = %_llgo_0 +// CHECK-NEXT: %38 = load ptr, ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %38) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %12 = getelementptr inbounds %main.eface, ptr %5, i32 0, i32 0 -// CHECK-NEXT: %13 = load ptr, ptr %12, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %13) +// CHECK-NEXT: %39 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 +// CHECK-NEXT: %40 = icmp eq ptr %2, null +// CHECK-NEXT: br i1 %40, label %41, label %42 +// CHECK-EMPTY: +// CHECK-NEXT: 41: ; preds = %37 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 42: ; preds = %37 +// CHECK-NEXT: %43 = load ptr, ptr %39, align 8 +// CHECK-NEXT: %44 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %43, i32 0, i32 10 +// CHECK-NEXT: %45 = icmp eq ptr %2, null +// CHECK-NEXT: br i1 %45, label %46, label %47 +// CHECK-EMPTY: +// CHECK-NEXT: 46: ; preds = %42 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 47: ; preds = %42 +// CHECK-NEXT: %48 = icmp eq ptr %39, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %48) +// CHECK-NEXT: %49 = icmp eq ptr %43, null +// CHECK-NEXT: br i1 %49, label %50, label %51 +// CHECK-EMPTY: +// CHECK-NEXT: 50: ; preds = %47 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 51: ; preds = %47 +// CHECK-NEXT: %52 = load ptr, ptr %44, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %52) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %14 = getelementptr inbounds %main.eface, ptr %5, i32 0, i32 0 -// CHECK-NEXT: %15 = load ptr, ptr %14, align 8 -// CHECK-NEXT: %16 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %15, i32 0, i32 10 -// CHECK-NEXT: %17 = load ptr, ptr %16, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %17) +// CHECK-NEXT: %53 = getelementptr inbounds %main.eface, ptr %5, i32 0, i32 0 +// CHECK-NEXT: %54 = icmp eq ptr %5, null +// CHECK-NEXT: br i1 %54, label %55, label %56 +// CHECK-EMPTY: +// CHECK-NEXT: 55: ; preds = %51 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 56: ; preds = %51 +// CHECK-NEXT: %57 = load ptr, ptr %53, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %57) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %18 = alloca %"{{.*}}/runtime/abi.StructField", align 8 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %18, i8 0, i64 56, i1 false) -// CHECK-NEXT: %19 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 -// CHECK-NEXT: %20 = load ptr, ptr %19, align 8 -// CHECK-NEXT: %21 = call ptr @"{{.*}}/runtime/abi.(*Type).StructType"(ptr %20) -// CHECK-NEXT: %22 = getelementptr inbounds %"{{.*}}/runtime/abi.StructType", ptr %21, i32 0, i32 2 -// CHECK-NEXT: %23 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %22, align 8 -// 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 0, %25 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %26, {{.*}}) -// CHECK-NEXT: %27 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %24, i64 0 -// CHECK-NEXT: %28 = load %"{{.*}}/runtime/abi.StructField", ptr %27, align 8 -// CHECK-NEXT: store %"{{.*}}/runtime/abi.StructField" %28, ptr %18, align 8 -// CHECK-NEXT: %29 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %18, i32 0, i32 1 -// CHECK-NEXT: %30 = load ptr, ptr %29, align 8 -// CHECK-NEXT: %31 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 -// CHECK-NEXT: %32 = load ptr, ptr %31, align 8 -// CHECK-NEXT: %33 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %32, i32 0, i32 10 -// CHECK-NEXT: %34 = load ptr, ptr %33, align 8 -// CHECK-NEXT: %35 = icmp ne ptr %30, %34 -// CHECK-NEXT: br i1 %35, label %_llgo_1, label %_llgo_2 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %36 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{.*}}, i64 13 }, 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: unreachable -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 -// CHECK-NEXT: %38 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %18, i32 0, i32 1 -// CHECK-NEXT: %39 = load ptr, ptr %38, align 8 -// CHECK-NEXT: %40 = call ptr @"{{.*}}/runtime/abi.(*Type).Elem"(ptr %39) -// CHECK-NEXT: %41 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 -// CHECK-NEXT: %42 = load ptr, ptr %41, align 8 -// CHECK-NEXT: %43 = icmp ne ptr %40, %42 -// CHECK-NEXT: br i1 %43, label %_llgo_3, label %_llgo_4 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 -// CHECK-NEXT: %44 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{.*}}, i64 18 }, ptr %44, align 8 -// CHECK-NEXT: %45 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %44, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %45) -// CHECK-NEXT: unreachable -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 -// CHECK-NEXT: %46 = alloca %"{{.*}}/runtime/abi.StructField", align 8 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %46, i8 0, i64 56, i1 false) -// CHECK-NEXT: %47 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 -// CHECK-NEXT: %48 = load ptr, ptr %47, align 8 -// CHECK-NEXT: %49 = call ptr @"{{.*}}/runtime/abi.(*Type).StructType"(ptr %48) -// CHECK-NEXT: %50 = getelementptr inbounds %"{{.*}}/runtime/abi.StructType", ptr %49, i32 0, i32 2 -// CHECK-NEXT: %51 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %50, align 8 -// CHECK-NEXT: %52 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %51, 0 -// CHECK-NEXT: %53 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %51, 1 -// CHECK-NEXT: %54 = icmp uge i64 1, %53 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %54, {{.*}}) -// CHECK-NEXT: %55 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %52, i64 1 -// CHECK-NEXT: %56 = load %"{{.*}}/runtime/abi.StructField", ptr %55, align 8 -// CHECK-NEXT: store %"{{.*}}/runtime/abi.StructField" %56, ptr %46, align 8 -// CHECK-NEXT: %57 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %46, i32 0, i32 1 -// CHECK-NEXT: %58 = load ptr, ptr %57, align 8 -// CHECK-NEXT: %59 = getelementptr inbounds %main.eface, ptr %5, i32 0, i32 0 -// CHECK-NEXT: %60 = load ptr, ptr %59, align 8 -// CHECK-NEXT: %61 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %60, i32 0, i32 10 -// CHECK-NEXT: %62 = load ptr, ptr %61, align 8 -// CHECK-NEXT: %63 = icmp ne ptr %58, %62 -// CHECK-NEXT: br i1 %63, label %_llgo_5, label %_llgo_6 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_5: ; preds = %_llgo_4 -// CHECK-NEXT: %64 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{.*}}, i64 13 }, ptr %64, align 8 -// CHECK-NEXT: %65 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %64, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %65) -// CHECK-NEXT: unreachable -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_6: ; preds = %_llgo_4 -// CHECK-NEXT: %66 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %46, i32 0, i32 1 -// CHECK-NEXT: %67 = load ptr, ptr %66, align 8 -// CHECK-NEXT: %68 = call ptr @"{{.*}}/runtime/abi.(*Type).Elem"(ptr %67) -// CHECK-NEXT: %69 = getelementptr inbounds %main.eface, ptr %5, i32 0, i32 0 -// CHECK-NEXT: %70 = load ptr, ptr %69, align 8 -// CHECK-NEXT: %71 = icmp ne ptr %68, %70 -// CHECK-NEXT: br i1 %71, label %_llgo_7, label %_llgo_8 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_7: ; preds = %_llgo_6 -// CHECK-NEXT: %72 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{.*}}, i64 18 }, ptr %72, align 8 -// CHECK-NEXT: %73 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %72, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %73) -// CHECK-NEXT: unreachable -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_8: ; preds = %_llgo_6 -// CHECK-NEXT: %74 = alloca %"{{.*}}/runtime/abi.StructField", align 8 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %74, i8 0, i64 56, i1 false) -// CHECK-NEXT: %75 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 -// CHECK-NEXT: %76 = load ptr, ptr %75, align 8 -// CHECK-NEXT: %77 = call ptr @"{{.*}}/runtime/abi.(*Type).StructType"(ptr %76) -// CHECK-NEXT: %78 = getelementptr inbounds %"{{.*}}/runtime/abi.StructType", ptr %77, i32 0, i32 2 -// CHECK-NEXT: %79 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %78, align 8 -// CHECK-NEXT: %80 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %79, 0 -// CHECK-NEXT: %81 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %79, 1 -// CHECK-NEXT: %82 = icmp uge i64 2, %81 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %82, {{.*}}) -// CHECK-NEXT: %83 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %80, i64 2 -// CHECK-NEXT: %84 = load %"{{.*}}/runtime/abi.StructField", ptr %83, align 8 -// CHECK-NEXT: store %"{{.*}}/runtime/abi.StructField" %84, ptr %74, align 8 -// CHECK-NEXT: %85 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %74, i32 0, i32 1 -// CHECK-NEXT: %86 = load ptr, ptr %85, align 8 -// CHECK-NEXT: %87 = getelementptr inbounds %main.eface, ptr %5, i32 0, i32 0 -// CHECK-NEXT: %88 = load ptr, ptr %87, align 8 -// CHECK-NEXT: %89 = call ptr @"{{.*}}/runtime/abi.(*Type).StructType"(ptr %88) -// CHECK-NEXT: %90 = getelementptr inbounds %"{{.*}}/runtime/abi.StructType", ptr %89, i32 0, i32 2 -// CHECK-NEXT: %91 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %90, align 8 -// CHECK-NEXT: %92 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %91, 0 -// CHECK-NEXT: %93 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %91, 1 -// CHECK-NEXT: %94 = icmp uge i64 0, %93 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %94, {{.*}}) -// CHECK-NEXT: %95 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %92, i64 0 -// CHECK-NEXT: %96 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %95, i32 0, i32 1 -// CHECK-NEXT: %97 = load ptr, ptr %96, align 8 -// CHECK-NEXT: %98 = icmp ne ptr %86, %97 -// CHECK-NEXT: br i1 %98, label %_llgo_9, label %_llgo_10 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_9: ; preds = %_llgo_8 -// CHECK-NEXT: %99 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{.*}}, i64 13 }, ptr %99, align 8 -// CHECK-NEXT: %100 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %99, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %100) -// CHECK-NEXT: unreachable -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_10: ; preds = %_llgo_8 -// CHECK-NEXT: %101 = alloca %"{{.*}}/runtime/abi.StructField", align 8 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %101, i8 0, i64 56, i1 false) -// CHECK-NEXT: %102 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 -// CHECK-NEXT: %103 = load ptr, ptr %102, align 8 -// CHECK-NEXT: %104 = call ptr @"{{.*}}/runtime/abi.(*Type).StructType"(ptr %103) -// CHECK-NEXT: %105 = getelementptr inbounds %"{{.*}}/runtime/abi.StructType", ptr %104, i32 0, i32 2 -// CHECK-NEXT: %106 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %105, align 8 -// CHECK-NEXT: %107 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %106, 0 -// CHECK-NEXT: %108 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %106, 1 -// CHECK-NEXT: %109 = icmp uge i64 3, %108 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %109, {{.*}}) -// CHECK-NEXT: %110 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %107, i64 3 -// CHECK-NEXT: %111 = load %"{{.*}}/runtime/abi.StructField", ptr %110, align 8 -// CHECK-NEXT: store %"{{.*}}/runtime/abi.StructField" %111, ptr %101, align 8 -// CHECK-NEXT: %112 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %101, i32 0, i32 1 -// CHECK-NEXT: %113 = load ptr, ptr %112, align 8 -// CHECK-NEXT: %114 = call ptr @"{{.*}}/runtime/abi.(*Type).Elem"(ptr %113) -// CHECK-NEXT: %115 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 -// CHECK-NEXT: %116 = load ptr, ptr %115, align 8 -// CHECK-NEXT: %117 = icmp ne ptr %114, %116 -// CHECK-NEXT: br i1 %117, label %_llgo_11, label %_llgo_12 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_11: ; preds = %_llgo_10 -// CHECK-NEXT: %118 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @{{.*}}, i64 13 }, ptr %118, align 8 -// CHECK-NEXT: %119 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %118, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %119) -// CHECK-NEXT: unreachable -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_12: ; preds = %_llgo_10 -// CHECK-NEXT: ret void +// CHECK-NEXT: %58 = getelementptr inbounds %main.eface, ptr %5, i32 0, i32 0 +// CHECK-NEXT: %59 = icmp eq ptr %5, null +// CHECK-NEXT: br i1 %59, label %60, label %61 +// CHECK-EMPTY: +// CHECK-NEXT: 60: ; preds = %56 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 61: ; preds = %56 +// CHECK-NEXT: %62 = load ptr, ptr %58, align 8 +// CHECK-NEXT: %63 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %62, i32 0, i32 10 +// CHECK-NEXT: %64 = icmp eq ptr %5, null +// CHECK-NEXT: br i1 %64, label %65, label %66 +// CHECK-EMPTY: +// CHECK-NEXT: 65: ; preds = %61 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 66: ; preds = %61 +// CHECK-NEXT: %67 = icmp eq ptr %58, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %67) +// CHECK-NEXT: %68 = icmp eq ptr %62, null +// CHECK-NEXT: br i1 %68, label %69, label %70 +// CHECK-EMPTY: +// CHECK-NEXT: 69: ; preds = %66 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 70: ; preds = %66 +// CHECK-NEXT: %71 = load ptr, ptr %63, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %71) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: %72 = alloca %"{{.*}}/runtime/abi.StructField", align 8 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %72, i8 0, i64 56, i1 false) +// CHECK-NEXT: %73 = icmp eq ptr %2, null +// CHECK-NEXT: br i1 %73, label %74, label %75 +// CHECK-EMPTY: +// CHECK-NEXT: 74: ; preds = %70 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 75: ; preds = %70 +// CHECK-NEXT: %76 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 +// CHECK-NEXT: %77 = load ptr, ptr %76, align 8 +// CHECK-NEXT: %78 = call ptr @"{{.*}}/runtime/abi.(*Type).StructType"(ptr %77) +// CHECK-NEXT: %79 = getelementptr inbounds %"{{.*}}/runtime/abi.StructType", ptr %78, i32 0, i32 2 +// CHECK-NEXT: %80 = icmp eq ptr %78, null +// CHECK-NEXT: br i1 %80, label %81, label %82 +// CHECK-EMPTY: +// CHECK-NEXT: 81: ; preds = %75 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 82: ; preds = %75 +// CHECK-NEXT: %83 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %79, align 8 +// CHECK-NEXT: %84 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %83, 0 +// CHECK-NEXT: %85 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %83, 1 +// CHECK-NEXT: %86 = icmp uge i64 0, %85 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %86, i64 0, i1 true, i64 %85) +// CHECK-NEXT: %87 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %84, i64 0 +// CHECK-NEXT: %88 = icmp eq ptr %78, null +// CHECK-NEXT: br i1 %88, label %89, label %90 +// CHECK-EMPTY: +// CHECK-NEXT: 89: ; preds = %82 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 90: ; preds = %82 +// CHECK-NEXT: %91 = icmp eq ptr %79, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %91) +// CHECK-NEXT: %92 = load %"{{.*}}/runtime/abi.StructField", ptr %87, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/abi.StructField" %92, ptr %72, align 8 +// CHECK-NEXT: %93 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %72, i32 0, i32 1 +// CHECK-NEXT: %94 = load ptr, ptr %93, align 8 +// CHECK-NEXT: %95 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 +// CHECK-NEXT: %96 = icmp eq ptr %2, null +// CHECK-NEXT: br i1 %96, label %97, label %98 +// CHECK-EMPTY: +// CHECK-NEXT: 97: ; preds = %90 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 98: ; preds = %90 +// CHECK-NEXT: %99 = load ptr, ptr %95, align 8 +// CHECK-NEXT: %100 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %99, i32 0, i32 10 +// CHECK-NEXT: %101 = icmp eq ptr %2, null +// CHECK-NEXT: br i1 %101, label %102, label %103 +// CHECK-EMPTY: +// CHECK-NEXT: 102: ; preds = %98 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 103: ; preds = %98 +// CHECK-NEXT: %104 = icmp eq ptr %95, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %104) +// CHECK-NEXT: %105 = icmp eq ptr %99, null +// CHECK-NEXT: br i1 %105, label %106, label %107 +// CHECK-EMPTY: +// CHECK-NEXT: 106: ; preds = %103 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 107: ; preds = %103 +// CHECK-NEXT: %108 = load ptr, ptr %100, align 8 +// CHECK-NEXT: %109 = icmp ne ptr %94, %108 +// CHECK-NEXT: br i1 %109, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: 110: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 111: ; preds = %_llgo_2 +// CHECK-NEXT: %112 = load ptr, ptr %13, align 8 +// CHECK-NEXT: %113 = icmp ne ptr %12, %112 +// CHECK-NEXT: br i1 %113, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: 114: ; preds = %_llgo_4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 115: ; preds = %_llgo_4 +// CHECK-NEXT: %116 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 +// CHECK-NEXT: %117 = load ptr, ptr %116, align 8 +// CHECK-NEXT: %118 = call ptr @"{{.*}}/runtime/abi.(*Type).StructType"(ptr %117) +// CHECK-NEXT: %119 = getelementptr inbounds %"{{.*}}/runtime/abi.StructType", ptr %118, i32 0, i32 2 +// CHECK-NEXT: %120 = icmp eq ptr %118, null +// CHECK-NEXT: br i1 %120, label %121, label %122 +// CHECK-EMPTY: +// CHECK-NEXT: 121: ; preds = %115 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 122: ; preds = %115 +// CHECK-NEXT: %123 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %119, align 8 +// CHECK-NEXT: %124 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %123, 0 +// CHECK-NEXT: %125 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %123, 1 +// CHECK-NEXT: %126 = icmp uge i64 1, %125 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %126, i64 1, i1 true, i64 %125) +// CHECK-NEXT: %127 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %124, i64 1 +// CHECK-NEXT: %128 = icmp eq ptr %118, null +// CHECK-NEXT: br i1 %128, label %129, label %130 +// CHECK-EMPTY: +// CHECK-NEXT: 129: ; preds = %122 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 130: ; preds = %122 +// CHECK-NEXT: %131 = icmp eq ptr %119, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %131) +// CHECK-NEXT: %132 = load %"{{.*}}/runtime/abi.StructField", ptr %127, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/abi.StructField" %132, ptr %17, align 8 +// CHECK-NEXT: %133 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %17, i32 0, i32 1 +// CHECK-NEXT: %134 = load ptr, ptr %133, align 8 +// CHECK-NEXT: %135 = getelementptr inbounds %main.eface, ptr %5, i32 0, i32 0 +// CHECK-NEXT: %136 = icmp eq ptr %5, null +// CHECK-NEXT: br i1 %136, label %137, label %138 +// CHECK-EMPTY: +// CHECK-NEXT: 137: ; preds = %130 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 138: ; preds = %130 +// CHECK-NEXT: %139 = load ptr, ptr %135, align 8 +// CHECK-NEXT: %140 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %139, i32 0, i32 10 +// CHECK-NEXT: %141 = icmp eq ptr %5, null +// CHECK-NEXT: br i1 %141, label %142, label %143 +// CHECK-EMPTY: +// CHECK-NEXT: 142: ; preds = %138 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 143: ; preds = %138 +// CHECK-NEXT: %144 = icmp eq ptr %135, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %144) +// CHECK-NEXT: %145 = icmp eq ptr %139, null +// CHECK-NEXT: br i1 %145, label %146, label %147 +// CHECK-EMPTY: +// CHECK-NEXT: 146: ; preds = %143 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 147: ; preds = %143 +// CHECK-NEXT: %148 = load ptr, ptr %140, align 8 +// CHECK-NEXT: %149 = icmp ne ptr %134, %148 +// CHECK-NEXT: br i1 %149, label %_llgo_5, label %_llgo_6 +// CHECK-EMPTY: +// CHECK-NEXT: 150: ; preds = %_llgo_6 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 151: ; preds = %_llgo_6 +// CHECK-NEXT: %152 = load ptr, ptr %24, align 8 +// CHECK-NEXT: %153 = icmp ne ptr %23, %152 +// CHECK-NEXT: br i1 %153, label %_llgo_7, label %_llgo_8 +// CHECK-EMPTY: +// CHECK-NEXT: 154: ; preds = %_llgo_8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 155: ; preds = %_llgo_8 +// CHECK-NEXT: %156 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 +// CHECK-NEXT: %157 = load ptr, ptr %156, align 8 +// CHECK-NEXT: %158 = call ptr @"{{.*}}/runtime/abi.(*Type).StructType"(ptr %157) +// CHECK-NEXT: %159 = getelementptr inbounds %"{{.*}}/runtime/abi.StructType", ptr %158, i32 0, i32 2 +// CHECK-NEXT: %160 = icmp eq ptr %158, null +// CHECK-NEXT: br i1 %160, label %161, label %162 +// CHECK-EMPTY: +// CHECK-NEXT: 161: ; preds = %155 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 162: ; preds = %155 +// CHECK-NEXT: %163 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %159, align 8 +// CHECK-NEXT: %164 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %163, 0 +// CHECK-NEXT: %165 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %163, 1 +// CHECK-NEXT: %166 = icmp uge i64 2, %165 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %166, i64 2, i1 true, i64 %165) +// CHECK-NEXT: %167 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %164, i64 2 +// CHECK-NEXT: %168 = icmp eq ptr %158, null +// CHECK-NEXT: br i1 %168, label %169, label %170 +// CHECK-EMPTY: +// CHECK-NEXT: 169: ; preds = %162 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 170: ; preds = %162 +// CHECK-NEXT: %171 = icmp eq ptr %159, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %171) +// CHECK-NEXT: %172 = load %"{{.*}}/runtime/abi.StructField", ptr %167, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/abi.StructField" %172, ptr %28, align 8 +// CHECK-NEXT: %173 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %28, i32 0, i32 1 +// CHECK-NEXT: %174 = load ptr, ptr %173, align 8 +// CHECK-NEXT: %175 = icmp eq ptr %5, null +// CHECK-NEXT: br i1 %175, label %176, label %177 +// CHECK-EMPTY: +// CHECK-NEXT: 176: ; preds = %170 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 177: ; preds = %170 +// CHECK-NEXT: %178 = getelementptr inbounds %main.eface, ptr %5, i32 0, i32 0 +// CHECK-NEXT: %179 = load ptr, ptr %178, align 8 +// CHECK-NEXT: %180 = call ptr @"{{.*}}/runtime/abi.(*Type).StructType"(ptr %179) +// CHECK-NEXT: %181 = getelementptr inbounds %"{{.*}}/runtime/abi.StructType", ptr %180, i32 0, i32 2 +// CHECK-NEXT: %182 = icmp eq ptr %180, null +// CHECK-NEXT: br i1 %182, label %183, label %184 +// CHECK-EMPTY: +// CHECK-NEXT: 183: ; preds = %177 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 184: ; preds = %177 +// CHECK-NEXT: %185 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %181, align 8 +// CHECK-NEXT: %186 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %185, 0 +// CHECK-NEXT: %187 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %185, 1 +// CHECK-NEXT: %188 = icmp uge i64 0, %187 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %188, i64 0, i1 true, i64 %187) +// CHECK-NEXT: %189 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %186, i64 0 +// CHECK-NEXT: %190 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %189, i32 0, i32 1 +// CHECK-NEXT: %191 = icmp eq ptr %180, null +// CHECK-NEXT: br i1 %191, label %192, label %193 +// CHECK-EMPTY: +// CHECK-NEXT: 192: ; preds = %184 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 193: ; preds = %184 +// CHECK-NEXT: %194 = icmp eq ptr %181, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %194) +// CHECK-NEXT: %195 = icmp eq ptr %189, null +// CHECK-NEXT: br i1 %195, label %196, label %197 +// CHECK-EMPTY: +// CHECK-NEXT: 196: ; preds = %193 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 197: ; preds = %193 +// CHECK-NEXT: %198 = load ptr, ptr %190, align 8 +// CHECK-NEXT: %199 = icmp ne ptr %174, %198 +// CHECK-NEXT: br i1 %199, label %_llgo_9, label %_llgo_10 +// CHECK-EMPTY: +// CHECK-NEXT: 200: ; preds = %_llgo_10 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 201: ; preds = %_llgo_10 +// CHECK-NEXT: %202 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 +// CHECK-NEXT: %203 = load ptr, ptr %202, align 8 +// CHECK-NEXT: %204 = call ptr @"{{.*}}/runtime/abi.(*Type).StructType"(ptr %203) +// CHECK-NEXT: %205 = getelementptr inbounds %"{{.*}}/runtime/abi.StructType", ptr %204, i32 0, i32 2 +// CHECK-NEXT: %206 = icmp eq ptr %204, null +// CHECK-NEXT: br i1 %206, label %207, label %208 +// CHECK-EMPTY: +// CHECK-NEXT: 207: ; preds = %201 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 208: ; preds = %201 +// CHECK-NEXT: %209 = load %"{{.*}}/runtime/internal/runtime.Slice", ptr %205, align 8 +// CHECK-NEXT: %210 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %209, 0 +// CHECK-NEXT: %211 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %209, 1 +// CHECK-NEXT: %212 = icmp uge i64 3, %211 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %212, i64 3, i1 true, i64 %211) +// CHECK-NEXT: %213 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %210, i64 3 +// CHECK-NEXT: %214 = icmp eq ptr %204, null +// CHECK-NEXT: br i1 %214, label %215, label %216 +// CHECK-EMPTY: +// CHECK-NEXT: 215: ; preds = %208 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 216: ; preds = %208 +// CHECK-NEXT: %217 = icmp eq ptr %205, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %217) +// CHECK-NEXT: %218 = load %"{{.*}}/runtime/abi.StructField", ptr %213, align 8 +// CHECK-NEXT: store %"{{.*}}/runtime/abi.StructField" %218, ptr %32, align 8 +// CHECK-NEXT: %219 = getelementptr inbounds %"{{.*}}/runtime/abi.StructField", ptr %32, i32 0, i32 1 +// CHECK-NEXT: %220 = load ptr, ptr %219, align 8 +// CHECK-NEXT: %221 = call ptr @"{{.*}}/runtime/abi.(*Type).Elem"(ptr %220) +// CHECK-NEXT: %222 = getelementptr inbounds %main.eface, ptr %2, i32 0, i32 0 +// CHECK-NEXT: %223 = icmp eq ptr %2, null +// CHECK-NEXT: br i1 %223, label %224, label %225 +// CHECK-EMPTY: +// CHECK-NEXT: 224: ; preds = %216 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 225: ; preds = %216 +// CHECK-NEXT: %226 = load ptr, ptr %222, align 8 +// CHECK-NEXT: %227 = icmp ne ptr %221, %226 +// CHECK-NEXT: br i1 %227, label %_llgo_11, label %_llgo_12 // CHECK-NEXT: } type T struct { diff --git a/cl/_testrt/abitype/in.go b/cl/_testrt/abitype/in.go index ced9c0c2d7..056cb9b883 100644 --- a/cl/_testrt/abitype/in.go +++ b/cl/_testrt/abitype/in.go @@ -14,41 +14,57 @@ import ( // CHECK-NEXT: store i32 0, ptr %1, align 4 // CHECK-NEXT: %2 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_int32, ptr undef }, ptr %1, 1 // CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %2, ptr %0, align 8 -// CHECK-NEXT: %3 = getelementptr inbounds %main.eface, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %4 = load ptr, ptr %3, align 8 -// CHECK-NEXT: %5 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/abi.(*Type).String"(ptr %4) -// CHECK-NEXT: %6 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %5, %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 5 }) -// CHECK-NEXT: %7 = xor i1 %6, true -// CHECK-NEXT: br i1 %7, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %3 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %3, label %11, label %12 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @1, i64 14 }, 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: _llgo_1: ; preds = %12 +// CHECK-NEXT: %4 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @1, i64 14 }, 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: %10 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) -// CHECK-NEXT: store i8 0, ptr %10, align 1 -// CHECK-NEXT: %11 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %10, 1 -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %11, ptr %0, align 8 -// CHECK-NEXT: %12 = getelementptr inbounds %main.eface, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %13 = load ptr, ptr %12, align 8 -// CHECK-NEXT: %14 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/abi.(*Type).String"(ptr %13) -// CHECK-NEXT: %15 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %14, %"{{.*}}/runtime/internal/runtime.String" { ptr @3, i64 5 }) -// CHECK-NEXT: %16 = xor i1 %15, true -// CHECK-NEXT: br i1 %16, label %_llgo_3, label %_llgo_4 +// CHECK-NEXT: _llgo_2: ; preds = %12 +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 1) +// CHECK-NEXT: store i8 0, ptr %6, align 1 +// CHECK-NEXT: %7 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_uint8, ptr undef }, ptr %6, 1 +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %7, ptr %0, align 8 +// CHECK-NEXT: %8 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %8, label %18, label %19 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 -// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @4, i64 14 }, 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: _llgo_3: ; preds = %19 +// CHECK-NEXT: %9 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @4, i64 14 }, ptr %9, align 8 +// CHECK-NEXT: %10 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %9, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %10) // CHECK-NEXT: unreachable // CHECK-EMPTY: -// CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 +// CHECK-NEXT: _llgo_4: ; preds = %19 // CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: 11: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 12: ; preds = %_llgo_0 +// CHECK-NEXT: %13 = getelementptr inbounds %main.eface, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %14 = load ptr, ptr %13, align 8 +// CHECK-NEXT: %15 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/abi.(*Type).String"(ptr %14) +// CHECK-NEXT: %16 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %15, %"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 5 }) +// CHECK-NEXT: %17 = xor i1 %16, true +// CHECK-NEXT: br i1 %17, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: 18: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 19: ; preds = %_llgo_2 +// CHECK-NEXT: %20 = getelementptr inbounds %main.eface, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %21 = load ptr, ptr %20, align 8 +// CHECK-NEXT: %22 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/abi.(*Type).String"(ptr %21) +// CHECK-NEXT: %23 = call i1 @"{{.*}}/runtime/internal/runtime.StringEqual"(%"{{.*}}/runtime/internal/runtime.String" %22, %"{{.*}}/runtime/internal/runtime.String" { ptr @3, i64 5 }) +// CHECK-NEXT: %24 = xor i1 %23, true +// CHECK-NEXT: br i1 %24, label %_llgo_3, label %_llgo_4 // CHECK-NEXT: } type eface struct { diff --git a/cl/_testrt/closure/in.go b/cl/_testrt/closure/in.go index 9f9b3571ee..6fb093bcad 100644 --- a/cl/_testrt/closure/in.go +++ b/cl/_testrt/closure/in.go @@ -42,10 +42,18 @@ func main() { // 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 }, ptr %2, align 8 - // CHECK-NEXT: %4 = extractvalue { ptr, ptr } %3, 1 - // CHECK-NEXT: %5 = extractvalue { ptr, ptr } %3, 0 - // CHECK-NEXT: call void %5(ptr %4, i64 100, i64 200) + // CHECK-NEXT: %3 = icmp eq ptr %2, null + // CHECK-NEXT: br i1 %3, label %4, label %5 + // CHECK-EMPTY: + // CHECK-NEXT: 4: ; preds = %_llgo_0 + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) + // CHECK-NEXT: unreachable + // CHECK-EMPTY: + // CHECK-NEXT: 5: ; preds = %_llgo_0 + // CHECK-NEXT: %6 = load { ptr, ptr }, ptr %2, align 8 + // CHECK-NEXT: %7 = extractvalue { ptr, ptr } %6, 1 + // CHECK-NEXT: %8 = extractvalue { ptr, ptr } %6, 0 + // CHECK-NEXT: call void %8(ptr %7, i64 100, i64 200) // CHECK-NEXT: ret void // CHECK-NEXT: } fn2 := func() { diff --git a/cl/_testrt/closureconv/in.go b/cl/_testrt/closureconv/in.go index 853b7da618..f6a9e1c1b1 100644 --- a/cl/_testrt/closureconv/in.go +++ b/cl/_testrt/closureconv/in.go @@ -13,9 +13,17 @@ type Call struct { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %3 = add i64 %1, %2 // CHECK-NEXT: %4 = getelementptr inbounds %main.Call, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %5 = load i64, ptr %4, align 8 -// CHECK-NEXT: %6 = add i64 %3, %5 -// CHECK-NEXT: ret i64 %6 +// CHECK-NEXT: %5 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %5, label %6, label %7 +// CHECK-EMPTY: +// CHECK-NEXT: 6: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 7: ; preds = %_llgo_0 +// CHECK-NEXT: %8 = load i64, ptr %4, align 8 +// CHECK-NEXT: %9 = add i64 %3, %8 +// CHECK-NEXT: ret i64 %9 // CHECK-NEXT: } func (c *Call) add(a int, b int) int { return a + b + c.n diff --git a/cl/_testrt/cvar/in.go b/cl/_testrt/cvar/in.go index 2a7b0a0d97..7a8416a18d 100644 --- a/cl/_testrt/cvar/in.go +++ b/cl/_testrt/cvar/in.go @@ -20,8 +20,6 @@ var barY struct { // CHECK-LABEL: define void @main.main(){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %0 = load { [16 x i8], [2 x ptr] }, ptr @_bar_x, align 8 -// CHECK-NEXT: %1 = load { [16 x i8] }, ptr @_bar_y, align 1 // CHECK-NEXT: ret void // CHECK-NEXT: } func main() { diff --git a/cl/_testrt/eface/in.go b/cl/_testrt/eface/in.go index 68b29347b3..e3a11a1f0e 100644 --- a/cl/_testrt/eface/in.go +++ b/cl/_testrt/eface/in.go @@ -22,8 +22,16 @@ func (t *T) Invoke() { // CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) // CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %0, ptr %1, align 8 // CHECK-NEXT: %2 = getelementptr inbounds %main.eface, ptr %1, i32 0, i32 0 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: call void @main.dumpTyp(ptr %3, %"{{.*}}/runtime/internal/runtime.String" zeroinitializer) +// CHECK-NEXT: %3 = icmp eq ptr %1, null +// CHECK-NEXT: br i1 %3, label %4, label %5 +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = load ptr, ptr %2, align 8 +// CHECK-NEXT: call void @main.dumpTyp(ptr %6, %"{{.*}}/runtime/internal/runtime.String" zeroinitializer) // CHECK-NEXT: ret void // CHECK-NEXT: } func dump(v any) { @@ -37,72 +45,136 @@ func dump(v any) { // CHECK-NEXT: %2 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/abi.(*Type).String"(ptr %0) // CHECK-NEXT: %3 = call i64 @"{{.*}}/runtime/abi.(*Type).Kind"(ptr %0) // CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %5 = load i64, ptr %4, align 8 -// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 1 -// CHECK-NEXT: %7 = load i64, ptr %6, align 8 -// CHECK-NEXT: %8 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 2 -// CHECK-NEXT: %9 = load i32, ptr %8, align 4 -// CHECK-NEXT: %10 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 3 -// CHECK-NEXT: %11 = load i8, ptr %10, align 1 -// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 4 -// CHECK-NEXT: %13 = load i8, ptr %12, align 1 -// CHECK-NEXT: %14 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 10 -// CHECK-NEXT: %15 = load ptr, ptr %14, align 8 -// CHECK-NEXT: %16 = call ptr @"{{.*}}/runtime/abi.(*Type).Uncommon"(ptr %0) +// CHECK-NEXT: %5 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %5, label %15, label %16 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_1: ; preds = %41 +// CHECK-NEXT: %6 = call ptr @"{{.*}}/runtime/abi.(*Type).Elem"(ptr %0) +// CHECK-NEXT: %7 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @1, i64 7 }) +// CHECK-NEXT: call void @main.dumpTyp(ptr %6, %"{{.*}}/runtime/internal/runtime.String" %7) +// CHECK-NEXT: br label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %41 +// CHECK-NEXT: %8 = call ptr @"{{.*}}/runtime/abi.(*Type).Uncommon"(ptr %0) +// CHECK-NEXT: %9 = icmp ne ptr %8, null +// CHECK-NEXT: br i1 %9, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 +// CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/abi.(*Type).Uncommon"(ptr %0) +// CHECK-NEXT: %11 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 9 }) +// CHECK-NEXT: call void @main.dumpUncommon(ptr %10, %"{{.*}}/runtime/internal/runtime.String" %11) +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 10 +// CHECK-NEXT: %13 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %13, label %49, label %50 +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_4: ; preds = %54, %50, %_llgo_2 +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: _llgo_5: ; preds = %50 +// CHECK-NEXT: %14 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %14, label %53, label %54 +// CHECK-EMPTY: +// CHECK-NEXT: 15: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 16: ; preds = %_llgo_0 +// CHECK-NEXT: %17 = load i64, ptr %4, align 8 +// CHECK-NEXT: %18 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 1 +// CHECK-NEXT: %19 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %19, label %20, label %21 +// CHECK-EMPTY: +// CHECK-NEXT: 20: ; preds = %16 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 21: ; preds = %16 +// CHECK-NEXT: %22 = load i64, ptr %18, align 8 +// CHECK-NEXT: %23 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 2 +// CHECK-NEXT: %24 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %24, label %25, label %26 +// CHECK-EMPTY: +// CHECK-NEXT: 25: ; preds = %21 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 26: ; preds = %21 +// CHECK-NEXT: %27 = load i32, ptr %23, align 4 +// CHECK-NEXT: %28 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 3 +// CHECK-NEXT: %29 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %29, label %30, label %31 +// CHECK-EMPTY: +// CHECK-NEXT: 30: ; preds = %26 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 31: ; preds = %26 +// CHECK-NEXT: %32 = load i8, ptr %28, align 1 +// CHECK-NEXT: %33 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 4 +// CHECK-NEXT: %34 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %34, label %35, label %36 +// CHECK-EMPTY: +// CHECK-NEXT: 35: ; preds = %31 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 36: ; preds = %31 +// CHECK-NEXT: %37 = load i8, ptr %33, align 1 +// CHECK-NEXT: %38 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 10 +// CHECK-NEXT: %39 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %39, label %40, label %41 +// CHECK-EMPTY: +// CHECK-NEXT: 40: ; preds = %36 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 41: ; preds = %36 +// CHECK-NEXT: %42 = load ptr, ptr %38, align 8 +// CHECK-NEXT: %43 = call ptr @"{{.*}}/runtime/abi.(*Type).Uncommon"(ptr %0) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %2) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %3) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %5) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %17) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %7) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %22) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: %17 = zext i32 %9 to i64 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %17) +// CHECK-NEXT: %44 = zext i32 %27 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %44) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: %18 = zext i8 %11 to i64 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %18) +// CHECK-NEXT: %45 = zext i8 %32 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %45) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: %19 = zext i8 %13 to i64 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %19) +// CHECK-NEXT: %46 = zext i8 %37 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %46) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %15) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %42) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %16) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintPointer"(ptr %43) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %20 = call ptr @"{{.*}}/runtime/abi.(*Type).Elem"(ptr %0) -// CHECK-NEXT: %21 = icmp ne ptr %20, null -// CHECK-NEXT: br i1 %21, label %_llgo_1, label %_llgo_2 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 -// CHECK-NEXT: %22 = call ptr @"{{.*}}/runtime/abi.(*Type).Elem"(ptr %0) -// CHECK-NEXT: %23 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{.*}}, i64 7 }) -// CHECK-NEXT: call void @main.dumpTyp(ptr %22, %"{{.*}}/runtime/internal/runtime.String" %23) -// CHECK-NEXT: br label %_llgo_2 +// CHECK-NEXT: %47 = call ptr @"{{.*}}/runtime/abi.(*Type).Elem"(ptr %0) +// CHECK-NEXT: %48 = icmp ne ptr %47, null +// CHECK-NEXT: br i1 %48, label %_llgo_1, label %_llgo_2 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 -// CHECK-NEXT: %24 = call ptr @"{{.*}}/runtime/abi.(*Type).Uncommon"(ptr %0) -// CHECK-NEXT: %25 = icmp ne ptr %24, null -// CHECK-NEXT: br i1 %25, label %_llgo_3, label %_llgo_4 +// CHECK-NEXT: 49: ; preds = %_llgo_3 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable // CHECK-EMPTY: -// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 -// CHECK-NEXT: %26 = call ptr @"{{.*}}/runtime/abi.(*Type).Uncommon"(ptr %0) -// CHECK-NEXT: %27 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{.*}}, i64 9 }) -// CHECK-NEXT: call void @main.dumpUncommon(ptr %26, %"{{.*}}/runtime/internal/runtime.String" %27) -// CHECK-NEXT: %28 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 10 -// CHECK-NEXT: %29 = load ptr, ptr %28, align 8 -// CHECK-NEXT: %30 = icmp ne ptr %29, null -// CHECK-NEXT: br i1 %30, label %_llgo_5, label %_llgo_4 -// CHECK-EMPTY: -// CHECK-NEXT: _llgo_4: ; preds = %_llgo_5, %_llgo_3, %_llgo_2 -// CHECK-NEXT: ret void +// CHECK-NEXT: 50: ; preds = %_llgo_3 +// CHECK-NEXT: %51 = load ptr, ptr %12, align 8 +// CHECK-NEXT: %52 = icmp ne ptr %51, null +// CHECK-NEXT: br i1 %52, label %_llgo_5, label %_llgo_4 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_5: ; preds = %_llgo_3 -// CHECK-NEXT: %31 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 10 -// CHECK-NEXT: %32 = load ptr, ptr %31, align 8 -// CHECK-NEXT: %33 = call ptr @"{{.*}}/runtime/abi.(*Type).Uncommon"(ptr %32) -// CHECK-NEXT: %34 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @{{.*}}, i64 9 }) -// CHECK-NEXT: call void @main.dumpUncommon(ptr %33, %"{{.*}}/runtime/internal/runtime.String" %34) +// CHECK-NEXT: 53: ; preds = %_llgo_5 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 54: ; preds = %_llgo_5 +// CHECK-NEXT: %55 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 10 +// CHECK-NEXT: %56 = load ptr, ptr %55, align 8 +// CHECK-NEXT: %57 = call ptr @"{{.*}}/runtime/abi.(*Type).Uncommon"(ptr %56) +// CHECK-NEXT: %58 = call %"{{.*}}/runtime/internal/runtime.String" @"{{.*}}/runtime/internal/runtime.StringCat"(%"{{.*}}/runtime/internal/runtime.String" %1, %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 9 }) +// CHECK-NEXT: call void @main.dumpUncommon(ptr %57, %"{{.*}}/runtime/internal/runtime.String" %58) // CHECK-NEXT: br label %_llgo_4 // CHECK-NEXT: } func dumpTyp(t *abi.Type, sep string) { @@ -123,18 +195,42 @@ func dumpTyp(t *abi.Type, sep string) { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %1) // CHECK-NEXT: %2 = getelementptr inbounds %"{{.*}}/runtime/abi.UncommonType", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %3 = load %"{{.*}}/runtime/internal/runtime.String", ptr %2, align 8 -// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/abi.UncommonType", ptr %0, i32 0, i32 1 -// CHECK-NEXT: %5 = load i16, ptr %4, align 2 -// CHECK-NEXT: %6 = getelementptr inbounds %"{{.*}}/runtime/abi.UncommonType", ptr %0, i32 0, i32 2 -// CHECK-NEXT: %7 = load i16, ptr %6, align 2 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %3) +// CHECK-NEXT: %3 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %3, label %4, label %5 +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = load %"{{.*}}/runtime/internal/runtime.String", ptr %2, align 8 +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/abi.UncommonType", ptr %0, i32 0, i32 1 +// CHECK-NEXT: %8 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %8, label %9, label %10 +// CHECK-EMPTY: +// CHECK-NEXT: 9: ; preds = %5 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 10: ; preds = %5 +// CHECK-NEXT: %11 = load i16, ptr %7, align 2 +// CHECK-NEXT: %12 = getelementptr inbounds %"{{.*}}/runtime/abi.UncommonType", ptr %0, i32 0, i32 2 +// CHECK-NEXT: %13 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %13, label %14, label %15 +// CHECK-EMPTY: +// CHECK-NEXT: 14: ; preds = %10 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 15: ; preds = %10 +// CHECK-NEXT: %16 = load i16, ptr %12, align 2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %6) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: %8 = zext i16 %5 to i64 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %8) +// CHECK-NEXT: %17 = zext i16 %11 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %17) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: %9 = zext i16 %7 to i64 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %9) +// CHECK-NEXT: %18 = zext i16 %16 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %18) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void // CHECK-NEXT: } diff --git a/cl/_testrt/float2any/in.go b/cl/_testrt/float2any/in.go index ee0e1cf095..fea4f953dd 100644 --- a/cl/_testrt/float2any/in.go +++ b/cl/_testrt/float2any/in.go @@ -37,9 +37,9 @@ func check32(v any) { // CHECK-LABEL: define void @main.check64(%"{{.*}}/runtime/internal/runtime.eface" %0){{.*}} { // CHECK: icmp eq ptr {{.*}}, @_llgo_float64 // CHECK: load i32, ptr -// CHECK: icmp ne i32 {{.*}}, 1405670641 -// CHECK: load i32, ptr // CHECK: icmp ne i32 {{.*}}, 1074340347 +// CHECK: load i32, ptr +// CHECK: icmp ne i32 {{.*}}, 1405670641 func check64(v any) { switch v.(type) { case float64: diff --git a/cl/_testrt/freevars/in.go b/cl/_testrt/freevars/in.go index 0a717e8bf5..76949dfb96 100644 --- a/cl/_testrt/freevars/in.go +++ b/cl/_testrt/freevars/in.go @@ -38,18 +38,34 @@ func main() { // CHECK-EMPTY: // CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 // CHECK-NEXT: %12 = extractvalue { ptr } %2, 0 - // CHECK-NEXT: %13 = load { ptr, ptr }, ptr %12, align 8 - // CHECK-NEXT: %14 = extractvalue { ptr, ptr } %13, 1 - // CHECK-NEXT: %15 = extractvalue { ptr, ptr } %13, 0 - // CHECK-NEXT: call void %15(ptr %14, %"{{.*}}/runtime/internal/runtime.iface" %1) - // CHECK-NEXT: ret void + // CHECK-NEXT: %13 = icmp eq ptr %12, null + // CHECK-NEXT: br i1 %13, label %16, label %17 // CHECK-EMPTY: // CHECK-NEXT: _llgo_2: ; preds = %_llgo_0 - // CHECK-NEXT: %16 = extractvalue { ptr } %2, 0 - // CHECK-NEXT: %17 = load { ptr, ptr }, ptr %16, align 8 - // CHECK-NEXT: %18 = extractvalue { ptr, ptr } %17, 1 - // CHECK-NEXT: %19 = extractvalue { ptr, ptr } %17, 0 - // CHECK-NEXT: call void %19(ptr %18, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer) + // CHECK-NEXT: %14 = extractvalue { ptr } %2, 0 + // CHECK-NEXT: %15 = icmp eq ptr %14, null + // CHECK-NEXT: br i1 %15, label %21, label %22 + // CHECK-EMPTY: + // CHECK-NEXT: 16: ; preds = %_llgo_1 + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) + // CHECK-NEXT: unreachable + // CHECK-EMPTY: + // CHECK-NEXT: 17: ; preds = %_llgo_1 + // CHECK-NEXT: %18 = load { ptr, ptr }, ptr %12, align 8 + // CHECK-NEXT: %19 = extractvalue { ptr, ptr } %18, 1 + // CHECK-NEXT: %20 = extractvalue { ptr, ptr } %18, 0 + // CHECK-NEXT: call void %20(ptr %19, %"{{.*}}/runtime/internal/runtime.iface" %1) + // CHECK-NEXT: ret void + // CHECK-EMPTY: + // CHECK-NEXT: 21: ; preds = %_llgo_2 + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) + // CHECK-NEXT: unreachable + // CHECK-EMPTY: + // CHECK-NEXT: 22: ; preds = %_llgo_2 + // CHECK-NEXT: %23 = load { ptr, ptr }, ptr %14, align 8 + // CHECK-NEXT: %24 = extractvalue { ptr, ptr } %23, 1 + // CHECK-NEXT: %25 = extractvalue { ptr, ptr } %23, 0 + // CHECK-NEXT: call void %25(ptr %24, %"{{.*}}/runtime/internal/runtime.iface" zeroinitializer) // CHECK-NEXT: ret void // CHECK-NEXT: } diff --git a/cl/_testrt/funcdecl/in.go b/cl/_testrt/funcdecl/in.go index 8efd3f4635..3c760dcad3 100644 --- a/cl/_testrt/funcdecl/in.go +++ b/cl/_testrt/funcdecl/in.go @@ -76,10 +76,36 @@ func check(fn func()) { // CHECK-NEXT: %1 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) // CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.eface" %0, ptr %1, align 8 // CHECK-NEXT: %2 = getelementptr inbounds %main.rtype, ptr %1, i32 0, i32 1 -// CHECK-NEXT: %3 = load ptr, ptr %2, align 8 -// CHECK-NEXT: %4 = getelementptr inbounds { ptr, ptr }, ptr %3, i32 0, i32 0 -// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 -// CHECK-NEXT: ret ptr %5 +// CHECK-NEXT: %3 = icmp eq ptr %1, null +// CHECK-NEXT: br i1 %3, label %4, label %5 +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = load ptr, ptr %2, align 8 +// CHECK-NEXT: %7 = getelementptr inbounds { ptr, ptr }, ptr %6, i32 0, i32 0 +// CHECK-NEXT: %8 = icmp eq ptr %1, null +// CHECK-NEXT: br i1 %8, label %9, label %10 +// CHECK-EMPTY: +// CHECK-NEXT: 9: ; preds = %5 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 10: ; preds = %5 +// CHECK-NEXT: %11 = icmp eq ptr %2, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %11) +// CHECK-NEXT: %12 = icmp eq ptr %6, null +// CHECK-NEXT: br i1 %12, label %13, label %14 +// CHECK-EMPTY: +// CHECK-NEXT: 13: ; preds = %10 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 14: ; preds = %10 +// CHECK-NEXT: %15 = load ptr, ptr %7, align 8 +// CHECK-NEXT: ret ptr %15 // CHECK-NEXT: } func closurePtr(a any) unsafe.Pointer { diff --git a/cl/_testrt/gblarray/in.go b/cl/_testrt/gblarray/in.go index 4d743a6713..479dc31e47 100644 --- a/cl/_testrt/gblarray/in.go +++ b/cl/_testrt/gblarray/in.go @@ -73,11 +73,27 @@ var ( // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %0 = call ptr @main.Basic(i64 24) // CHECK-NEXT: %1 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 6 -// CHECK-NEXT: %2 = load i8, ptr %1, align 1 -// CHECK-NEXT: %3 = zext i8 %2 to i64 -// CHECK-NEXT: %4 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %5 = load i64, ptr %4, align 8 -// CHECK-NEXT: %6 = call i32 (ptr, ...) @printf(ptr @0, i64 %3, i64 %5) +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load i8, ptr %1, align 1 +// CHECK-NEXT: %6 = zext i8 %5 to i64 +// CHECK-NEXT: %7 = getelementptr inbounds %"{{.*}}/runtime/abi.Type", ptr %0, i32 0, i32 0 +// CHECK-NEXT: %8 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %8, label %9, label %10 +// CHECK-EMPTY: +// CHECK-NEXT: 9: ; preds = %4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 10: ; preds = %4 +// CHECK-NEXT: %11 = load i64, ptr %7, align 8 +// CHECK-NEXT: %12 = call i32 (ptr, ...) @printf(ptr @0, i64 %6, i64 %11) // CHECK-NEXT: ret void // CHECK-NEXT: } func main() { diff --git a/cl/_testrt/index/in.go b/cl/_testrt/index/in.go index 8f19ac4768..ec5b51a566 100644 --- a/cl/_testrt/index/in.go +++ b/cl/_testrt/index/in.go @@ -125,28 +125,36 @@ type S []int // CHECK-NEXT: store i64 1, ptr %53, align 8 // CHECK-NEXT: store i64 2, ptr %54, align 8 // CHECK-NEXT: %55 = getelementptr inbounds i64, ptr %52, i64 1 -// CHECK-NEXT: %56 = load i64, ptr %55, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %56) +// CHECK-NEXT: %56 = icmp eq ptr %52, null +// CHECK-NEXT: br i1 %56, label %57, label %58 +// CHECK-EMPTY: +// CHECK-NEXT: 57: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 58: ; preds = %_llgo_0 +// CHECK-NEXT: %59 = load i64, ptr %55, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %59) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %57 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) -// CHECK-NEXT: %58 = getelementptr inbounds i64, ptr %57, i64 0 -// CHECK-NEXT: store i64 1, ptr %58, align 8 -// CHECK-NEXT: %59 = getelementptr inbounds i64, ptr %57, i64 1 -// CHECK-NEXT: store i64 2, ptr %59, align 8 -// CHECK-NEXT: %60 = getelementptr inbounds i64, ptr %57, i64 2 -// CHECK-NEXT: store i64 3, ptr %60, align 8 -// CHECK-NEXT: %61 = getelementptr inbounds i64, ptr %57, i64 3 -// CHECK-NEXT: store i64 4, ptr %61, align 8 -// CHECK-NEXT: %62 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %57, 0 -// CHECK-NEXT: %63 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %62, i64 4, 1 -// CHECK-NEXT: %64 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %63, i64 4, 2 -// CHECK-NEXT: %65 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %64, 0 -// CHECK-NEXT: %66 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %64, 1 -// CHECK-NEXT: %67 = icmp uge i64 1, %66 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %67, i64 1, i1 true, i64 %66) -// CHECK-NEXT: %68 = getelementptr inbounds i64, ptr %65, i64 1 -// CHECK-NEXT: %69 = load i64, ptr %68, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %69) +// CHECK-NEXT: %60 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 32) +// CHECK-NEXT: %61 = getelementptr inbounds i64, ptr %60, i64 0 +// CHECK-NEXT: store i64 1, ptr %61, align 8 +// CHECK-NEXT: %62 = getelementptr inbounds i64, ptr %60, i64 1 +// CHECK-NEXT: store i64 2, ptr %62, align 8 +// CHECK-NEXT: %63 = getelementptr inbounds i64, ptr %60, i64 2 +// CHECK-NEXT: store i64 3, ptr %63, align 8 +// CHECK-NEXT: %64 = getelementptr inbounds i64, ptr %60, i64 3 +// CHECK-NEXT: store i64 4, ptr %64, align 8 +// CHECK-NEXT: %65 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %60, 0 +// CHECK-NEXT: %66 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %65, i64 4, 1 +// CHECK-NEXT: %67 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %66, i64 4, 2 +// CHECK-NEXT: %68 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %67, 0 +// CHECK-NEXT: %69 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %67, 1 +// CHECK-NEXT: %70 = icmp uge i64 1, %69 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.CheckIndexRange"(i1 %70, i64 1, i1 true, i64 %69) +// CHECK-NEXT: %71 = getelementptr inbounds i64, ptr %68, i64 1 +// CHECK-NEXT: %72 = load i64, ptr %71, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %72) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 0) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) diff --git a/cl/_testrt/intgen/in.go b/cl/_testrt/intgen/in.go index cc8d1d42a3..a326cbfca5 100644 --- a/cl/_testrt/intgen/in.go +++ b/cl/_testrt/intgen/in.go @@ -45,13 +45,29 @@ func genInts(n int, gen func() c.Int) []c.Int { // CHECK-LABEL: define i32 @"main.(*generator).next"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.generator, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load i32, ptr %1, align 4 -// CHECK-NEXT: %3 = add i32 %2, 1 -// CHECK-NEXT: %4 = getelementptr inbounds %main.generator, ptr %0, i32 0, i32 0 -// CHECK-NEXT: store i32 %3, ptr %4, align 4 -// CHECK-NEXT: %5 = getelementptr inbounds %main.generator, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %6 = load i32, ptr %5, align 4 -// CHECK-NEXT: ret i32 %6 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load i32, ptr %1, align 4 +// CHECK-NEXT: %6 = add i32 %5, 1 +// CHECK-NEXT: %7 = getelementptr inbounds %main.generator, ptr %0, i32 0, i32 0 +// CHECK-NEXT: store i32 %6, ptr %7, align 4 +// CHECK-NEXT: %8 = getelementptr inbounds %main.generator, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %9 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %9, label %10, label %11 +// CHECK-EMPTY: +// CHECK-NEXT: 10: ; preds = %4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 11: ; preds = %4 +// CHECK-NEXT: %12 = load i32, ptr %8, align 4 +// CHECK-NEXT: ret i32 %12 // CHECK-NEXT: } func (g *generator) next() c.Int { g.val++ diff --git a/cl/_testrt/makemap/in.go b/cl/_testrt/makemap/in.go index d3693bcb69..79631c1bc2 100644 --- a/cl/_testrt/makemap/in.go +++ b/cl/_testrt/makemap/in.go @@ -596,7 +596,7 @@ func make3() { // CHECK-NEXT: %38 = call ptr @"{{.*}}/runtime/internal/runtime.NewMapIter"(ptr @"map[_llgo_any]_llgo_int", ptr %17) // CHECK-NEXT: br label %_llgo_1 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_7, %_llgo_0 +// CHECK-NEXT: _llgo_1: ; preds = %61, %_llgo_0 // CHECK-NEXT: %39 = call { i1, ptr, ptr } @"{{.*}}/runtime/internal/runtime.MapIterNext"(ptr %38) // CHECK-NEXT: %40 = extractvalue { i1, ptr, ptr } %39, 0 // CHECK-NEXT: br i1 %40, label %_llgo_4, label %_llgo_5 @@ -637,17 +637,25 @@ func make3() { // CHECK-NEXT: %56 = getelementptr inbounds ptr, ptr %55, i64 0 // CHECK-NEXT: %57 = load ptr, ptr %56, align 8 // CHECK-NEXT: %58 = getelementptr inbounds %main.N, ptr %57, i32 0, i32 0 -// CHECK-NEXT: %59 = load i8, ptr %58, align 1 -// CHECK-NEXT: %60 = sext i8 %59 to i64 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %60) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %42) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: br label %_llgo_1 +// CHECK-NEXT: %59 = icmp eq ptr %57, null +// CHECK-NEXT: br i1 %59, label %60, label %61 // CHECK-EMPTY: // CHECK-NEXT: _llgo_8: ; preds = %_llgo_2 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicTypeAssert"(ptr %43, %"{{.*}}/runtime/internal/runtime.String" { ptr @42, i64 44 }, %"{{.*}}/runtime/internal/runtime.String" zeroinitializer) // CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 60: ; preds = %_llgo_7 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 61: ; preds = %_llgo_7 +// CHECK-NEXT: %62 = load i8, ptr %58, align 1 +// CHECK-NEXT: %63 = sext i8 %62 to i64 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %63) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %42) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) +// CHECK-NEXT: br label %_llgo_1 // CHECK-NEXT: } func make4() { diff --git a/cl/_testrt/mapclosure/in.go b/cl/_testrt/mapclosure/in.go index a866b94a17..32bf22108e 100644 --- a/cl/_testrt/mapclosure/in.go +++ b/cl/_testrt/mapclosure/in.go @@ -88,8 +88,16 @@ func main() { // CHECK-LABEL: define %"{{.*}}/runtime/internal/runtime.String" @"main.(*typ).String"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.typ, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load %"{{.*}}/runtime/internal/runtime.String", ptr %1, align 8 -// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load %"{{.*}}/runtime/internal/runtime.String", ptr %1, align 8 +// CHECK-NEXT: ret %"{{.*}}/runtime/internal/runtime.String" %5 // CHECK-NEXT: } func (t *typ) String() string { diff --git a/cl/_testrt/methodthunk/in.go b/cl/_testrt/methodthunk/in.go index afe1ec56b3..2661817de4 100644 --- a/cl/_testrt/methodthunk/in.go +++ b/cl/_testrt/methodthunk/in.go @@ -13,8 +13,16 @@ type outer struct { // CHECK-LABEL: define i64 @"main.(*InnerInt).M"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %main.InnerInt, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load i64, ptr %1, align 8 -// CHECK-NEXT: ret i64 %2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load i64, ptr %1, align 8 +// CHECK-NEXT: ret i64 %5 // CHECK-NEXT: } func (*inner) M() {} @@ -24,9 +32,17 @@ type InnerInt struct { // CHECK-LABEL: define i64 @"main.(*OuterInt).M"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds %main.OuterInt, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = call i64 @"main.(*InnerInt).M"(ptr %1) -// CHECK-NEXT: ret i64 %2 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds %main.OuterInt, ptr %0, i32 0, i32 1 +// CHECK-NEXT: %5 = call i64 @"main.(*InnerInt).M"(ptr %4) +// CHECK-NEXT: ret i64 %5 // CHECK-NEXT: } type OuterInt struct { Y int diff --git a/cl/_testrt/named/in.go b/cl/_testrt/named/in.go index 07d435287a..6bdce9bdc9 100644 --- a/cl/_testrt/named/in.go +++ b/cl/_testrt/named/in.go @@ -36,80 +36,310 @@ type mspan struct { // CHECK-NEXT: store ptr %5, ptr %6, align 8 // CHECK-NEXT: %7 = load ptr, ptr %0, align 8 // CHECK-NEXT: %8 = getelementptr inbounds %main.mspan, ptr %7, i32 0, i32 0 -// CHECK-NEXT: %9 = load ptr, ptr %8, align 8 -// CHECK-NEXT: %10 = getelementptr inbounds %main.mspan, ptr %9, i32 0, i32 4 -// CHECK-NEXT: store i64 200, ptr %10, align 8 -// CHECK-NEXT: %11 = load ptr, ptr %0, align 8 -// CHECK-NEXT: %12 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) -// CHECK-NEXT: %13 = getelementptr inbounds %main.mspan, ptr %11, i32 0, i32 2 -// CHECK-NEXT: store ptr %12, ptr %13, align 8 +// CHECK-NEXT: %9 = icmp eq ptr %7, null +// CHECK-NEXT: br i1 %9, label %10, label %11 +// CHECK-EMPTY: +// CHECK-NEXT: 10: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 11: ; preds = %_llgo_0 +// CHECK-NEXT: %12 = load ptr, ptr %8, align 8 +// CHECK-NEXT: %13 = getelementptr inbounds %main.mspan, ptr %12, i32 0, i32 4 +// CHECK-NEXT: store i64 200, ptr %13, align 8 // CHECK-NEXT: %14 = load ptr, ptr %0, align 8 -// CHECK-NEXT: %15 = getelementptr inbounds %main.mspan, ptr %14, i32 0, i32 2 -// CHECK-NEXT: %16 = load ptr, ptr %15, align 8 -// CHECK-NEXT: %17 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 64) -// CHECK-NEXT: %18 = getelementptr inbounds %main.mSpanList, ptr %16, i32 0, i32 1 -// CHECK-NEXT: store ptr %17, ptr %18, align 8 -// CHECK-NEXT: %19 = load ptr, ptr %0, align 8 -// CHECK-NEXT: %20 = getelementptr inbounds %main.mspan, ptr %19, i32 0, i32 2 -// CHECK-NEXT: %21 = load ptr, ptr %20, align 8 -// CHECK-NEXT: %22 = getelementptr inbounds %main.mSpanList, ptr %21, i32 0, i32 1 -// CHECK-NEXT: %23 = load ptr, ptr %22, align 8 -// CHECK-NEXT: %24 = getelementptr inbounds %main.mspan, ptr %23, i32 0, i32 4 -// CHECK-NEXT: store i64 300, ptr %24, align 8 +// CHECK-NEXT: %15 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 16) +// CHECK-NEXT: %16 = getelementptr inbounds %main.mspan, ptr %14, i32 0, i32 2 +// CHECK-NEXT: store ptr %15, ptr %16, align 8 +// CHECK-NEXT: %17 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %18 = getelementptr inbounds %main.mspan, ptr %17, i32 0, i32 2 +// CHECK-NEXT: %19 = icmp eq ptr %17, null +// CHECK-NEXT: br i1 %19, label %20, label %21 +// CHECK-EMPTY: +// CHECK-NEXT: 20: ; preds = %11 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 21: ; preds = %11 +// CHECK-NEXT: %22 = load ptr, ptr %18, align 8 +// CHECK-NEXT: %23 = call ptr @"{{.*}}/runtime/internal/runtime.AllocZ"(i64 64) +// CHECK-NEXT: %24 = getelementptr inbounds %main.mSpanList, ptr %22, i32 0, i32 1 +// CHECK-NEXT: store ptr %23, ptr %24, align 8 // CHECK-NEXT: %25 = load ptr, ptr %0, align 8 -// CHECK-NEXT: %26 = getelementptr inbounds %main.mspan, ptr %25, i32 0, i32 3 -// CHECK-NEXT: %27 = getelementptr inbounds %main.minfo, ptr %26, i32 0, i32 1 -// CHECK-NEXT: store i64 10, ptr %27, align 8 -// CHECK-NEXT: %28 = load ptr, ptr %0, align 8 -// CHECK-NEXT: %29 = getelementptr inbounds %main.mspan, ptr %28, i32 0, i32 3 -// CHECK-NEXT: %30 = load ptr, ptr %0, align 8 -// CHECK-NEXT: %31 = getelementptr inbounds %main.minfo, ptr %29, i32 0, i32 0 -// CHECK-NEXT: store ptr %30, ptr %31, align 8 -// CHECK-NEXT: %32 = load ptr, ptr %0, align 8 -// CHECK-NEXT: %33 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) -// CHECK-NEXT: %34 = getelementptr inbounds { ptr }, ptr %33, i32 0, i32 0 -// CHECK-NEXT: store ptr %0, ptr %34, align 8 -// CHECK-NEXT: %35 = insertvalue { ptr, ptr } { ptr @"main.main$1", ptr undef }, ptr %33, 1 -// CHECK-NEXT: %36 = getelementptr inbounds %main.mspan, ptr %32, i32 0, i32 5 -// CHECK-NEXT: store { ptr, ptr } %35, ptr %36, align 8 -// CHECK-NEXT: %37 = load ptr, ptr %0, align 8 -// CHECK-NEXT: %38 = getelementptr inbounds %main.mspan, ptr %37, i32 0, i32 0 -// CHECK-NEXT: %39 = load ptr, ptr %38, align 8 +// CHECK-NEXT: %26 = getelementptr inbounds %main.mspan, ptr %25, i32 0, i32 2 +// CHECK-NEXT: %27 = icmp eq ptr %25, null +// CHECK-NEXT: br i1 %27, label %28, label %29 +// CHECK-EMPTY: +// CHECK-NEXT: 28: ; preds = %21 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 29: ; preds = %21 +// CHECK-NEXT: %30 = load ptr, ptr %26, align 8 +// CHECK-NEXT: %31 = getelementptr inbounds %main.mSpanList, ptr %30, i32 0, i32 1 +// CHECK-NEXT: %32 = icmp eq ptr %25, null +// CHECK-NEXT: br i1 %32, label %33, label %34 +// CHECK-EMPTY: +// CHECK-NEXT: 33: ; preds = %29 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 34: ; preds = %29 +// CHECK-NEXT: %35 = icmp eq ptr %26, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %35) +// CHECK-NEXT: %36 = icmp eq ptr %30, null +// CHECK-NEXT: br i1 %36, label %37, label %38 +// CHECK-EMPTY: +// CHECK-NEXT: 37: ; preds = %34 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 38: ; preds = %34 +// CHECK-NEXT: %39 = load ptr, ptr %31, align 8 // CHECK-NEXT: %40 = getelementptr inbounds %main.mspan, ptr %39, i32 0, i32 4 -// CHECK-NEXT: %41 = load i64, ptr %40, align 8 -// CHECK-NEXT: %42 = load ptr, ptr %0, align 8 -// CHECK-NEXT: %43 = getelementptr inbounds %main.mspan, ptr %42, i32 0, i32 2 -// CHECK-NEXT: %44 = load ptr, ptr %43, align 8 -// CHECK-NEXT: %45 = getelementptr inbounds %main.mSpanList, ptr %44, i32 0, i32 1 -// CHECK-NEXT: %46 = load ptr, ptr %45, align 8 -// CHECK-NEXT: %47 = getelementptr inbounds %main.mspan, ptr %46, i32 0, i32 4 -// CHECK-NEXT: %48 = load i64, ptr %47, align 8 -// CHECK-NEXT: %49 = load ptr, ptr %0, align 8 -// CHECK-NEXT: %50 = getelementptr inbounds %main.mspan, ptr %49, i32 0, i32 3 -// CHECK-NEXT: %51 = getelementptr inbounds %main.minfo, ptr %50, i32 0, i32 1 -// CHECK-NEXT: %52 = load i64, ptr %51, align 8 +// CHECK-NEXT: store i64 300, ptr %40, align 8 +// CHECK-NEXT: %41 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %42 = getelementptr inbounds %main.mspan, ptr %41, i32 0, i32 3 +// CHECK-NEXT: %43 = getelementptr inbounds %main.minfo, ptr %42, i32 0, i32 1 +// CHECK-NEXT: store i64 10, ptr %43, align 8 +// CHECK-NEXT: %44 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %45 = getelementptr inbounds %main.mspan, ptr %44, i32 0, i32 3 +// CHECK-NEXT: %46 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %47 = getelementptr inbounds %main.minfo, ptr %45, i32 0, i32 0 +// CHECK-NEXT: store ptr %46, ptr %47, align 8 +// CHECK-NEXT: %48 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %49 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 8) +// CHECK-NEXT: %50 = getelementptr inbounds { ptr }, ptr %49, i32 0, i32 0 +// CHECK-NEXT: store ptr %0, ptr %50, align 8 +// CHECK-NEXT: %51 = insertvalue { ptr, ptr } { ptr @"main.main$1", ptr undef }, ptr %49, 1 +// CHECK-NEXT: %52 = getelementptr inbounds %main.mspan, ptr %48, i32 0, i32 5 +// CHECK-NEXT: store { ptr, ptr } %51, ptr %52, align 8 // CHECK-NEXT: %53 = load ptr, ptr %0, align 8 -// CHECK-NEXT: %54 = getelementptr inbounds %main.mspan, ptr %53, i32 0, i32 3 -// CHECK-NEXT: %55 = getelementptr inbounds %main.minfo, ptr %54, i32 0, i32 0 -// CHECK-NEXT: %56 = load ptr, ptr %55, align 8 -// CHECK-NEXT: %57 = getelementptr inbounds %main.mspan, ptr %56, i32 0, i32 4 -// CHECK-NEXT: %58 = load i64, ptr %57, align 8 -// CHECK-NEXT: %59 = load ptr, ptr %0, align 8 -// CHECK-NEXT: %60 = getelementptr inbounds %main.mspan, ptr %59, i32 0, i32 5 -// CHECK-NEXT: %61 = load { ptr, ptr }, ptr %60, align 8 -// CHECK-NEXT: %62 = extractvalue { ptr, ptr } %61, 1 -// CHECK-NEXT: %63 = extractvalue { ptr, ptr } %61, 0 -// CHECK-NEXT: %64 = call i64 %63(ptr %62, i64 -2) -// CHECK-NEXT: %65 = load ptr, ptr %0, align 8 -// CHECK-NEXT: %66 = getelementptr inbounds %main.mspan, ptr %65, i32 0, i32 3 -// CHECK-NEXT: %67 = getelementptr inbounds %main.minfo, ptr %66, i32 0, i32 0 -// CHECK-NEXT: %68 = load ptr, ptr %67, align 8 -// CHECK-NEXT: %69 = getelementptr inbounds %main.mspan, ptr %68, i32 0, i32 5 -// CHECK-NEXT: %70 = load { ptr, ptr }, ptr %69, align 8 -// CHECK-NEXT: %71 = extractvalue { ptr, ptr } %70, 1 -// CHECK-NEXT: %72 = extractvalue { ptr, ptr } %70, 0 -// CHECK-NEXT: %73 = call i64 %72(ptr %71, i64 -3) -// CHECK-NEXT: %74 = call i32 (ptr, ...) @printf(ptr @0, i64 %41, i64 %48, i64 %52, i64 %58, i64 %64, i64 %73) +// CHECK-NEXT: %54 = getelementptr inbounds %main.mspan, ptr %53, i32 0, i32 0 +// CHECK-NEXT: %55 = icmp eq ptr %53, null +// CHECK-NEXT: br i1 %55, label %56, label %57 +// CHECK-EMPTY: +// CHECK-NEXT: 56: ; preds = %38 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 57: ; preds = %38 +// CHECK-NEXT: %58 = load ptr, ptr %54, align 8 +// CHECK-NEXT: %59 = getelementptr inbounds %main.mspan, ptr %58, i32 0, i32 4 +// CHECK-NEXT: %60 = icmp eq ptr %53, null +// CHECK-NEXT: br i1 %60, label %61, label %62 +// CHECK-EMPTY: +// CHECK-NEXT: 61: ; preds = %57 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 62: ; preds = %57 +// CHECK-NEXT: %63 = icmp eq ptr %54, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %63) +// CHECK-NEXT: %64 = icmp eq ptr %58, null +// CHECK-NEXT: br i1 %64, label %65, label %66 +// CHECK-EMPTY: +// CHECK-NEXT: 65: ; preds = %62 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 66: ; preds = %62 +// CHECK-NEXT: %67 = load i64, ptr %59, align 8 +// CHECK-NEXT: %68 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %69 = getelementptr inbounds %main.mspan, ptr %68, i32 0, i32 2 +// CHECK-NEXT: %70 = icmp eq ptr %68, null +// CHECK-NEXT: br i1 %70, label %71, label %72 +// CHECK-EMPTY: +// CHECK-NEXT: 71: ; preds = %66 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 72: ; preds = %66 +// CHECK-NEXT: %73 = load ptr, ptr %69, align 8 +// CHECK-NEXT: %74 = getelementptr inbounds %main.mSpanList, ptr %73, i32 0, i32 1 +// CHECK-NEXT: %75 = icmp eq ptr %68, null +// CHECK-NEXT: br i1 %75, label %76, label %77 +// CHECK-EMPTY: +// CHECK-NEXT: 76: ; preds = %72 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 77: ; preds = %72 +// CHECK-NEXT: %78 = icmp eq ptr %69, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %78) +// CHECK-NEXT: %79 = icmp eq ptr %73, null +// CHECK-NEXT: br i1 %79, label %80, label %81 +// CHECK-EMPTY: +// CHECK-NEXT: 80: ; preds = %77 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 81: ; preds = %77 +// CHECK-NEXT: %82 = load ptr, ptr %74, align 8 +// CHECK-NEXT: %83 = getelementptr inbounds %main.mspan, ptr %82, i32 0, i32 4 +// CHECK-NEXT: %84 = icmp eq ptr %68, null +// CHECK-NEXT: br i1 %84, label %85, label %86 +// CHECK-EMPTY: +// CHECK-NEXT: 85: ; preds = %81 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 86: ; preds = %81 +// CHECK-NEXT: %87 = icmp eq ptr %69, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %87) +// CHECK-NEXT: %88 = icmp eq ptr %73, null +// CHECK-NEXT: br i1 %88, label %89, label %90 +// CHECK-EMPTY: +// CHECK-NEXT: 89: ; preds = %86 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 90: ; preds = %86 +// CHECK-NEXT: %91 = icmp eq ptr %74, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %91) +// CHECK-NEXT: %92 = icmp eq ptr %82, null +// CHECK-NEXT: br i1 %92, label %93, label %94 +// CHECK-EMPTY: +// CHECK-NEXT: 93: ; preds = %90 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 94: ; preds = %90 +// CHECK-NEXT: %95 = load i64, ptr %83, align 8 +// CHECK-NEXT: %96 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %97 = getelementptr inbounds %main.mspan, ptr %96, i32 0, i32 3 +// CHECK-NEXT: %98 = getelementptr inbounds %main.minfo, ptr %97, i32 0, i32 1 +// CHECK-NEXT: %99 = icmp eq ptr %96, null +// CHECK-NEXT: br i1 %99, label %100, label %101 +// CHECK-EMPTY: +// CHECK-NEXT: 100: ; preds = %94 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 101: ; preds = %94 +// CHECK-NEXT: %102 = icmp eq ptr %97, null +// CHECK-NEXT: br i1 %102, label %103, label %104 +// CHECK-EMPTY: +// CHECK-NEXT: 103: ; preds = %101 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 104: ; preds = %101 +// CHECK-NEXT: %105 = load i64, ptr %98, align 8 +// CHECK-NEXT: %106 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %107 = getelementptr inbounds %main.mspan, ptr %106, i32 0, i32 3 +// CHECK-NEXT: %108 = getelementptr inbounds %main.minfo, ptr %107, i32 0, i32 0 +// CHECK-NEXT: %109 = icmp eq ptr %106, null +// CHECK-NEXT: br i1 %109, label %110, label %111 +// CHECK-EMPTY: +// CHECK-NEXT: 110: ; preds = %104 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 111: ; preds = %104 +// CHECK-NEXT: %112 = icmp eq ptr %107, null +// CHECK-NEXT: br i1 %112, label %113, label %114 +// CHECK-EMPTY: +// CHECK-NEXT: 113: ; preds = %111 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 114: ; preds = %111 +// CHECK-NEXT: %115 = load ptr, ptr %108, align 8 +// CHECK-NEXT: %116 = getelementptr inbounds %main.mspan, ptr %115, i32 0, i32 4 +// CHECK-NEXT: %117 = icmp eq ptr %106, null +// CHECK-NEXT: br i1 %117, label %118, label %119 +// CHECK-EMPTY: +// CHECK-NEXT: 118: ; preds = %114 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 119: ; preds = %114 +// CHECK-NEXT: %120 = icmp eq ptr %107, null +// CHECK-NEXT: br i1 %120, label %121, label %122 +// CHECK-EMPTY: +// CHECK-NEXT: 121: ; preds = %119 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 122: ; preds = %119 +// CHECK-NEXT: %123 = icmp eq ptr %108, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %123) +// CHECK-NEXT: %124 = icmp eq ptr %115, null +// CHECK-NEXT: br i1 %124, label %125, label %126 +// CHECK-EMPTY: +// CHECK-NEXT: 125: ; preds = %122 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 126: ; preds = %122 +// CHECK-NEXT: %127 = load i64, ptr %116, align 8 +// CHECK-NEXT: %128 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %129 = getelementptr inbounds %main.mspan, ptr %128, i32 0, i32 5 +// CHECK-NEXT: %130 = icmp eq ptr %128, null +// CHECK-NEXT: br i1 %130, label %131, label %132 +// CHECK-EMPTY: +// CHECK-NEXT: 131: ; preds = %126 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 132: ; preds = %126 +// CHECK-NEXT: %133 = load { ptr, ptr }, ptr %129, align 8 +// CHECK-NEXT: %134 = extractvalue { ptr, ptr } %133, 1 +// CHECK-NEXT: %135 = extractvalue { ptr, ptr } %133, 0 +// CHECK-NEXT: %136 = call i64 %135(ptr %134, i64 -2) +// CHECK-NEXT: %137 = load ptr, ptr %0, align 8 +// CHECK-NEXT: %138 = getelementptr inbounds %main.mspan, ptr %137, i32 0, i32 3 +// CHECK-NEXT: %139 = getelementptr inbounds %main.minfo, ptr %138, i32 0, i32 0 +// CHECK-NEXT: %140 = icmp eq ptr %137, null +// CHECK-NEXT: br i1 %140, label %141, label %142 +// CHECK-EMPTY: +// CHECK-NEXT: 141: ; preds = %132 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 142: ; preds = %132 +// CHECK-NEXT: %143 = icmp eq ptr %138, null +// CHECK-NEXT: br i1 %143, label %144, label %145 +// CHECK-EMPTY: +// CHECK-NEXT: 144: ; preds = %142 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 145: ; preds = %142 +// CHECK-NEXT: %146 = load ptr, ptr %139, align 8 +// CHECK-NEXT: %147 = getelementptr inbounds %main.mspan, ptr %146, i32 0, i32 5 +// CHECK-NEXT: %148 = icmp eq ptr %137, null +// CHECK-NEXT: br i1 %148, label %149, label %150 +// CHECK-EMPTY: +// CHECK-NEXT: 149: ; preds = %145 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 150: ; preds = %145 +// CHECK-NEXT: %151 = icmp eq ptr %138, null +// CHECK-NEXT: br i1 %151, label %152, label %153 +// CHECK-EMPTY: +// CHECK-NEXT: 152: ; preds = %150 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 153: ; preds = %150 +// CHECK-NEXT: %154 = icmp eq ptr %139, null +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %154) +// CHECK-NEXT: %155 = icmp eq ptr %146, null +// CHECK-NEXT: br i1 %155, label %156, label %157 +// CHECK-EMPTY: +// CHECK-NEXT: 156: ; preds = %153 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 157: ; preds = %153 +// CHECK-NEXT: %158 = load { ptr, ptr }, ptr %147, align 8 +// CHECK-NEXT: %159 = extractvalue { ptr, ptr } %158, 1 +// CHECK-NEXT: %160 = extractvalue { ptr, ptr } %158, 0 +// CHECK-NEXT: %161 = call i64 %160(ptr %159, i64 -3) +// CHECK-NEXT: %162 = call i32 (ptr, ...) @printf(ptr @0, i64 %67, i64 %95, i64 %105, i64 %127, i64 %136, i64 %161) // CHECK-NEXT: ret void // CHECK-NEXT: } func main() { @@ -131,9 +361,20 @@ func main() { // CHECK-NEXT: %3 = extractvalue { ptr } %2, 0 // CHECK-NEXT: %4 = load ptr, ptr %3, align 8 // CHECK-NEXT: %5 = getelementptr inbounds %main.mspan, ptr %4, i32 0, i32 4 - // CHECK-NEXT: %6 = load i64, ptr %5, align 8 - // CHECK-NEXT: %7 = mul i64 %6, %1 - // CHECK-NEXT: ret i64 %7 + // CHECK-NEXT: %6 = extractvalue { ptr } %2, 0 + // CHECK-NEXT: %7 = icmp eq ptr %6, null + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %7) + // CHECK-NEXT: %8 = icmp eq ptr %4, null + // CHECK-NEXT: br i1 %8, label %9, label %10 + // CHECK-EMPTY: + // CHECK-NEXT: 9: ; preds = %_llgo_0 + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) + // CHECK-NEXT: unreachable + // CHECK-EMPTY: + // CHECK-NEXT: 10: ; preds = %_llgo_0 + // CHECK-NEXT: %11 = load i64, ptr %5, align 8 + // CHECK-NEXT: %12 = mul i64 %11, %1 + // CHECK-NEXT: ret i64 %12 // CHECK-NEXT: } c.Printf(c.Str("%d %d %d %d %d %d\n"), m.next.value, m.list.last.value, m.info.info, m.info.span.value, m.check(-2), m.info.span.check(-3)) diff --git a/cl/_testrt/slice2array/in.go b/cl/_testrt/slice2array/in.go index 690aa33ae3..35e5855f8f 100644 --- a/cl/_testrt/slice2array/in.go +++ b/cl/_testrt/slice2array/in.go @@ -27,56 +27,72 @@ package main // CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 // CHECK-NEXT: %11 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %7, 0 // CHECK-NEXT: %12 = load [4 x i8], ptr %0, align 1 -// CHECK-NEXT: %13 = load [4 x i8], ptr %11, align 1 -// CHECK-NEXT: %14 = extractvalue [4 x i8] %12, 0 -// CHECK-NEXT: %15 = extractvalue [4 x i8] %13, 0 -// CHECK-NEXT: %16 = icmp eq i8 %14, %15 -// CHECK-NEXT: %17 = and i1 true, %16 -// CHECK-NEXT: %18 = extractvalue [4 x i8] %12, 1 -// CHECK-NEXT: %19 = extractvalue [4 x i8] %13, 1 -// CHECK-NEXT: %20 = icmp eq i8 %18, %19 -// CHECK-NEXT: %21 = and i1 %17, %20 -// CHECK-NEXT: %22 = extractvalue [4 x i8] %12, 2 -// CHECK-NEXT: %23 = extractvalue [4 x i8] %13, 2 -// CHECK-NEXT: %24 = icmp eq i8 %22, %23 -// CHECK-NEXT: %25 = and i1 %21, %24 -// CHECK-NEXT: %26 = extractvalue [4 x i8] %12, 3 -// CHECK-NEXT: %27 = extractvalue [4 x i8] %13, 3 -// CHECK-NEXT: %28 = icmp eq i8 %26, %27 -// CHECK-NEXT: %29 = and i1 %25, %28 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 %29) +// CHECK-NEXT: %13 = icmp eq ptr %11, null +// CHECK-NEXT: br i1 %13, label %14, label %15 +// CHECK-EMPTY: +// CHECK-NEXT: 14: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 15: ; preds = %_llgo_2 +// CHECK-NEXT: %16 = load [4 x i8], ptr %11, align 1 +// CHECK-NEXT: %17 = extractvalue [4 x i8] %12, 0 +// CHECK-NEXT: %18 = extractvalue [4 x i8] %16, 0 +// CHECK-NEXT: %19 = icmp eq i8 %17, %18 +// CHECK-NEXT: %20 = and i1 true, %19 +// CHECK-NEXT: %21 = extractvalue [4 x i8] %12, 1 +// CHECK-NEXT: %22 = extractvalue [4 x i8] %16, 1 +// CHECK-NEXT: %23 = icmp eq i8 %21, %22 +// CHECK-NEXT: %24 = and i1 %20, %23 +// CHECK-NEXT: %25 = extractvalue [4 x i8] %12, 2 +// CHECK-NEXT: %26 = extractvalue [4 x i8] %16, 2 +// CHECK-NEXT: %27 = icmp eq i8 %25, %26 +// CHECK-NEXT: %28 = and i1 %24, %27 +// CHECK-NEXT: %29 = extractvalue [4 x i8] %12, 3 +// CHECK-NEXT: %30 = extractvalue [4 x i8] %16, 3 +// CHECK-NEXT: %31 = icmp eq i8 %29, %30 +// CHECK-NEXT: %32 = and i1 %28, %31 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 %32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %30 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %0, 0 -// CHECK-NEXT: %31 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %30, i64 4, 1 -// CHECK-NEXT: %32 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %31, i64 4, 2 -// CHECK-NEXT: %33 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %32, 1 -// CHECK-NEXT: %34 = icmp slt i64 %33, 2 -// CHECK-NEXT: br i1 %34, label %_llgo_3, label %_llgo_4 +// CHECK-NEXT: %33 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" undef, ptr %0, 0 +// CHECK-NEXT: %34 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %33, i64 4, 1 +// CHECK-NEXT: %35 = insertvalue %"{{.*}}/runtime/internal/runtime.Slice" %34, i64 4, 2 +// CHECK-NEXT: %36 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %35, 1 +// CHECK-NEXT: %37 = icmp slt i64 %36, 2 +// CHECK-NEXT: br i1 %37, label %_llgo_3, label %_llgo_4 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 -// CHECK-NEXT: %35 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %32, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicSliceConvert"(i64 2, i64 %35) +// CHECK-NEXT: _llgo_3: ; preds = %15 +// CHECK-NEXT: %38 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %35, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PanicSliceConvert"(i64 2, i64 %38) // CHECK-NEXT: br label %_llgo_4 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_4: ; preds = %_llgo_3, %_llgo_2 -// CHECK-NEXT: %36 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %32, 0 -// CHECK-NEXT: %37 = load [2 x i8], ptr %36, align 1 -// CHECK-NEXT: %38 = alloca [2 x i8], align 1 -// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %38, i8 0, i64 2, i1 false) -// CHECK-NEXT: %39 = getelementptr inbounds i8, ptr %38, i64 0 -// CHECK-NEXT: %40 = getelementptr inbounds i8, ptr %38, i64 1 -// CHECK-NEXT: store i8 1, ptr %39, align 1 -// CHECK-NEXT: store i8 2, ptr %40, align 1 -// CHECK-NEXT: %41 = load [2 x i8], ptr %38, align 1 -// CHECK-NEXT: %42 = extractvalue [2 x i8] %37, 0 -// CHECK-NEXT: %43 = extractvalue [2 x i8] %41, 0 -// CHECK-NEXT: %44 = icmp eq i8 %42, %43 -// CHECK-NEXT: %45 = and i1 true, %44 -// CHECK-NEXT: %46 = extractvalue [2 x i8] %37, 1 -// CHECK-NEXT: %47 = extractvalue [2 x i8] %41, 1 -// CHECK-NEXT: %48 = icmp eq i8 %46, %47 -// CHECK-NEXT: %49 = and i1 %45, %48 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 %49) +// CHECK-NEXT: _llgo_4: ; preds = %_llgo_3, %15 +// CHECK-NEXT: %39 = extractvalue %"{{.*}}/runtime/internal/runtime.Slice" %35, 0 +// CHECK-NEXT: %40 = icmp eq ptr %39, null +// CHECK-NEXT: br i1 %40, label %41, label %42 +// CHECK-EMPTY: +// CHECK-NEXT: 41: ; preds = %_llgo_4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 42: ; preds = %_llgo_4 +// CHECK-NEXT: %43 = load [2 x i8], ptr %39, align 1 +// CHECK-NEXT: %44 = alloca [2 x i8], align 1 +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr %44, i8 0, i64 2, i1 false) +// CHECK-NEXT: %45 = getelementptr inbounds i8, ptr %44, i64 0 +// CHECK-NEXT: %46 = getelementptr inbounds i8, ptr %44, i64 1 +// CHECK-NEXT: store i8 1, ptr %45, align 1 +// CHECK-NEXT: store i8 2, ptr %46, align 1 +// CHECK-NEXT: %47 = load [2 x i8], ptr %44, align 1 +// CHECK-NEXT: %48 = extractvalue [2 x i8] %43, 0 +// CHECK-NEXT: %49 = extractvalue [2 x i8] %47, 0 +// CHECK-NEXT: %50 = icmp eq i8 %48, %49 +// CHECK-NEXT: %51 = and i1 true, %50 +// CHECK-NEXT: %52 = extractvalue [2 x i8] %43, 1 +// CHECK-NEXT: %53 = extractvalue [2 x i8] %47, 1 +// CHECK-NEXT: %54 = icmp eq i8 %52, %53 +// CHECK-NEXT: %55 = and i1 %51, %54 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintBool"(i1 %55) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void // CHECK-NEXT: } diff --git a/cl/_testrt/tpabi/in.go b/cl/_testrt/tpabi/in.go index 287b027664..1c63e0451f 100644 --- a/cl/_testrt/tpabi/in.go +++ b/cl/_testrt/tpabi/in.go @@ -136,12 +136,28 @@ func main() { // CHECK-LABEL: define linkonce void @"main.(*T[string,int]).Demo"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds %"main.T[string,int]", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load %"{{.*}}/runtime/internal/runtime.String", ptr %1, align 8 -// CHECK-NEXT: %3 = getelementptr inbounds %"main.T[string,int]", ptr %0, i32 0, i32 1 -// CHECK-NEXT: %4 = load i64, ptr %3, align 8 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %2) +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %3, label %4 +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: %5 = load %"{{.*}}/runtime/internal/runtime.String", ptr %1, align 8 +// CHECK-NEXT: %6 = getelementptr inbounds %"main.T[string,int]", ptr %0, i32 0, i32 1 +// CHECK-NEXT: %7 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %7, label %8, label %9 +// CHECK-EMPTY: +// CHECK-NEXT: 8: ; preds = %4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 9: ; preds = %4 +// CHECK-NEXT: %10 = load i64, ptr %6, align 8 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" %5) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %4) +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %10) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void // CHECK-NEXT: } diff --git a/cl/_testrt/tpfunc/in.go b/cl/_testrt/tpfunc/in.go index 3612acfe9e..b6c1bb28fd 100644 --- a/cl/_testrt/tpfunc/in.go +++ b/cl/_testrt/tpfunc/in.go @@ -41,9 +41,15 @@ func main() { // CHECK-LABEL: define void @"main.main$1"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = icmp eq ptr %0, null - // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %1) - // CHECK-NEXT: %2 = load i64, ptr %0, align 8 - // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %2) + // CHECK-NEXT: br i1 %1, label %2, label %3 + // CHECK-EMPTY: + // CHECK-NEXT: 2: ; preds = %_llgo_0 + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) + // CHECK-NEXT: unreachable + // CHECK-EMPTY: + // CHECK-NEXT: 3: ; preds = %_llgo_0 + // CHECK-NEXT: %4 = load i64, ptr %0, align 8 + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %4) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void // CHECK-NEXT: } @@ -55,9 +61,15 @@ func main() { // CHECK-LABEL: define void @"main.main$2"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = icmp eq ptr %0, null - // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %1) - // CHECK-NEXT: %2 = load i64, ptr %0, align 8 - // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %2) + // CHECK-NEXT: br i1 %1, label %2, label %3 + // CHECK-EMPTY: + // CHECK-NEXT: 2: ; preds = %_llgo_0 + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) + // CHECK-NEXT: unreachable + // CHECK-EMPTY: + // CHECK-NEXT: 3: ; preds = %_llgo_0 + // CHECK-NEXT: %4 = load i64, ptr %0, align 8 + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %4) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void // CHECK-NEXT: } @@ -69,9 +81,15 @@ func main() { // CHECK-LABEL: define void @"main.main$3"(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = icmp eq ptr %0, null - // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 %1) - // CHECK-NEXT: %2 = load i64, ptr %0, align 8 - // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %2) + // CHECK-NEXT: br i1 %1, label %2, label %3 + // CHECK-EMPTY: + // CHECK-NEXT: 2: ; preds = %_llgo_0 + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) + // CHECK-NEXT: unreachable + // CHECK-EMPTY: + // CHECK-NEXT: 3: ; preds = %_llgo_0 + // CHECK-NEXT: %4 = load i64, ptr %0, align 8 + // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 %4) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) // CHECK-NEXT: ret void // CHECK-NEXT: } diff --git a/cl/_testrt/tpmethod/in.go b/cl/_testrt/tpmethod/in.go index 501cbaa649..7bfe892126 100644 --- a/cl/_testrt/tpmethod/in.go +++ b/cl/_testrt/tpmethod/in.go @@ -132,10 +132,18 @@ func main() { // CHECK-LABEL: define linkonce void @"main.(*future[main.Tuple[error]]).Then"(ptr %0, { ptr, ptr } %1){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %2 = getelementptr inbounds %"main.future[main.Tuple[error]]", ptr %0, i32 0, i32 0 -// CHECK-NEXT: %3 = load { ptr, ptr }, ptr %2, align 8 -// CHECK-NEXT: %4 = extractvalue { ptr, ptr } %3, 1 -// CHECK-NEXT: %5 = extractvalue { ptr, ptr } %3, 0 -// CHECK-NEXT: call void %5(ptr %4, { ptr, ptr } %1) +// CHECK-NEXT: %3 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %3, label %4, label %5 +// CHECK-EMPTY: +// CHECK-NEXT: 4: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: %6 = load { ptr, ptr }, ptr %2, align 8 +// CHECK-NEXT: %7 = extractvalue { ptr, ptr } %6, 1 +// CHECK-NEXT: %8 = extractvalue { ptr, ptr } %6, 0 +// CHECK-NEXT: call void %8(ptr %7, { ptr, ptr } %1) // CHECK-NEXT: ret void // CHECK-NEXT: } diff --git a/cl/_testrt/tpunsafe/in.go b/cl/_testrt/tpunsafe/in.go index a19bd33d6e..93b70a5520 100644 --- a/cl/_testrt/tpunsafe/in.go +++ b/cl/_testrt/tpunsafe/in.go @@ -34,11 +34,10 @@ func main() { // CHECK-LABEL: define linkonce void @"main.(*M[bool]).check"(ptr %0, i64 %1, i64 %2, i64 %3){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %4 = getelementptr inbounds %"main.M[bool]", ptr %0, i32 0, i32 2 -// CHECK-NEXT: %5 = load %"main.N[bool]", ptr %4, align 1 -// CHECK-NEXT: %6 = icmp ne i64 1, %1 -// CHECK-NEXT: br i1 %6, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %5 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %5, label %17, label %18 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: _llgo_1: ; preds = %18 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 4 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 1) @@ -47,19 +46,18 @@ func main() { // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %1) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 20 }, 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: %6 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 20 }, 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: %9 = getelementptr inbounds %"main.M[bool]", ptr %0, i32 0, i32 2 -// CHECK-NEXT: %10 = load %"main.N[bool]", ptr %9, align 1 -// CHECK-NEXT: %11 = icmp ne i64 8, %2 -// CHECK-NEXT: br i1 %11, label %_llgo_3, label %_llgo_4 +// CHECK-NEXT: _llgo_2: ; preds = %18 +// CHECK-NEXT: %8 = getelementptr inbounds %"main.M[bool]", ptr %0, i32 0, i32 2 +// CHECK-NEXT: %9 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %9, label %21, label %22 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 +// CHECK-NEXT: _llgo_3: ; preds = %22 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 4 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 8) @@ -68,20 +66,19 @@ func main() { // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %2) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %12 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @4, i64 21 }, ptr %12, align 8 -// CHECK-NEXT: %13 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %12, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %13) +// CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @4, i64 21 }, ptr %10, align 8 +// CHECK-NEXT: %11 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %10, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %11) // CHECK-NEXT: unreachable // CHECK-EMPTY: -// CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 -// CHECK-NEXT: %14 = getelementptr inbounds %"main.M[bool]", ptr %0, i32 0, i32 2 -// CHECK-NEXT: %15 = getelementptr inbounds %"main.N[bool]", ptr %14, i32 0, i32 1 -// CHECK-NEXT: %16 = load i1, ptr %15, align 1 -// CHECK-NEXT: %17 = icmp ne i64 1, %3 -// CHECK-NEXT: br i1 %17, label %_llgo_5, label %_llgo_6 +// CHECK-NEXT: _llgo_4: ; preds = %22 +// CHECK-NEXT: %12 = getelementptr inbounds %"main.M[bool]", ptr %0, i32 0, i32 2 +// CHECK-NEXT: %13 = getelementptr inbounds %"main.N[bool]", ptr %12, i32 0, i32 1 +// CHECK-NEXT: %14 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %14, label %25, label %26 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_5: ; preds = %_llgo_4 +// CHECK-NEXT: _llgo_5: ; preds = %29 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 4 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 1) @@ -90,14 +87,49 @@ func main() { // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %3) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %18 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @4, i64 21 }, 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: %15 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @4, i64 21 }, ptr %15, align 8 +// CHECK-NEXT: %16 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %15, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %16) // CHECK-NEXT: unreachable // CHECK-EMPTY: -// CHECK-NEXT: _llgo_6: ; preds = %_llgo_4 +// CHECK-NEXT: _llgo_6: ; preds = %29 // CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: 17: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 18: ; preds = %_llgo_0 +// CHECK-NEXT: %19 = load %"main.N[bool]", ptr %4, align 1 +// CHECK-NEXT: %20 = icmp ne i64 1, %1 +// CHECK-NEXT: br i1 %20, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: 21: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 22: ; preds = %_llgo_2 +// CHECK-NEXT: %23 = load %"main.N[bool]", ptr %8, align 1 +// CHECK-NEXT: %24 = icmp ne i64 8, %2 +// CHECK-NEXT: br i1 %24, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: 25: ; preds = %_llgo_4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 26: ; preds = %_llgo_4 +// CHECK-NEXT: %27 = icmp eq ptr %12, null +// CHECK-NEXT: br i1 %27, label %28, label %29 +// CHECK-EMPTY: +// CHECK-NEXT: 28: ; preds = %26 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 29: ; preds = %26 +// CHECK-NEXT: %30 = load i1, ptr %13, align 1 +// CHECK-NEXT: %31 = icmp ne i64 1, %3 +// CHECK-NEXT: br i1 %31, label %_llgo_5, label %_llgo_6 // CHECK-NEXT: } func (m *M[T]) check(align, offset1, offset2 uintptr) { if v := unsafe.Alignof(m.m2); v != align { @@ -117,11 +149,10 @@ func (m *M[T]) check(align, offset1, offset2 uintptr) { // CHECK-LABEL: define linkonce void @"main.(*M[int64]).check"(ptr %0, i64 %1, i64 %2, i64 %3){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %4 = getelementptr inbounds %"main.M[int64]", ptr %0, i32 0, i32 2 -// CHECK-NEXT: %5 = load %"main.N[int64]", ptr %4, align 8 -// CHECK-NEXT: %6 = icmp ne i64 8, %1 -// CHECK-NEXT: br i1 %6, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %5 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %5, label %17, label %18 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: _llgo_1: ; preds = %18 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 4 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 8) @@ -130,19 +161,18 @@ func (m *M[T]) check(align, offset1, offset2 uintptr) { // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %1) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %7 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 20 }, 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: %6 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @2, i64 20 }, 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: %9 = getelementptr inbounds %"main.M[int64]", ptr %0, i32 0, i32 2 -// CHECK-NEXT: %10 = load %"main.N[int64]", ptr %9, align 8 -// CHECK-NEXT: %11 = icmp ne i64 16, %2 -// CHECK-NEXT: br i1 %11, label %_llgo_3, label %_llgo_4 +// CHECK-NEXT: _llgo_2: ; preds = %18 +// CHECK-NEXT: %8 = getelementptr inbounds %"main.M[int64]", ptr %0, i32 0, i32 2 +// CHECK-NEXT: %9 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %9, label %21, label %22 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_3: ; preds = %_llgo_2 +// CHECK-NEXT: _llgo_3: ; preds = %22 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 4 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 16) @@ -151,20 +181,19 @@ func (m *M[T]) check(align, offset1, offset2 uintptr) { // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %2) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %12 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @4, i64 21 }, ptr %12, align 8 -// CHECK-NEXT: %13 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %12, 1 -// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %13) +// CHECK-NEXT: %10 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @4, i64 21 }, ptr %10, align 8 +// CHECK-NEXT: %11 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %10, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %11) // CHECK-NEXT: unreachable // CHECK-EMPTY: -// CHECK-NEXT: _llgo_4: ; preds = %_llgo_2 -// CHECK-NEXT: %14 = getelementptr inbounds %"main.M[int64]", ptr %0, i32 0, i32 2 -// CHECK-NEXT: %15 = getelementptr inbounds %"main.N[int64]", ptr %14, i32 0, i32 1 -// CHECK-NEXT: %16 = load i64, ptr %15, align 8 -// CHECK-NEXT: %17 = icmp ne i64 8, %3 -// CHECK-NEXT: br i1 %17, label %_llgo_5, label %_llgo_6 +// CHECK-NEXT: _llgo_4: ; preds = %22 +// CHECK-NEXT: %12 = getelementptr inbounds %"main.M[int64]", ptr %0, i32 0, i32 2 +// CHECK-NEXT: %13 = getelementptr inbounds %"main.N[int64]", ptr %12, i32 0, i32 1 +// CHECK-NEXT: %14 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %14, label %25, label %26 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_5: ; preds = %_llgo_4 +// CHECK-NEXT: _llgo_5: ; preds = %29 // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintString"(%"{{.*}}/runtime/internal/runtime.String" { ptr @0, i64 4 }) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintInt"(i64 8) @@ -173,12 +202,47 @@ func (m *M[T]) check(align, offset1, offset2 uintptr) { // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 32) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintUint"(i64 %3) // CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.PrintByte"(i8 10) -// CHECK-NEXT: %18 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) -// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @4, i64 21 }, 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: %15 = call ptr @"{{.*}}/runtime/internal/runtime.AllocU"(i64 16) +// CHECK-NEXT: store %"{{.*}}/runtime/internal/runtime.String" { ptr @4, i64 21 }, ptr %15, align 8 +// CHECK-NEXT: %16 = insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr @_llgo_string, ptr undef }, ptr %15, 1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.Panic"(%"{{.*}}/runtime/internal/runtime.eface" %16) // CHECK-NEXT: unreachable // CHECK-EMPTY: -// CHECK-NEXT: _llgo_6: ; preds = %_llgo_4 +// CHECK-NEXT: _llgo_6: ; preds = %29 // CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: 17: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 18: ; preds = %_llgo_0 +// CHECK-NEXT: %19 = load %"main.N[int64]", ptr %4, align 8 +// CHECK-NEXT: %20 = icmp ne i64 8, %1 +// CHECK-NEXT: br i1 %20, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: 21: ; preds = %_llgo_2 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 22: ; preds = %_llgo_2 +// CHECK-NEXT: %23 = load %"main.N[int64]", ptr %8, align 8 +// CHECK-NEXT: %24 = icmp ne i64 16, %2 +// CHECK-NEXT: br i1 %24, label %_llgo_3, label %_llgo_4 +// CHECK-EMPTY: +// CHECK-NEXT: 25: ; preds = %_llgo_4 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 26: ; preds = %_llgo_4 +// CHECK-NEXT: %27 = icmp eq ptr %12, null +// CHECK-NEXT: br i1 %27, label %28, label %29 +// CHECK-EMPTY: +// CHECK-NEXT: 28: ; preds = %26 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 29: ; preds = %26 +// CHECK-NEXT: %30 = load i64, ptr %13, align 8 +// CHECK-NEXT: %31 = icmp ne i64 8, %3 +// CHECK-NEXT: br i1 %31, label %_llgo_5, label %_llgo_6 // CHECK-NEXT: } diff --git a/cl/_testrt/typalias/in.go b/cl/_testrt/typalias/in.go index f35416ed36..d13436c77a 100644 --- a/cl/_testrt/typalias/in.go +++ b/cl/_testrt/typalias/in.go @@ -17,17 +17,33 @@ var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0} // CHECK-LABEL: define void @main.Print(ptr %0){{.*}} { // CHECK-NEXT: _llgo_0: // CHECK-NEXT: %1 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 1 -// CHECK-NEXT: %2 = load i1, ptr %1, align 1 -// CHECK-NEXT: br i1 %2, label %_llgo_1, label %_llgo_2 +// CHECK-NEXT: %2 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %2, label %5, label %6 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_1: ; preds = %_llgo_0 +// CHECK-NEXT: _llgo_1: ; preds = %6 // CHECK-NEXT: %3 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %4 = load i32, ptr %3, align 4 -// CHECK-NEXT: call void (ptr, ...) @printf(ptr @main.format, i32 %4) -// CHECK-NEXT: br label %_llgo_2 +// CHECK-NEXT: %4 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %4, label %8, label %9 // CHECK-EMPTY: -// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0 +// CHECK-NEXT: _llgo_2: ; preds = %9, %6 // CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: 5: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 6: ; preds = %_llgo_0 +// CHECK-NEXT: %7 = load i1, ptr %1, align 1 +// CHECK-NEXT: br i1 %7, label %_llgo_1, label %_llgo_2 +// CHECK-EMPTY: +// CHECK-NEXT: 8: ; preds = %_llgo_1 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 9: ; preds = %_llgo_1 +// CHECK-NEXT: %10 = load i32, ptr %3, align 4 +// CHECK-NEXT: call void (ptr, ...) @printf(ptr @main.format, i32 %10) +// CHECK-NEXT: br label %_llgo_2 // CHECK-NEXT: } func Print(p *Foo) { diff --git a/cl/_testrt/vamethod/in.go b/cl/_testrt/vamethod/in.go index a7ef707b26..8af8b3fe22 100644 --- a/cl/_testrt/vamethod/in.go +++ b/cl/_testrt/vamethod/in.go @@ -20,10 +20,18 @@ import ( // CHECK-LABEL: define i32 @"main.(*CFmt).Printf"(ptr %0, ...){{.*}} { // CHECK-NEXT: _llgo_0: -// CHECK-NEXT: %1 = getelementptr inbounds %main.CFmt, ptr %0, i32 0, i32 0 -// CHECK-NEXT: %2 = load ptr, ptr %1, align 8 -// CHECK-NEXT: %3 = call i32 (ptr, ...) @printf(ptr %2) -// CHECK-NEXT: ret i32 %3 +// CHECK-NEXT: %1 = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %1, label %2, label %3 +// CHECK-EMPTY: +// CHECK-NEXT: 2: ; preds = %_llgo_0 +// CHECK-NEXT: call void @"{{.*}}/runtime/internal/runtime.AssertNilDeref"(i1 true) +// CHECK-NEXT: unreachable +// CHECK-EMPTY: +// CHECK-NEXT: 3: ; preds = %_llgo_0 +// CHECK-NEXT: %4 = getelementptr inbounds %main.CFmt, ptr %0, i32 0, i32 0 +// CHECK-NEXT: %5 = load ptr, ptr %4, align 8 +// CHECK-NEXT: %6 = call i32 (ptr, ...) @printf(ptr %5) +// CHECK-NEXT: ret i32 %6 // CHECK-NEXT: } // CHECK-LABEL: define void @"main.(*CFmt).SetFormat"(ptr %0, ptr %1){{.*}} { diff --git a/cl/builtin_test.go b/cl/builtin_test.go index 3fa2161aac..191d0a9c04 100644 --- a/cl/builtin_test.go +++ b/cl/builtin_test.go @@ -176,6 +176,263 @@ func TestCompilePromotedValueMethodNilDerefGuard(t *testing.T) { } } +func TestCollectPromotedPointerReceiverBaseChecks(t *testing.T) { + ssapkg := buildSSAPackage(t, ` +package foo + +type embedded struct{} + +func (*embedded) pointer() int { return 1 } + +type outer struct { + padding int + embedded +} + +func promoted(o *outer) int { return o.pointer() } +func explicit(o *outer) int { return o.embedded.pointer() } +func bound(o *outer) func() int { return o.pointer } +func direct(e *embedded) int { return e.pointer() } +`) + for _, name := range []string{"promoted", "explicit", "bound"} { + checks := collectMethodReceiverBases(ssapkg.Func(name)) + if len(checks) != 1 { + t.Fatalf("%s promoted receiver base checks = %v, want one", name, checks) + } + } + if checks := collectMethodReceiverBases(ssapkg.Func("direct")); len(checks) != 0 { + t.Fatalf("direct nil-capable pointer receiver checks = %v, want none", checks) + } +} + +func TestCompileDominatingNilCheckAvoidsRedundantGuard(t *testing.T) { + const sourcePrefix = ` +package foo + +type value struct { n int } +` + tests := []struct { + name string + body string + }{ + {"equal", ` + if p == nil { + return 0 + } + return p.n +`}, + {"equal reversed", ` + if nil == p { + return 0 + } + return p.n +`}, + {"not equal", ` + if p != nil { + return p.n + } + return 0 +`}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, checked := mustCompileLLPkgFromSrc(t, sourcePrefix+` +func read(p *value) int {`+tt.body+`} +`) + checkedRead := llvmFunction(t, checked.String(), "foo.read") + if got := strings.Count(checkedRead, "AssertNilDeref"); got != 0 { + t.Fatalf("nil-checked field load guards = %d, want 0:\n%s", got, checkedRead) + } + }) + } + + _, unchecked := mustCompileLLPkgFromSrc(t, sourcePrefix+` +func read(p *value) int { return p.n } +`) + uncheckedRead := llvmFunction(t, unchecked.String(), "foo.read") + if got := strings.Count(uncheckedRead, "AssertNilDeref"); got != 1 { + t.Fatalf("unchecked field load guards = %d, want 1:\n%s", got, uncheckedRead) + } +} + +func TestCompileLocalPointerStoresAvoidRedundantGuards(t *testing.T) { + _, m := mustCompileLLPkgFromSrc(t, ` +package foo + +type node struct { + next *node + value int +} + +var root *node + +func straightLine() int { + root = &node{} + root.next = &node{value: 1} + return root.next.value +} + +func resetRoot() { root = nil } + +func afterCall() int { + root = &node{} + resetRoot() + return root.value +} + +func afterPossibleAlias(slot **node) int { + root = &node{} + *slot = nil + return root.value +} + +func afterNilStore() int { + root = &node{} + root = nil + return root.value +} + +func afterGlobalCheck() int { + if root == nil { + return 0 + } + return root.value +} + +func afterCheckedAlias(slot **node) int { + if root == nil { + return 0 + } + *slot = nil + return root.value +} +`) + + for _, name := range []string{"straightLine", "afterGlobalCheck"} { + fn := llvmFunction(t, m.String(), "foo."+name) + if got := strings.Count(fn, "AssertNilDeref"); got != 0 { + t.Fatalf("%s emitted %d redundant nil guards, want 0:\n%s", name, got, fn) + } + } + for _, name := range []string{"afterCall", "afterPossibleAlias", "afterNilStore", "afterCheckedAlias"} { + fn := llvmFunction(t, m.String(), "foo."+name) + if got := strings.Count(fn, "AssertNilDeref"); got != 1 { + t.Fatalf("%s emitted %d nil guards after a memory barrier, want 1:\n%s", name, got, fn) + } + } +} + +func TestLocalNonNilAnalysisHelpersFailClosed(t *testing.T) { + ssapkg := buildSSAPackage(t, ` +package foo + +type node struct{} + +var first, second *node + +func allocations() (*node, *node) { + return new(node), new(node) +} +`) + fn := ssapkg.Func("allocations") + var allocs []*ssa.Alloc + for _, block := range fn.Blocks { + for _, instr := range block.Instrs { + if alloc, ok := instr.(*ssa.Alloc); ok { + allocs = append(allocs, alloc) + } + } + } + if len(allocs) != 2 { + t.Fatalf("allocations contains %d allocs, want 2", len(allocs)) + } + first := ssapkg.Members["first"].(*ssa.Global) + second := ssapkg.Members["second"].(*ssa.Global) + field0 := &ssa.FieldAddr{X: allocs[0], Field: 0} + field1 := &ssa.FieldAddr{X: allocs[0], Field: 1} + index0 := &ssa.IndexAddr{X: allocs[0], Index: ssa.NewConst(constant.MakeInt64(0), types.Typ[types.Int])} + + if !isLocallyKnownNonNil(allocs[0], make(map[ssa.Value]bool)) { + t.Fatal("allocation should be known non-nil") + } + if isLocallyKnownNonNil(nil, make(map[ssa.Value]bool)) || + isLocallyKnownNonNil(allocs[0], map[ssa.Value]bool{allocs[0]: true}) { + t.Fatal("nil or already visited value should fail closed") + } + if !isLocallyDerivedNonNil(field0) || !isLocallyDerivedNonNil(index0) || isLocallyDerivedNonNil(allocs[0]) { + t.Fatal("derived-address non-nil classification is incorrect") + } + + change0 := &ssa.ChangeType{X: allocs[0]} + change1 := &ssa.ChangeType{X: allocs[0]} + convert0 := &ssa.Convert{X: allocs[0]} + convert1 := &ssa.Convert{X: allocs[0]} + if !equivalentPointerValues(change0, change1, make(map[ssaValuePair]bool)) || + !equivalentPointerValues(convert0, convert1, make(map[ssaValuePair]bool)) { + t.Fatal("equivalent conversions should preserve pointer identity") + } + if equivalentPointerValues(allocs[0], nil, make(map[ssaValuePair]bool)) || + !equivalentPointerValues(allocs[0], allocs[1], map[ssaValuePair]bool{{allocs[0], allocs[1]}: true}) { + t.Fatal("pointer equivalence did not handle nil or a visited pair") + } + if !equivalentMemoryAddresses(&ssa.ChangeType{X: field0}, &ssa.ChangeType{X: field0}, make(map[ssaValuePair]bool)) || + !equivalentMemoryAddresses(&ssa.Convert{X: field0}, &ssa.Convert{X: field0}, make(map[ssaValuePair]bool)) || + equivalentMemoryAddresses(field0, field1, make(map[ssaValuePair]bool)) { + t.Fatal("memory-address equivalence is incorrect") + } + zero := ssa.NewConst(constant.MakeInt64(0), types.Typ[types.Int]) + otherZero := ssa.NewConst(constant.MakeInt64(0), types.Typ[types.Int]) + one := ssa.NewConst(constant.MakeInt64(1), types.Typ[types.Int]) + if !equivalentSSAIndices(zero, otherZero) || equivalentSSAIndices(zero, one) { + t.Fatal("constant index equivalence is incorrect") + } + + if !mayAliasMemoryAddresses(first, first) || mayAliasMemoryAddresses(first, second) || + mayAliasMemoryAddresses(first, field0) || !mayAliasMemoryAddresses(first, allocs[0]) { + t.Fatal("global/local alias classification is incorrect") + } + if root, ok := localPointerRoot(field0, make(map[ssa.Value]bool)); !ok || root != allocs[0] { + t.Fatalf("field root = (%v, %v), want first allocation", root, ok) + } + if root, ok := localPointerRoot(index0, make(map[ssa.Value]bool)); !ok || root != allocs[0] { + t.Fatalf("index root = (%v, %v), want first allocation", root, ok) + } + if _, ok := localPointerRoot(nil, make(map[ssa.Value]bool)); ok { + t.Fatal("nil pointer root should fail closed") + } + if !definitelyDistinctPointerRoots(allocs[0], allocs[1]) || + definitelyDistinctPointerRoots(allocs[0], allocs[0]) || + definitelyDistinctPointerRoots(&ssa.Parameter{}, allocs[0]) { + t.Fatal("distinct pointer-root classification is incorrect") + } + if !isSafeDerivedAddress(field0) || !isSafeDerivedAddress(index0) || isSafeDerivedAddress(allocs[0]) { + t.Fatal("safe derived-address classification is incorrect") + } + + for _, instr := range []ssa.Instruction{ + &ssa.Call{}, &ssa.Go{}, &ssa.Defer{}, &ssa.Send{}, &ssa.MapUpdate{}, &ssa.RunDefers{}, + &ssa.UnOp{Op: token.ARROW}, + } { + if !mayChangePointerMemory(instr) { + t.Fatalf("%T should stop a local memory proof", instr) + } + } + if mayChangePointerMemory(&ssa.Return{}) || mayChangePointerMemory(&ssa.UnOp{Op: token.MUL}) { + t.Fatal("pure instructions should not stop a local memory proof") + } + ret := &ssa.Return{} + block := &ssa.BasicBlock{Instrs: []ssa.Instruction{ret}} + if instructionIndex(block, ret) != 0 || instructionIndex(block, &ssa.Return{}) != -1 { + t.Fatal("instructionIndex returned an incorrect position") + } + if _, ok := localStoredValue(allocs[0], ret); ok || memoryUnchangedBetween(ret, ret, allocs[0]) { + t.Fatal("instructions without a block should fail closed") + } + if isKnownNonNilAt(&ssa.Parameter{}, ret) { + t.Fatal("unknown value at an instruction without a block should fail closed") + } +} + func TestCompileValueReceiverNilDerefKeepsDominance(t *testing.T) { _, m := mustCompileLLPkgFromSrc(t, ` package foo @@ -307,6 +564,9 @@ func TestCollectMethodNilDerefChecksSkipsDynamicDeferGo(t *testing.T) { if got := collectMethodNilDerefChecks(fn); len(got) != 0 { t.Fatalf("collectMethodNilDerefChecks() = %v, want no static checks", got) } + if got := collectMethodReceiverBases(fn); len(got) != 0 { + t.Fatalf("collectMethodReceiverBases() = %v, want no static checks", got) + } } func TestToBackground(t *testing.T) { diff --git a/cl/compile.go b/cl/compile.go index 9032deb02b..ed2ad78ef0 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -199,6 +199,7 @@ type context struct { loaded map[*types.Package]*pkgInfo // loaded packages bvals map[ssa.Value]llssa.Expr // block values methodNilDerefChecks map[*ssa.UnOp]none + methodReceiverBases map[ssa.Value]none vargs map[*ssa.Alloc][]llssa.Expr // varargs funcs map[*ssa.Function]llssa.Function linkOnceFns map[*ssa.Function]none @@ -641,7 +642,9 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun dbgEnabled := p.frontendOptions().Debug dbgSymsEnabled := p.frontendOptions().DebugSymbols && (f == nil || f.Origin() == nil) p.inits = append(p.inits, func() { - oldFn, oldGoFn, oldMethodNilDerefChecks, oldCallerFrameMark := p.fn, p.goFn, p.methodNilDerefChecks, p.callerFrameMark + oldFn, oldGoFn := p.fn, p.goFn + oldMethodNilDerefChecks, oldMethodReceiverBases := p.methodNilDerefChecks, p.methodReceiverBases + oldCallerFrameMark := p.callerFrameMark oldLocalityFunction := p.locality.function p.fn = fn p.goFn = f @@ -649,7 +652,9 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun p.locality.function = localityFunction{} p.state = state // restore pkgState when compiling funcBody defer func() { - p.fn, p.goFn, p.methodNilDerefChecks, p.callerFrameMark = oldFn, oldGoFn, oldMethodNilDerefChecks, oldCallerFrameMark + p.fn, p.goFn = oldFn, oldGoFn + p.methodNilDerefChecks, p.methodReceiverBases = oldMethodNilDerefChecks, oldMethodReceiverBases + p.callerFrameMark = oldCallerFrameMark p.locality.function = oldLocalityFunction }() p.phis = nil @@ -671,6 +676,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun p.prepareExportedLocalContext(f) p.bvals = make(map[ssa.Value]llssa.Expr) p.methodNilDerefChecks = collectMethodNilDerefChecks(f) + p.methodReceiverBases = collectMethodReceiverBases(f) off := make([]int, len(f.Blocks)) if isCgo { p.cgoArgs = make([]llssa.Expr, len(f.Params)) @@ -1032,14 +1038,30 @@ func skipUnusedArrayDeref(v *ssa.UnOp) bool { } func shouldAssertDirectNilDeref(v *ssa.UnOp) bool { - if v.Op != token.MUL { + if v.Op != token.MUL || isKnownNonNilAddr(v.X) || isWrapNilCheckCall(v.X) { return false } - if _, ok := v.X.(*ssa.Parameter); !ok { + if isInterfaceCompareDeref(v) { return false } - switch types.Unalias(v.Type()).Underlying().(type) { - case *types.Basic, *types.Pointer, *types.Chan, *types.Map, *types.Slice, *types.Interface: + if _, ok := v.X.(*ssa.Parameter); ok { + switch types.Unalias(v.Type()).Underlying().(type) { + case *types.Basic, *types.Pointer, *types.Chan, *types.Map, *types.Slice, *types.Interface: + return true + } + } + switch typ := types.Unalias(v.Type()).Underlying().(type) { + case *types.Basic: + return typ.Kind() == types.String || typ.Kind() == types.Complex64 || typ.Kind() == types.Complex128 + case *types.Array, *types.Struct, *types.Slice, *types.Interface, *types.Signature: + return true + } + return false +} + +func isDerivedDerefAddress(v ssa.Value) bool { + switch v.(type) { + case *ssa.FieldAddr, *ssa.IndexAddr: return true } return false @@ -1271,38 +1293,37 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue y := p.compileValueAs(b, v.Y, v.X.Type()) ret = b.BinOp(v.Op, x, y) case *ssa.UnOp: + effectfulArrayDeref := false if v.Op == token.MUL { if _, ok := p.methodNilDerefChecks[v]; ok { return p.compileCheckedDeref(b, v) } - if isEffectfulArrayPointerDeref(v) { + effectfulArrayDeref = isEffectfulArrayPointerDeref(v) + if effectfulArrayDeref { x := p.compileValue(b, v.X) p.recordPanicLocation(b, v.Pos()) + p.emitNilDerefBaseCheck(b, v.X) b.AssertNilDeref(x) } if refs, ok := nonDebugReferrers(v); ok && len(refs) == 0 { - if t := p.type_(v.Type(), llssa.InGo); t.RawType() != nil { - if p.isLargeNonPointerValue(t) { - x := p.compileValue(b, v.X) - p.recordPanicLocation(b, v.Pos()) - p.assertNilDerefBase(b, v.X) - b.AssertNilDeref(x) - return - } - } if skipUnusedArrayDeref(v) { p.compileValue(b, v.X) return } - if _, ok := types.Unalias(v.Type()).Underlying().(*types.Slice); ok { - // Zero-length slice-to-array conversions can leave only - // an unused slice deref; preserve its required nil check. - x := p.compileValue(b, v.X) - p.recordPanicLocation(b, v.Pos()) - p.assertNilDerefBase(b, v.X) - b.AssertNilDeref(x) + if effectfulArrayDeref { + return + } + if isKnownNonNilAddr(v.X) || isWrapNilCheckCall(v.X) { + p.compileValue(b, v.X) return } + // LLVM may eliminate an unused load, but evaluating a Go + // dereference must still panic when its pointer is nil. + x := p.compileValue(b, v.X) + p.recordPanicLocation(b, v.Pos()) + p.assertNilDerefBase(b, v.X) + b.AssertNilDeref(x) + return } if refs, ok := nonDebugReferrers(v); ok && len(refs) == 1 { if _, ok := refs[0].(*ssa.MakeInterface); ok { @@ -1332,8 +1353,11 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue if v.Op != token.ARROW { p.recordPanicLocation(b, v.Pos()) } - if shouldAssertDirectNilDeref(v) { - b.AssertNilDeref(x) + if !effectfulArrayDeref && v.Op == token.MUL { + p.emitNilDerefBaseCheck(b, v.X) + if shouldAssertDirectNilDeref(v) && !isDerivedDerefAddress(v.X) { + b.AssertNilDerefBranch(x) + } } if v.Op == token.ARROW { ret = b.Recv(x, v.CommaOk) @@ -1368,6 +1392,9 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue case *ssa.FieldAddr: x := p.compileValue(b, v.X) p.recordPanicLocation(b, v.Pos()) + if _, ok := p.methodReceiverBases[v]; ok && !isKnownNonNilAt(v.X, v) { + b.AssertNilDerefBranch(x) + } if p.isAddressOfFieldAddr(v) { b.AssertNilDeref(x) } @@ -1391,6 +1418,9 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue x := p.compileValue(b, vx) idx := p.compileValue(b, v.Index) p.recordPanicLocation(b, v.Pos()) + if _, ok := p.methodReceiverBases[v]; ok && !isKnownNonNilAt(v.X, v) { + b.AssertNilDerefBranch(x) + } ret = b.IndexAddr(x, idx) case *ssa.Index: x := p.compileValue(b, v.X) @@ -1653,6 +1683,8 @@ func (p *context) assertNilDerefBase(b llssa.Builder, addr ssa.Value) { base = b.NilDerefCheck(base) } p.bvals[addr] = b.FieldAddr(base, addr.Field) + case *ssa.IndexAddr: + p.emitNilDerefBaseCheck(b, addr) } } diff --git a/cl/instr.go b/cl/instr.go index 7e091eee82..82cdac447f 100644 --- a/cl/instr.go +++ b/cl/instr.go @@ -813,6 +813,11 @@ func collectFieldSelectorChain(ret map[token.Pos]none, expr ast.Expr) { case *ast.SelectorExpr: ret[e.Sel.Pos()] = none{} expr = e.X + case *ast.IndexExpr: + // Keep walking the addressable base. In &p.array[i], SSA checks + // the derived array pointer, which may already be non-nil because + // of the field offset even when p itself is nil. + expr = e.X default: return } @@ -1830,6 +1835,372 @@ func isKnownNonNilAddr(v ssa.Value) bool { return false } +// isKnownNonNilAt proves only two deliberately small classes of facts: +// straight-line loads whose latest local store is non-nil, and reloads of a +// value tested against nil on a side-effect-free dominator path. Unknown +// aliases, calls, joins, and loops all stop the proof. +func isKnownNonNilAt(v ssa.Value, instr ssa.Instruction) bool { + if isKnownNonNilAddr(v) || isLocallyStoredNonNil(v) || isLocallyDerivedNonNil(v) { + return true + } + target := instr.Block() + if target == nil { + return false + } + for block := target.Idom(); block != nil; block = block.Idom() { + if len(block.Instrs) == 0 || len(block.Succs) != 2 { + continue + } + branch, ok := block.Instrs[len(block.Instrs)-1].(*ssa.If) + if !ok { + continue + } + cmp, ok := branch.Cond.(*ssa.BinOp) + if !ok || (cmp.Op != token.EQL && cmp.Op != token.NEQ) { + continue + } + compared := cmp.X + if isNilConst(cmp.X) { + compared = cmp.Y + } else if !isNilConst(cmp.Y) { + continue + } + if !equivalentPointerValues(compared, v, make(map[ssaValuePair]bool)) { + continue + } + nonNilSucc := block.Succs[0] + if cmp.Op == token.EQL { + nonNilSucc = block.Succs[1] + } + if nonNilSucc.Dominates(target) { + return true + } + } + return false +} + +func isLocallyDerivedNonNil(v ssa.Value) bool { + switch v := v.(type) { + case *ssa.FieldAddr: + return isKnownNonNilAddr(v.X) || isLocallyStoredNonNil(v.X) || isLocallyDerivedNonNil(v.X) + case *ssa.IndexAddr: + return isKnownNonNilAddr(v.X) || isLocallyStoredNonNil(v.X) || isLocallyDerivedNonNil(v.X) + } + return false +} + +type ssaValuePair struct { + x ssa.Value + y ssa.Value +} + +// isLocallyStoredNonNil recognizes straight-line pointer initialization such +// as p.next = new(node); use(p.next). It deliberately stays within one SSA +// block and gives up at calls or stores that may alias the loaded slot. +func isLocallyStoredNonNil(v ssa.Value) bool { + load, ok := v.(*ssa.UnOp) + if !ok || load.Op != token.MUL || !isPointerGoType(load.Type()) { + return false + } + stored, ok := localStoredValue(load.X, load) + return ok && isLocallyKnownNonNil(stored, make(map[ssa.Value]bool)) +} + +func isLocallyKnownNonNil(v ssa.Value, seen map[ssa.Value]bool) bool { + if v == nil || seen[v] { + return false + } + seen[v] = true + if isKnownNonNilAddr(v) { + return true + } + switch v := v.(type) { + case *ssa.ChangeType: + return isLocallyKnownNonNil(v.X, seen) + case *ssa.Convert: + return isPointerGoType(v.X.Type()) && isLocallyKnownNonNil(v.X, seen) + case *ssa.UnOp: + if v.Op == token.MUL && isPointerGoType(v.Type()) { + stored, ok := localStoredValue(v.X, v) + return ok && isLocallyKnownNonNil(stored, seen) + } + } + return false +} + +func localStoredValue(addr ssa.Value, before ssa.Instruction) (ssa.Value, bool) { + block := before.Block() + if block == nil { + return nil, false + } + beforeIndex := instructionIndex(block, before) + if beforeIndex < 0 { + return nil, false + } + for i := beforeIndex - 1; i >= 0; i-- { + instr := block.Instrs[i] + switch instr := instr.(type) { + case *ssa.Store: + if equivalentMemoryAddresses(instr.Addr, addr, make(map[ssaValuePair]bool)) { + return instr.Val, true + } + if mayAliasMemoryAddresses(instr.Addr, addr) { + return nil, false + } + default: + if mayChangePointerMemory(instr) { + return nil, false + } + } + } + return nil, false +} + +// equivalentPointerValues compares repeated pointer loads without treating +// arbitrary SSA expressions as equal. Every load pair must use equivalent +// addresses, and the path between them must preserve that memory. +func equivalentPointerValues(x, y ssa.Value, seen map[ssaValuePair]bool) bool { + if x == y { + return true + } + if x == nil || y == nil { + return false + } + pair := ssaValuePair{x, y} + if seen[pair] { + return true + } + seen[pair] = true + + switch x := x.(type) { + case *ssa.ChangeType: + y, ok := y.(*ssa.ChangeType) + return ok && equivalentPointerValues(x.X, y.X, seen) + case *ssa.Convert: + y, ok := y.(*ssa.Convert) + return ok && equivalentPointerValues(x.X, y.X, seen) + case *ssa.UnOp: + y, ok := y.(*ssa.UnOp) + if !ok || x.Op != token.MUL || y.Op != token.MUL { + return false + } + if !equivalentMemoryAddresses(x.X, y.X, seen) { + return false + } + return memoryUnchangedBetween(x, y, x.X) || memoryUnchangedBetween(y, x, y.X) + } + return false +} + +func equivalentMemoryAddresses(x, y ssa.Value, seen map[ssaValuePair]bool) bool { + if x == y { + return true + } + switch x := x.(type) { + case *ssa.FieldAddr: + y, ok := y.(*ssa.FieldAddr) + return ok && x.Field == y.Field && equivalentPointerValues(x.X, y.X, seen) + case *ssa.IndexAddr: + y, ok := y.(*ssa.IndexAddr) + return ok && equivalentSSAIndices(x.Index, y.Index) && equivalentPointerValues(x.X, y.X, seen) + case *ssa.ChangeType: + y, ok := y.(*ssa.ChangeType) + return ok && equivalentMemoryAddresses(x.X, y.X, seen) + case *ssa.Convert: + y, ok := y.(*ssa.Convert) + return ok && equivalentMemoryAddresses(x.X, y.X, seen) + } + return false +} + +func equivalentSSAIndices(x, y ssa.Value) bool { + if x == y { + return true + } + xv, xok := constInt(x) + yv, yok := constInt(y) + return xok && yok && xv == yv +} + +func instructionIndex(block *ssa.BasicBlock, target ssa.Instruction) int { + for i, instr := range block.Instrs { + if instr == target { + return i + } + } + return -1 +} + +// memoryUnchangedBetween follows only a single-predecessor path. This keeps a +// proof from silently crossing a merge where another predecessor may write. +func memoryUnchangedBetween(from, to ssa.Instruction, addr ssa.Value) bool { + fromBlock, toBlock := from.Block(), to.Block() + if fromBlock == nil || toBlock == nil || !fromBlock.Dominates(toBlock) { + return false + } + fromIndex, toIndex := instructionIndex(fromBlock, from), instructionIndex(toBlock, to) + if fromIndex < 0 || toIndex < 0 { + return false + } + if fromBlock == toBlock { + if fromIndex >= toIndex { + return false + } + return memoryRangeUnchanged(fromBlock.Instrs[fromIndex+1:toIndex], addr) + } + + var path []*ssa.BasicBlock + for block := toBlock; block != fromBlock; { + if len(block.Preds) != 1 { + return false + } + path = append(path, block) + block = block.Preds[0] + } + if !memoryRangeUnchanged(fromBlock.Instrs[fromIndex+1:], addr) { + return false + } + for i := len(path) - 1; i >= 0; i-- { + block := path[i] + end := len(block.Instrs) + if block == toBlock { + end = toIndex + } + if !memoryRangeUnchanged(block.Instrs[:end], addr) { + return false + } + } + return true +} + +func memoryRangeUnchanged(instrs []ssa.Instruction, addr ssa.Value) bool { + for _, instr := range instrs { + if store, ok := instr.(*ssa.Store); ok { + if mayAliasMemoryAddresses(store.Addr, addr) { + return false + } + continue + } + if mayChangePointerMemory(instr) { + return false + } + } + return true +} + +func mayChangePointerMemory(instr ssa.Instruction) bool { + switch instr := instr.(type) { + case *ssa.Call, *ssa.Go, *ssa.Defer, *ssa.Send, *ssa.MapUpdate, *ssa.RunDefers: + return true + case *ssa.UnOp: + return instr.Op == token.ARROW + } + return false +} + +// mayAliasMemoryAddresses is conservative except for locations that Go SSA +// proves disjoint: different globals, fields of a locally rooted object, or +// fields rooted in distinct allocations. Unsafe conversions never get a +// local root and therefore remain possible aliases. +func mayAliasMemoryAddresses(x, y ssa.Value) bool { + if equivalentMemoryAddresses(x, y, make(map[ssaValuePair]bool)) { + return true + } + if xg, ok := x.(*ssa.Global); ok { + if yg, ok := y.(*ssa.Global); ok { + return xg == yg + } + return !isSafeDerivedAddress(y) + } + if _, ok := y.(*ssa.Global); ok { + return !isSafeDerivedAddress(x) + } + if xf, ok := x.(*ssa.FieldAddr); ok { + if yf, ok := y.(*ssa.FieldAddr); ok { + if equivalentPointerValues(xf.X, yf.X, make(map[ssaValuePair]bool)) { + return xf.Field == yf.Field + } + xroot, xok := localPointerRoot(xf.X, make(map[ssa.Value]bool)) + yroot, yok := localPointerRoot(yf.X, make(map[ssa.Value]bool)) + if xok && yok && definitelyDistinctPointerRoots(xroot, yroot) { + return false + } + } + } + return true +} + +func localPointerRoot(v ssa.Value, seen map[ssa.Value]bool) (ssa.Value, bool) { + if v == nil || seen[v] { + return nil, false + } + seen[v] = true + switch v := v.(type) { + case *ssa.Alloc, *ssa.Global: + return v, true + case *ssa.ChangeType: + return localPointerRoot(v.X, seen) + case *ssa.Convert: + if isPointerGoType(v.X.Type()) { + return localPointerRoot(v.X, seen) + } + case *ssa.FieldAddr: + return localPointerRoot(v.X, seen) + case *ssa.IndexAddr: + return localPointerRoot(v.X, seen) + case *ssa.UnOp: + if v.Op == token.MUL && isPointerGoType(v.Type()) { + stored, ok := localStoredValue(v.X, v) + if ok { + return localPointerRoot(stored, seen) + } + } + } + return nil, false +} + +func definitelyDistinctPointerRoots(x, y ssa.Value) bool { + if x == y { + return false + } + switch x.(type) { + case *ssa.Alloc, *ssa.Global: + default: + return false + } + switch y.(type) { + case *ssa.Alloc, *ssa.Global: + return true + } + return false +} + +func isSafeDerivedAddress(v ssa.Value) bool { + var base ssa.Value + switch v := v.(type) { + case *ssa.FieldAddr: + base = v.X + case *ssa.IndexAddr: + base = v.X + default: + return false + } + root, ok := localPointerRoot(base, make(map[ssa.Value]bool)) + if !ok { + return false + } + switch root.(type) { + case *ssa.Alloc, *ssa.Global: + return true + } + return false +} + +func isNilConst(v ssa.Value) bool { + c, ok := v.(*ssa.Const) + return ok && c.Value == nil +} + func isWrapNilCheckCall(v ssa.Value) bool { call, ok := v.(*ssa.Call) if !ok { @@ -1847,19 +2218,37 @@ func (p *context) emitNilDerefBaseCheck(b llssa.Builder, addr ssa.Value) { } p.emitCheckedDerefCheck(b, addr) case *ssa.FieldAddr: - if isKnownNonNilAddr(addr.X) || isWrapNilCheckCall(addr.X) { + if _, ok := p.methodReceiverBases[addr]; ok { + return + } + if isKnownNonNilAddr(addr.X) || isWrapNilCheckCall(addr.X) || isKnownNonNilAt(addr.X, addr) { + return + } + p.emitNilDerefBaseCheck(b, addr.X) + if isPointerGoType(addr.X.Type()) { + base := p.compileValue(b, addr.X) + b.AssertNilDerefBranch(base) + } + case *ssa.IndexAddr: + if _, ok := p.methodReceiverBases[addr]; ok { + return + } + if isKnownNonNilAddr(addr.X) || isWrapNilCheckCall(addr.X) || isKnownNonNilAt(addr.X, addr) { return } p.emitNilDerefBaseCheck(b, addr.X) if isPointerGoType(addr.X.Type()) { base := p.compileValue(b, addr.X) - b.AssertNilDeref(base) + b.AssertNilDerefBranch(base) } } } func (p *context) emitCheckedDerefCheck(b llssa.Builder, arg *ssa.UnOp) { p.emitNilDerefBaseCheck(b, arg.X) + if isKnownNonNilAt(arg.X, arg) { + return + } ptr := p.compileValue(b, arg.X) b.AssertNilDeref(ptr) } @@ -1940,6 +2329,95 @@ func collectMethodNilDerefChecks(fn *ssa.Function) map[*ssa.UnOp]none { return checks } +func promotedPointerReceiverBase(fn *ssa.Function, args []ssa.Value) (ssa.Value, bool) { + if fn == nil || len(args) == 0 { + return nil, false + } + recv := fn.Signature.Recv() + if recv == nil || !isPointerGoType(recv.Type()) { + return nil, false + } + return derivedReceiverBase(args[0]) +} + +func boundPromotedPointerReceiverBase(fn *ssa.Function, bindings []ssa.Value) (ssa.Value, bool) { + if fn == nil || len(fn.FreeVars) == 0 || len(bindings) == 0 || + !strings.HasPrefix(fn.Synthetic, "bound method wrapper for ") || + !isPointerGoType(fn.FreeVars[0].Type()) { + return nil, false + } + return derivedReceiverBase(bindings[0]) +} + +func derivedReceiverBase(arg ssa.Value) (ssa.Value, bool) { + addr := arg + if deref, ok := arg.(*ssa.UnOp); ok { + if deref.Op != token.MUL { + return nil, false + } + addr = deref.X + } + var root ssa.Value + for { + switch current := addr.(type) { + case *ssa.FieldAddr: + root = current + addr = current.X + case *ssa.IndexAddr: + if !isPointerGoType(current.X.Type()) { + addr = nil + break + } + root = current + addr = current.X + default: + addr = nil + } + if addr == nil { + break + } + } + if root == nil || isKnownNonNilAddr(root) || isWrapNilCheckCall(root) { + return nil, false + } + return root, true +} + +func collectMethodReceiverBases(fn *ssa.Function) map[ssa.Value]none { + var checks map[ssa.Value]none + mark := func(addr ssa.Value, ok bool) { + if !ok { + return + } + if checks == nil { + checks = make(map[ssa.Value]none) + } + checks[addr] = none{} + } + markCall := func(call *ssa.CallCommon) { + if fn, ok := call.Value.(*ssa.Function); ok { + mark(promotedPointerReceiverBase(fn, call.Args)) + } + } + for _, block := range fn.Blocks { + for _, instr := range block.Instrs { + switch instr := instr.(type) { + case *ssa.Call: + markCall(&instr.Call) + case *ssa.Defer: + markCall(&instr.Call) + case *ssa.Go: + markCall(&instr.Call) + case *ssa.MakeClosure: + if bound, ok := instr.Fn.(*ssa.Function); ok { + mark(boundPromotedPointerReceiverBase(bound, instr.Bindings)) + } + } + } + } + return checks +} + func (p *context) callEx(b llssa.Builder, act llssa.DoAction, call *ssa.CallCommon, ds *explicitDeferStack) (ret llssa.Expr) { p.recordCallerLocationForCall(b, call) p.emitPCLineLabel(b, call.Pos()) diff --git a/cl/instr_offsetof_test.go b/cl/instr_offsetof_test.go index f7edc21812..992b9d5879 100644 --- a/cl/instr_offsetof_test.go +++ b/cl/instr_offsetof_test.go @@ -325,12 +325,17 @@ type outer struct { A int C int inner + innerArray [2]inner } func addr(v *outer) *int { return &v.B } +func indexedAddr(v *outer, i int) *int { + return &v.innerArray[i].B +} + func nestedAddr(v *outer) *int { return &(v.inner.B) } @@ -367,6 +372,15 @@ func offset(v *outer) uintptr { t.Fatalf("nested address-of field selector was not detected: %s", field) } } + indexed := fieldAddrInstrs(t, ssaPkg.Func("indexedAddr")) + if len(indexed) < 2 { + t.Fatalf("indexedAddr FieldAddr count = %d, want at least 2", len(indexed)) + } + for _, field := range indexed { + if !ctx.isAddressOfFieldAddr(field) { + t.Fatalf("indexed address-of field selector was not detected: %s", field) + } + } if ctx.isAddressOfFieldAddr(fieldAddrInstr(t, ssaPkg.Func("value"), "B")) { t.Fatal("plain field selector should not be treated as address-of") } diff --git a/cl/zero_size_deref_test.go b/cl/zero_size_deref_test.go index 6ece9780ea..8ab6f93569 100644 --- a/cl/zero_size_deref_test.go +++ b/cl/zero_size_deref_test.go @@ -23,3 +23,47 @@ func Eq(p, q *T) bool { t.Fatalf("zero-sized field comparison should guard field bases and loads, got %d guards:\n%s", got, ir) } } + +func TestUnusedDerefEmitsNilGuard(t *testing.T) { + const src = `package unusedderef +func LoadArrayElement() { + var values [2]*int + _ = *values[1] +} +func LoadPointer(p *int) { + _ = *p +} +` + ir := compileWithRewrites(t, src, nil) + arrayLoad := llvmFunction(t, ir, "unusedderef.LoadArrayElement") + if !strings.Contains(arrayLoad, "AssertNilDeref") { + t.Fatalf("unused array-element dereference should retain a nil guard:\n%s", arrayLoad) + } + directLoad := llvmFunction(t, ir, "unusedderef.LoadPointer") + if !strings.Contains(directLoad, "AssertNilDeref") { + t.Fatalf("unused direct dereference should retain a nil guard:\n%s", directLoad) + } +} + +func TestUnusedDerefAvoidsRedundantNilGuards(t *testing.T) { + const src = `package unusedderef +func LocalAlloc() { + p := new(int) + _ = *p +} +//go:noinline +func ArrayPointer() *[2]int { return nil } +func EffectfulArray() { + _ = *ArrayPointer() +} +` + ir := compileWithRewrites(t, src, nil) + localAlloc := llvmFunction(t, ir, "unusedderef.LocalAlloc") + if got := strings.Count(localAlloc, "AssertNilDeref"); got != 0 { + t.Fatalf("known-non-nil local allocation emitted %d nil guards, want 0:\n%s", got, localAlloc) + } + effectfulArray := llvmFunction(t, ir, "unusedderef.EffectfulArray") + if got := strings.Count(effectfulArray, "AssertNilDeref"); got != 1 { + t.Fatalf("effectful array-pointer dereference emitted %d nil guards, want 1:\n%s", got, effectfulArray) + } +} diff --git a/ssa/memory.go b/ssa/memory.go index f88b4826d5..71b9cce124 100644 --- a/ssa/memory.go +++ b/ssa/memory.go @@ -348,6 +348,28 @@ func (b Builder) AssertNilDeref(ptr Expr) { b.InlineCall(b.Pkg.rtFunc("AssertNilDeref"), isNil) } +// AssertNilDerefBranch checks ptr without keeping it live across the panic +// call on the non-nil path. This matters for conservative collectors, where a +// spill created solely by the check could retain an otherwise dead object. +func (b Builder) AssertNilDerefBranch(ptr Expr) { + if ptr.impl.C == nil { + return + } + if ptr.impl.IsConstant() && !ptr.impl.IsNull() { + return + } + nilPtr := llvm.ConstNull(ptr.impl.Type()) + isNil := Expr{llvm.CreateICmp(b.impl, llvm.IntEQ, ptr.impl, nilPtr), b.Prog.Bool()} + panicBlock := b.Prog.ctx.AddBasicBlock(b.Func.impl, "") + continueBlock := b.Prog.ctx.AddBasicBlock(b.Func.impl, "") + b.impl.CreateCondBr(isNil.impl, panicBlock, continueBlock) + b.impl.SetInsertPointAtEnd(panicBlock) + b.Call(b.Pkg.rtFunc("AssertNilDeref"), b.Prog.BoolVal(true)) + b.impl.CreateUnreachable() + b.impl.SetInsertPointAtEnd(continueBlock) + b.blk.last = continueBlock +} + func (b Builder) NilDerefCheck(ptr Expr) Expr { checked := b.Call(b.Pkg.rtFunc("AssertNilDerefPtr"), b.Convert(b.Prog.VoidPtr(), ptr)) return b.Convert(ptr.Type, checked) diff --git a/ssa/memory_test.go b/ssa/memory_test.go index e1eb34ef9d..9646bbd1e8 100644 --- a/ssa/memory_test.go +++ b/ssa/memory_test.go @@ -1,8 +1,42 @@ package ssa -import "testing" +import ( + "go/constant" + "go/token" + "go/types" + "strings" + "testing" +) func TestAssertNilDerefZeroExprNoPanic(t *testing.T) { var b Builder b.AssertNilDeref(Expr{}) + b.AssertNilDerefBranch(Expr{}) +} + +func TestAssertNilDerefBranchIR(t *testing.T) { + prog := NewProgram(nil) + defer prog.Dispose() + runtimePkg := types.NewPackage(PkgRuntime, "runtime") + params := types.NewTuple(types.NewVar(token.NoPos, runtimePkg, "isNil", types.Typ[types.Bool])) + assertNilDeref := types.NewFunc(token.NoPos, runtimePkg, "AssertNilDeref", types.NewSignatureType(nil, nil, nil, params, nil, false)) + runtimePkg.Scope().Insert(assertNilDeref) + prog.SetRuntime(runtimePkg) + + ptrParams := types.NewTuple(types.NewVar(token.NoPos, nil, "ptr", types.Typ[types.UnsafePointer])) + pkg := prog.NewPackage("main", "main") + fn := pkg.NewFunc("check", types.NewSignatureType(nil, nil, nil, ptrParams, nil, false), InGo) + b := fn.MakeBody(1) + b.AssertNilDerefBranch(b.Const(constant.MakeInt64(1), prog.VoidPtr())) + b.AssertNilDerefBranch(fn.Param(0)) + b.Return() + b.EndBuild() + + ir := pkg.String() + if got := strings.Count(ir, "AssertNilDeref"); got != 2 { + t.Fatalf("AssertNilDeref references = %d, want declaration and one call:\n%s", got, ir) + } + if !strings.Contains(ir, "br i1") || !strings.Contains(ir, "unreachable") { + t.Fatalf("AssertNilDerefBranch did not emit a nil-only panic path:\n%s", ir) + } } diff --git a/test/go/nil_deref_address_test.go b/test/go/nil_deref_address_test.go index e2a9506b3d..32fc057002 100644 --- a/test/go/nil_deref_address_test.go +++ b/test/go/nil_deref_address_test.go @@ -9,9 +9,25 @@ import ( type nilDerefAddressStruct struct { i int x [2]int + s string +} + +type nilDerefEmbeddedReceiver struct{} + +func (*nilDerefEmbeddedReceiver) value() int { return 0 } + +type nilDerefEmbeddedOuter struct { + padding int + nilDerefEmbeddedReceiver } var nilDerefAddressSink any +var nilDerefAddressStructPtr *nilDerefAddressStruct +var nilDerefAddressSlicePtr *[]byte +var nilDerefAddressStringPtr *string +var nilDerefAddressArrayPtr *[4]int +var nilDerefEmbeddedOuterPtr *nilDerefEmbeddedOuter +var nilDerefEmbeddedReceiverPtr *nilDerefEmbeddedReceiver func TestNilDerefAddressOperationsPanic(t *testing.T) { tests := []struct { @@ -39,6 +55,46 @@ func TestNilDerefAddressOperationsPanic(t *testing.T) { nilDerefAddressSink = &p[0] }, }, + { + name: "array field element address", + f: func() { + nilDerefAddressSink = &nilDerefAddressStructPtr.x[0] + }, + }, + { + name: "array field variable element address", + f: func() { + i := 1 + nilDerefAddressSink = &nilDerefAddressStructPtr.x[i] + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + expectNilDerefAddressPanic(t, tt.f) + }) + } +} + +func TestUnusedNilDerefOperationsPanic(t *testing.T) { + tests := []struct { + name string + f func() + }{ + { + name: "direct pointer", + f: func() { + var p *int + _ = *p + }, + }, + { + name: "pointer loaded from array", + f: func() { + var values [2]*int + _ = *values[1] + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -55,15 +111,13 @@ func TestNilDerefPrintedCompositeLoadsPanic(t *testing.T) { { name: "slice pointer load", f: func() { - var p *[]byte - println(*p) + println(*nilDerefAddressSlicePtr) }, }, { name: "string pointer load", f: func() { - var p *string - println(*p) + println(*nilDerefAddressStringPtr) }, }, } @@ -75,10 +129,35 @@ func TestNilDerefPrintedCompositeLoadsPanic(t *testing.T) { } func TestNilDerefPrintedFieldLoadPanic(t *testing.T) { - expectNilDerefAddressPanic(t, func() { - var p *nilDerefAddressStruct - println(p.i) - }) + tests := []struct { + name string + f func() + }{ + { + name: "basic field", + f: func() { + println(nilDerefAddressStructPtr.i) + }, + }, + { + name: "multiword field", + f: func() { + println(nilDerefAddressStructPtr.s) + }, + }, + { + name: "array field element", + f: func() { + i := 1 + println(nilDerefAddressStructPtr.x[i]) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + expectNilDerefAddressPanic(t, tt.f) + }) + } } func TestNilDerefInterfaceCopiesPanic(t *testing.T) { @@ -89,15 +168,13 @@ func TestNilDerefInterfaceCopiesPanic(t *testing.T) { { name: "array pointer to interface", f: func() { - var p *[4]int - nilDerefAddressSink = *p + nilDerefAddressSink = *nilDerefAddressArrayPtr }, }, { name: "struct pointer to interface", f: func() { - var p *nilDerefAddressStruct - nilDerefAddressSink = *p + nilDerefAddressSink = *nilDerefAddressStructPtr }, }, } @@ -108,6 +185,44 @@ func TestNilDerefInterfaceCopiesPanic(t *testing.T) { } } +func TestNilDerefPromotedPointerReceiverPanic(t *testing.T) { + tests := []struct { + name string + f func() + }{ + { + name: "promoted method", + f: func() { + nilDerefAddressSink = nilDerefEmbeddedOuterPtr.value() + }, + }, + { + name: "explicit embedded field", + f: func() { + nilDerefAddressSink = nilDerefEmbeddedOuterPtr.nilDerefEmbeddedReceiver.value() + }, + }, + { + name: "promoted method value", + f: func() { + method := nilDerefEmbeddedOuterPtr.value + nilDerefAddressSink = method() + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + expectNilDerefAddressPanic(t, tt.f) + }) + } +} + +func TestNilPointerReceiverRemainsAllowed(t *testing.T) { + if got := nilDerefEmbeddedReceiverPtr.value(); got != 0 { + t.Fatalf("nil pointer receiver method = %d, want 0", got) + } +} + func expectNilDerefAddressPanic(t *testing.T, f func()) { t.Helper() defer func() { diff --git a/test/goroot/xfail.yaml b/test/goroot/xfail.yaml index cee4671e72..732eb1e08c 100644 --- a/test/goroot/xfail.yaml +++ b/test/goroot/xfail.yaml @@ -2440,10 +2440,6 @@ xfails: directive: run case: inline_caller.go reason: runtime caller frame reports main instead of runtime.main on darwin/arm64 - - platform: darwin/arm64 - directive: run - case: nilptr2.go - reason: address-of a dereferenced nil pointer does not panic and the run hangs on darwin/arm64 - platform: darwin/arm64 directive: run case: range4.go @@ -3354,10 +3350,6 @@ xfails: directive: run case: fixedbugs/issue43835.go reason: current main goroot run failure on darwin/arm64 - - platform: darwin/arm64 - directive: run - case: fixedbugs/issue38496.go - reason: current main goroot run failure on darwin/arm64 - version: go1.26 platform: darwin/arm64 directive: run @@ -3452,10 +3444,6 @@ xfails: directive: run case: fixedbugs/issue8132.go reason: current main goroot run failure on linux/amd64 - - platform: linux/amd64 - directive: run - case: fixedbugs/issue38496.go - reason: current main goroot run failure on linux/amd64 - version: go1.24 platform: linux/amd64 directive: run