diff --git a/cl/_testgo/strucintf/out.ll b/cl/_testgo/strucintf/out.ll index 07c3ac59..9e09848f 100644 --- a/cl/_testgo/strucintf/out.ll +++ b/cl/_testgo/strucintf/out.ll @@ -3,8 +3,7 @@ source_filename = "main" %"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr } %"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } -%"github.com/goplus/llgo/internal/abi.StructField" = type { %"github.com/goplus/llgo/internal/abi.Name", ptr, i64 } -%"github.com/goplus/llgo/internal/abi.Name" = type { ptr } +%"github.com/goplus/llgo/internal/abi.StructField" = type { %"github.com/goplus/llgo/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/internal/runtime.String", i1 } %"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 } @"main.init$guard" = global ptr null @@ -270,14 +269,14 @@ _llgo_0: %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %5, i32 0, i32 1 store i64 0, ptr %7, align 4 %8 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %5, align 8 - %9 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %3, ptr %4, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %8, i1 false, i1 false) + %9 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %3, ptr %4, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %8, i1 false) %10 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %10, i32 0, i32 0 store ptr @5, ptr %11, align 8 %12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %10, i32 0, i32 1 store i64 4, ptr %12, align 4 %13 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %10, align 8 - %14 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 24) + %14 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 56) %15 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %14, i64 0 store %"github.com/goplus/llgo/internal/abi.StructField" %9, ptr %15, align 8 %16 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 @@ -288,7 +287,7 @@ _llgo_0: %19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %16, i32 0, i32 2 store i64 1, ptr %19, align 4 %20 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %16, align 8 - %21 = call ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String" %13, %"github.com/goplus/llgo/internal/runtime.Slice" %20) + %21 = call ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String" %13, i64 8, %"github.com/goplus/llgo/internal/runtime.Slice" %20) store ptr %21, ptr @"main.struct$MYpsoM99ZwFY087IpUOkIw1zjBA_sgFXVodmn1m-G88", align 8 %22 = load ptr, ptr @"_llgo_struct$K-dZ9QotZfVPz2a0YdRa9vmZUuDXPTqZOlMShKEDJtk", align 8 %23 = icmp eq ptr %22, null @@ -308,14 +307,14 @@ _llgo_1: ; preds = %_llgo_0 %31 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %29, i32 0, i32 1 store i64 0, ptr %31, align 4 %32 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %29, align 8 - %33 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %27, ptr %28, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %32, i1 true, i1 false) + %33 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %27, ptr %28, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %32, i1 false) %34 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %35 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %34, i32 0, i32 0 store ptr @8, ptr %35, align 8 %36 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %34, i32 0, i32 1 store i64 4, ptr %36, align 4 %37 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %34, align 8 - %38 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 24) + %38 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 56) %39 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %38, i64 0 store %"github.com/goplus/llgo/internal/abi.StructField" %33, ptr %39, align 8 %40 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 @@ -326,7 +325,7 @@ _llgo_1: ; preds = %_llgo_0 %43 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %40, i32 0, i32 2 store i64 1, ptr %43, align 4 %44 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %40, align 8 - %45 = call ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String" %37, %"github.com/goplus/llgo/internal/runtime.Slice" %44) + %45 = call ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String" %37, i64 8, %"github.com/goplus/llgo/internal/runtime.Slice" %44) store ptr %45, ptr @"_llgo_struct$K-dZ9QotZfVPz2a0YdRa9vmZUuDXPTqZOlMShKEDJtk", align 8 br label %_llgo_2 @@ -334,9 +333,9 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 ret void } -declare ptr @"github.com/goplus/llgo/internal/runtime.Struct"(i64, %"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.Slice") +declare ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String", i64, %"github.com/goplus/llgo/internal/runtime.Slice") -declare %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/internal/runtime.String", i1, i1) +declare %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/internal/runtime.String", i1) declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) diff --git a/cl/_testgo/struczero/in.go b/cl/_testgo/struczero/in.go index 589b75f2..ce583d11 100644 --- a/cl/_testgo/struczero/in.go +++ b/cl/_testgo/struczero/in.go @@ -20,6 +20,7 @@ func Bar(v any) (ret foo.Foo, ok bool) { func main() { ret, ok := Foo(nil) println(ret.pb, ret.f, "notOk:", !ok) + ret2, ok2 := Bar(foo.Foo{}) println(ret2.Pb(), ret2.F, ok2) } diff --git a/cl/_testgo/struczero/out.ll b/cl/_testgo/struczero/out.ll index 60b85986..8299781b 100644 --- a/cl/_testgo/struczero/out.ll +++ b/cl/_testgo/struczero/out.ll @@ -5,8 +5,7 @@ source_filename = "main" %"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr } %main.bar = type { ptr, float } %"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } -%"github.com/goplus/llgo/internal/abi.StructField" = type { %"github.com/goplus/llgo/internal/abi.Name", ptr, i64 } -%"github.com/goplus/llgo/internal/abi.Name" = type { ptr } +%"github.com/goplus/llgo/internal/abi.StructField" = type { %"github.com/goplus/llgo/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/internal/runtime.String", i1 } %"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 } @"main.init$guard" = global ptr null @@ -21,13 +20,15 @@ source_filename = "main" @3 = private unnamed_addr constant [2 x i8] c"F\00", align 1 @4 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 @5 = private unnamed_addr constant [5 x i8] c"main\00", align 1 -@6 = private unnamed_addr constant [43 x i8] c"github.com/goplus/llgo/cl/internal/foo.Foo\00", align 1 -@7 = private unnamed_addr constant [3 x i8] c"pb\00", align 1 -@8 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 -@9 = private unnamed_addr constant [2 x i8] c"f\00", align 1 -@10 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 -@11 = private unnamed_addr constant [5 x i8] c"main\00", align 1 -@12 = private unnamed_addr constant [9 x i8] c"main.bar\00", align 1 +@6 = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@7 = private unnamed_addr constant [43 x i8] c"github.com/goplus/llgo/cl/internal/foo.Foo\00", align 1 +@8 = private unnamed_addr constant [3 x i8] c"pb\00", align 1 +@9 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 +@10 = private unnamed_addr constant [2 x i8] c"f\00", align 1 +@11 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 +@12 = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@13 = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@14 = private unnamed_addr constant [9 x i8] c"main.bar\00", align 1 define { %"github.com/goplus/llgo/cl/internal/foo.Foo", i1 } @main.Bar(%"github.com/goplus/llgo/internal/runtime.eface" %0) { _llgo_0: @@ -217,7 +218,7 @@ _llgo_1: ; preds = %_llgo_0 %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %7, i32 0, i32 1 store i64 0, ptr %9, align 4 %10 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %7, align 8 - %11 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %5, ptr %6, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %10, i1 false, i1 false) + %11 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %5, ptr %6, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %10, i1 false) %12 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %12, i32 0, i32 0 store ptr @3, ptr %13, align 8 @@ -231,14 +232,14 @@ _llgo_1: ; preds = %_llgo_0 %19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %17, i32 0, i32 1 store i64 0, ptr %19, align 4 %20 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %17, align 8 - %21 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %15, ptr %16, i64 8, %"github.com/goplus/llgo/internal/runtime.String" %20, i1 true, i1 false) + %21 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %15, ptr %16, i64 8, %"github.com/goplus/llgo/internal/runtime.String" %20, i1 false) %22 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %23 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 0 store ptr @5, ptr %23, align 8 %24 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 1 store i64 4, ptr %24, align 4 %25 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %22, align 8 - %26 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 48) + %26 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 112) %27 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %26, i64 0 store %"github.com/goplus/llgo/internal/abi.StructField" %11, ptr %27, align 8 %28 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %26, i64 1 @@ -251,81 +252,93 @@ _llgo_1: ; preds = %_llgo_0 %32 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %29, i32 0, i32 2 store i64 2, ptr %32, align 4 %33 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %29, align 8 - %34 = call ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String" %25, %"github.com/goplus/llgo/internal/runtime.Slice" %33) + %34 = call ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String" %25, i64 16, %"github.com/goplus/llgo/internal/runtime.Slice" %33) %35 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %36 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 0 store ptr @6, ptr %36, align 8 %37 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 1 - store i64 42, ptr %37, align 4 + store i64 4, ptr %37, align 4 %38 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %35, align 8 - %39 = call ptr @"github.com/goplus/llgo/internal/runtime.Named"(%"github.com/goplus/llgo/internal/runtime.String" %38, ptr %34) - store ptr %39, ptr @"github.com/goplus/llgo/cl/internal/foo.Foo", align 8 + %39 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %40 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %39, i32 0, i32 0 + store ptr @7, ptr %40, align 8 + %41 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %39, i32 0, i32 1 + store i64 42, ptr %41, align 4 + %42 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %39, align 8 + %43 = call ptr @"github.com/goplus/llgo/internal/runtime.Named"(%"github.com/goplus/llgo/internal/runtime.String" %38, %"github.com/goplus/llgo/internal/runtime.String" %42, ptr %34, { ptr, i64, i64 } zeroinitializer) + store ptr %43, ptr @"github.com/goplus/llgo/cl/internal/foo.Foo", align 8 br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 - %40 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %41 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %40, i32 0, i32 0 - store ptr @7, ptr %41, align 8 - %42 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %40, i32 0, i32 1 - store i64 2, ptr %42, align 4 - %43 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %40, align 8 - %44 = load ptr, ptr @"*_llgo_byte", align 8 - %45 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %46 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %45, i32 0, i32 0 - store ptr @8, ptr %46, align 8 - %47 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %45, i32 0, i32 1 - store i64 0, ptr %47, align 4 - %48 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %45, align 8 - %49 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %43, ptr %44, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %48, i1 false, i1 false) - %50 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %51 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %50, i32 0, i32 0 - store ptr @9, ptr %51, align 8 - %52 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %50, i32 0, i32 1 - store i64 1, ptr %52, align 4 - %53 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %50, align 8 - %54 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 13) - %55 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %56 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %55, i32 0, i32 0 - store ptr @10, ptr %56, align 8 - %57 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %55, i32 0, i32 1 - store i64 0, ptr %57, align 4 - %58 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %55, align 8 - %59 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %53, ptr %54, i64 8, %"github.com/goplus/llgo/internal/runtime.String" %58, i1 false, i1 false) - %60 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %61 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %60, i32 0, i32 0 - store ptr @11, ptr %61, align 8 - %62 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %60, i32 0, i32 1 - store i64 4, ptr %62, align 4 - %63 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %60, align 8 - %64 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 48) - %65 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %64, i64 0 - store %"github.com/goplus/llgo/internal/abi.StructField" %49, ptr %65, align 8 - %66 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %64, i64 1 - store %"github.com/goplus/llgo/internal/abi.StructField" %59, ptr %66, align 8 - %67 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 - %68 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %67, i32 0, i32 0 - store ptr %64, ptr %68, align 8 - %69 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %67, i32 0, i32 1 - store i64 2, ptr %69, align 4 - %70 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %67, i32 0, i32 2 - store i64 2, ptr %70, align 4 - %71 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %67, align 8 - %72 = call ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String" %63, %"github.com/goplus/llgo/internal/runtime.Slice" %71) - %73 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %74 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %73, i32 0, i32 0 - store ptr @12, ptr %74, align 8 - %75 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %73, i32 0, i32 1 - store i64 8, ptr %75, align 4 - %76 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %73, align 8 - %77 = call ptr @"github.com/goplus/llgo/internal/runtime.Named"(%"github.com/goplus/llgo/internal/runtime.String" %76, ptr %72) - store ptr %77, ptr @main.bar, align 8 + %44 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %45 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %44, i32 0, i32 0 + store ptr @8, ptr %45, align 8 + %46 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %44, i32 0, i32 1 + store i64 2, ptr %46, align 4 + %47 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %44, align 8 + %48 = load ptr, ptr @"*_llgo_byte", align 8 + %49 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %50 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %49, i32 0, i32 0 + store ptr @9, ptr %50, align 8 + %51 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %49, i32 0, i32 1 + store i64 0, ptr %51, align 4 + %52 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %49, align 8 + %53 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %47, ptr %48, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %52, i1 false) + %54 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %55 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %54, i32 0, i32 0 + store ptr @10, ptr %55, align 8 + %56 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %54, i32 0, i32 1 + store i64 1, ptr %56, align 4 + %57 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %54, align 8 + %58 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 13) + %59 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %60 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %59, i32 0, i32 0 + store ptr @11, ptr %60, align 8 + %61 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %59, i32 0, i32 1 + store i64 0, ptr %61, align 4 + %62 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %59, align 8 + %63 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %57, ptr %58, i64 8, %"github.com/goplus/llgo/internal/runtime.String" %62, i1 false) + %64 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %65 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %64, i32 0, i32 0 + store ptr @12, ptr %65, align 8 + %66 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %64, i32 0, i32 1 + store i64 4, ptr %66, align 4 + %67 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %64, align 8 + %68 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 112) + %69 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %68, i64 0 + store %"github.com/goplus/llgo/internal/abi.StructField" %53, ptr %69, align 8 + %70 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %68, i64 1 + store %"github.com/goplus/llgo/internal/abi.StructField" %63, ptr %70, align 8 + %71 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %72 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %71, i32 0, i32 0 + store ptr %68, ptr %72, align 8 + %73 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %71, i32 0, i32 1 + store i64 2, ptr %73, align 4 + %74 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %71, i32 0, i32 2 + store i64 2, ptr %74, align 4 + %75 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %71, align 8 + %76 = call ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String" %67, i64 16, %"github.com/goplus/llgo/internal/runtime.Slice" %75) + %77 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %78 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %77, i32 0, i32 0 + store ptr @13, ptr %78, align 8 + %79 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %77, i32 0, i32 1 + store i64 4, ptr %79, align 4 + %80 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %77, align 8 + %81 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %82 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %81, i32 0, i32 0 + store ptr @14, ptr %82, align 8 + %83 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %81, i32 0, i32 1 + store i64 8, ptr %83, align 4 + %84 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %81, align 8 + %85 = call ptr @"github.com/goplus/llgo/internal/runtime.Named"(%"github.com/goplus/llgo/internal/runtime.String" %80, %"github.com/goplus/llgo/internal/runtime.String" %84, ptr %76, { ptr, i64, i64 } zeroinitializer) + store ptr %85, ptr @main.bar, align 8 ret void } -declare ptr @"github.com/goplus/llgo/internal/runtime.Struct"(i64, %"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.Slice") +declare ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String", i64, %"github.com/goplus/llgo/internal/runtime.Slice") -declare %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/internal/runtime.String", i1, i1) +declare %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/internal/runtime.String", i1) declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) -declare ptr @"github.com/goplus/llgo/internal/runtime.Named"(%"github.com/goplus/llgo/internal/runtime.String", ptr) +declare ptr @"github.com/goplus/llgo/internal/runtime.Named"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String", ptr, %"github.com/goplus/llgo/internal/runtime.Slice") diff --git a/cl/_testrt/concat/out.ll b/cl/_testrt/concat/out.ll index f850807f..1ef2685d 100644 --- a/cl/_testrt/concat/out.ll +++ b/cl/_testrt/concat/out.ll @@ -25,37 +25,26 @@ _llgo_0: %4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 1 store i64 0, ptr %4, align 4 %5 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8 - %6 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %5, 0 - %7 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %5, 1 br label %_llgo_1 _llgo_1: ; preds = %_llgo_2, %_llgo_0 - %8 = phi ptr [ %6, %_llgo_0 ], [ %22, %_llgo_2 ] - %9 = phi i64 [ %7, %_llgo_0 ], [ %23, %_llgo_2 ] - %10 = phi i64 [ -1, %_llgo_0 ], [ %15, %_llgo_2 ] - %11 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 - %12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %11, i32 0, i32 0 - store ptr %8, ptr %12, align 8 - %13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %11, i32 0, i32 1 - store i64 %9, ptr %13, align 4 - %14 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %11, align 8 - %15 = add i64 %10, 1 - %16 = icmp slt i64 %15, %1 - br i1 %16, label %_llgo_2, label %_llgo_3 + %6 = phi %"github.com/goplus/llgo/internal/runtime.String" [ %5, %_llgo_0 ], [ %14, %_llgo_2 ] + %7 = phi i64 [ -1, %_llgo_0 ], [ %8, %_llgo_2 ] + %8 = add i64 %7, 1 + %9 = icmp slt i64 %8, %1 + br i1 %9, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %17 = icmp slt i64 %15, 0 - call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %17) - %18 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 - %19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i64 %15 - %20 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %19, align 8 - %21 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String" %14, %"github.com/goplus/llgo/internal/runtime.String" %20) - %22 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %21, 0 - %23 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %21, 1 + %10 = icmp slt i64 %8, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %10) + %11 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 + %12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %11, i64 %8 + %13 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %12, align 8 + %14 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String" %6, %"github.com/goplus/llgo/internal/runtime.String" %13) br label %_llgo_1 _llgo_3: ; preds = %_llgo_1 - ret %"github.com/goplus/llgo/internal/runtime.String" %14 + ret %"github.com/goplus/llgo/internal/runtime.String" %6 } define %"github.com/goplus/llgo/internal/runtime.String" @main.info(%"github.com/goplus/llgo/internal/runtime.String" %0) { diff --git a/cl/_testrt/gblarray/out.ll b/cl/_testrt/gblarray/out.ll index 2fc333fb..45de88a6 100644 --- a/cl/_testrt/gblarray/out.ll +++ b/cl/_testrt/gblarray/out.ll @@ -1,8 +1,8 @@ ; ModuleID = 'main' source_filename = "main" -%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, { ptr, ptr }, ptr, %"github.com/goplus/llgo/internal/abi.Name", ptr } -%"github.com/goplus/llgo/internal/abi.Name" = type { ptr } +%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, { ptr, ptr }, ptr, %"github.com/goplus/llgo/internal/runtime.String", ptr } +%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } @main.basicTypes = global [25 x ptr] undef @"main.init$guard" = global ptr null @@ -20,7 +20,7 @@ _llgo_0: define ptr @main.basicType(i64 %0) { _llgo_0: - %1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 64) + %1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 72) %2 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 0 %3 = getelementptr inbounds i64, ptr @main.sizeBasicTypes, i64 %0 %4 = load i64, ptr %3, align 4 diff --git a/cl/compile.go b/cl/compile.go index 991c136e..7105730d 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -522,7 +522,7 @@ func (p *context) compilePhis(b llssa.Builder, block *ssa.BasicBlock) int { } for i := 0; i < n; i++ { iv := block.Instrs[i].(*ssa.Phi) - p.bvals[iv] = rets[i].Do(b) + p.bvals[iv] = rets[i] } return n } @@ -540,7 +540,8 @@ func (p *context) compilePhi(b llssa.Builder, v *ssa.Phi) (ret llssa.Expr) { bblks[i] = p.fn.Block(pred.Index) } edges := v.Edges - phi.AddIncoming(b, bblks, func(i int) llssa.Expr { + phi.AddIncoming(b, bblks, func(i int, blk llssa.BasicBlock) llssa.Expr { + b.SetBlockEx(blk, llssa.BeforeLast, false) return p.compileValue(b, edges[i]) }) }) @@ -784,7 +785,7 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) { val := p.compileValue(b, v.Value) b.MapUpdate(m, key, val) case *ssa.Panic: - arg := p.compileValue(b, v.X).Do(b) + arg := p.compileValue(b, v.X) b.Panic(arg) default: panic(fmt.Sprintf("compileInstr: unknown instr - %T\n", instr)) @@ -856,7 +857,7 @@ func (p *context) compileValues(b llssa.Builder, vals []ssa.Value, hasVArg int) n := len(vals) - hasVArg ret := make([]llssa.Expr, n) for i := 0; i < n; i++ { - ret[i] = p.compileValue(b, vals[i]).Do(b) + ret[i] = p.compileValue(b, vals[i]) } if hasVArg > 0 { ret = p.compileVArg(ret, b, vals[n]) diff --git a/internal/abi/llgo_autogen.lla b/internal/abi/llgo_autogen.lla index 0d23b976..2eb60535 100644 Binary files a/internal/abi/llgo_autogen.lla and b/internal/abi/llgo_autogen.lla differ diff --git a/internal/abi/type.go b/internal/abi/type.go index b43621a9..8cf09096 100644 --- a/internal/abi/type.go +++ b/internal/abi/type.go @@ -20,6 +20,15 @@ import ( "unsafe" ) +// IsExported reports whether name starts with an upper-case letter. +func IsExported(name string) bool { + if len(name) > 0 { + c := name[0] + return 'A' <= c && c <= 'Z' + } + return false +} + // ----------------------------------------------------------------------------- // Type is the runtime representation of a Go type. @@ -46,8 +55,8 @@ type Type struct { // If the KindGCProg bit is set in kind, GCData is a GC program. // Otherwise it is a ptrmask bitmap. See mbitmap.go for details. GCData *byte - Str_ Name // string form - PtrToThis_ *Type // type for pointer to this type, may be nil + Str_ string // string form + PtrToThis_ *Type // type for pointer to this type, may be nil } // A Kind represents the specific kind of type that a Type represents. @@ -209,43 +218,57 @@ func (p *FuncType) Variadic() bool { } type StructField struct { - Name Name // name is always non-empty + Name_ string // name is always non-empty Typ *Type // type of field Offset uintptr // byte offset of field + + Tag_ string + Embedded_ bool } +// Embedded reports whether the field is embedded. func (f *StructField) Embedded() bool { - return f.Name.IsEmbedded() + return f.Embedded_ +} + +// Exported reports whether the field is exported. +func (f *StructField) Exported() bool { + return IsExported(f.Name_) } type StructType struct { Type - PkgPath Name - Fields []StructField + PkgPath_ string + Fields []StructField } type InterfaceType struct { Type - PkgPath Name // import path - Methods []Imethod // sorted by hash + PkgPath_ string // import path + Methods []Imethod // sorted by hash } type Text = unsafe.Pointer // TODO(xsw): to be confirmed // Method on non-interface type type Method struct { - Name_ Name // name of method + Name_ string // name of method Mtyp_ *FuncType // method type (without receiver) Ifn_ Text // fn used in interface call (one-word receiver) Tfn_ Text // fn used for normal method call } +// Exported reports whether the method is exported. +func (p *Method) Exported() bool { + return IsExported(p.Name_) +} + // UncommonType is present only for defined types or types with methods // (if T is a defined type, the uncommonTypes for T and *T have methods). // Using a pointer to this struct reduces the overall size required // to describe a non-defined type with no methods. type UncommonType struct { - PkgPath_ Name // import path; empty for built-in types like int, string + PkgPath_ string // import path; empty for built-in types like int, string Mcount uint16 // number of methods Xcount uint16 // number of exported methods Moff uint32 // offset from this uncommontype to [mcount]Method @@ -267,7 +290,7 @@ func (t *UncommonType) ExportedMethods() []Method { // Imethod represents a method on an interface type type Imethod struct { - Name_ Name // name of method + Name_ string // name of method Typ_ *FuncType // .(*FuncType) underneath } @@ -285,6 +308,70 @@ func (t *Type) Common() *Type { return t } +type structTypeUncommon struct { + StructType + u UncommonType +} + +// Uncommon returns a pointer to T's "uncommon" data if there is any, otherwise nil +func (t *Type) Uncommon() *UncommonType { + if t.TFlag&TFlagUncommon == 0 { + return nil + } + switch t.Kind() { + case Struct: + return &(*structTypeUncommon)(unsafe.Pointer(t)).u + case Pointer: + type u struct { + PtrType + u UncommonType + } + return &(*u)(unsafe.Pointer(t)).u + case Func: + type u struct { + FuncType + u UncommonType + } + return &(*u)(unsafe.Pointer(t)).u + case Slice: + type u struct { + SliceType + u UncommonType + } + return &(*u)(unsafe.Pointer(t)).u + case Array: + type u struct { + ArrayType + u UncommonType + } + return &(*u)(unsafe.Pointer(t)).u + case Chan: + type u struct { + ChanType + u UncommonType + } + return &(*u)(unsafe.Pointer(t)).u + case Map: + type u struct { + MapType + u UncommonType + } + return &(*u)(unsafe.Pointer(t)).u + case Interface: + type u struct { + InterfaceType + u UncommonType + } + return &(*u)(unsafe.Pointer(t)).u + default: + type u struct { + Type + u UncommonType + } + return &(*u)(unsafe.Pointer(t)).u + } +} + // Len returns the length of t if t is an array type, otherwise 0 func (t *Type) Len() int { if t.Kind() == Array { @@ -369,6 +456,7 @@ func addChecked(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer { return unsafe.Pointer(uintptr(p) + x) } +/* // Name is an encoded type Name with optional extra data. // // The first byte is a bit field containing: @@ -519,5 +607,6 @@ func NewName(n, tag string, exported, embedded bool) Name { return Name{Bytes: &b[0]} } +*/ // ----------------------------------------------------------------------------- diff --git a/internal/runtime/c/c.go b/internal/runtime/c/c.go index eb502d92..3d200e36 100644 --- a/internal/runtime/c/c.go +++ b/internal/runtime/c/c.go @@ -42,8 +42,8 @@ var Stderr FilePtr //go:linkname Str llgo.cstr func Str(string) *Char -//go:linkname Advance llgo.advance -func Advance(ptr Pointer, offset int) Pointer +// llgo:link Advance llgo.advance +func Advance[PtrT any](ptr PtrT, offset int) PtrT { return ptr } //go:linkname Alloca llgo.alloca func Alloca(size uintptr) Pointer diff --git a/internal/runtime/llgo_autogen.lla b/internal/runtime/llgo_autogen.lla index e2f90b84..6b788455 100644 Binary files a/internal/runtime/llgo_autogen.lla and b/internal/runtime/llgo_autogen.lla differ diff --git a/internal/runtime/runtime2.go b/internal/runtime/runtime2.go deleted file mode 100644 index 69d80ae1..00000000 --- a/internal/runtime/runtime2.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package runtime - -import ( - "unsafe" -) - -type eface struct { - _type *_type - data unsafe.Pointer -} - -type iface struct { - tab *itab - data unsafe.Pointer -} - -// layout of Itab known to compilers -// allocated in non-garbage-collected memory -// Needs to be in sync with -// ../cmd/compile/internal/reflectdata/reflect.go:/^func.WriteTabs. -type itab struct { - inter *interfacetype - _type *_type - hash uint32 // copy of _type.hash. Used for type switches. - _ [4]byte - fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter. -} - -/* -func efaceOf(ep *any) *eface { - return (*eface)(unsafe.Pointer(ep)) -} - -func MakeInterface(inter *InterfaceType, typ *Type, data unsafe.Pointer) Interface { - tab := &itab{inter: inter, _type: typ, hash: 0, fun: [1]uintptr{0}} - return Interface{ - tab: tab, data: data, - } -} -*/ diff --git a/internal/runtime/type.go b/internal/runtime/type.go index 36ce1a0f..8e8b4332 100644 --- a/internal/runtime/type.go +++ b/internal/runtime/type.go @@ -12,11 +12,9 @@ import ( type _type = abi.Type -type interfacetype = abi.InterfaceType - +/* type maptype = abi.MapType -/* type arraytype = abi.ArrayType type chantype = abi.ChanType diff --git a/internal/runtime/z_face.go b/internal/runtime/z_face.go new file mode 100644 index 00000000..c7611fd3 --- /dev/null +++ b/internal/runtime/z_face.go @@ -0,0 +1,205 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +import ( + "unsafe" + + "github.com/goplus/llgo/internal/abi" + "github.com/goplus/llgo/internal/runtime/c" +) + +type eface struct { + _type *_type + data unsafe.Pointer +} + +type iface struct { + tab *itab + data unsafe.Pointer +} + +type interfacetype = abi.InterfaceType + +// layout of Itab known to compilers +// allocated in non-garbage-collected memory +// Needs to be in sync with +// ../cmd/compile/internal/reflectdata/reflect.go:/^func.WriteTabs. +type itab struct { + inter *interfacetype + _type *_type + hash uint32 // copy of _type.hash. Used for type switches. + _ [4]byte + fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter. +} + +// ----------------------------------------------------------------------------- + +type ( + Eface = eface + Iface = iface + Itab = itab +) + +type FuncType = abi.FuncType +type InterfaceType = abi.InterfaceType + +// ToEface converts an iface to an eface. +func ToEface(i Iface) Eface { + return Eface{i.tab._type, i.data} +} + +// ----------------------------------------------------------------------------- + +const ( + typeHdrSize = unsafe.Sizeof(abi.Type{}) + funcTypeHdrSize = unsafe.Sizeof(abi.FuncType{}) + uncommonTypeHdrSize = unsafe.Sizeof(abi.UncommonType{}) + methodSize = unsafe.Sizeof(abi.Method{}) + pointerSize = unsafe.Sizeof(uintptr(0)) + itabHdrSize = unsafe.Sizeof(itab{}) - pointerSize +) + +// Func returns a function type. +func Func(in, out []*Type, variadic bool) *FuncType { + n := len(in) + len(out) + ptr := AllocU(funcTypeHdrSize + uintptr(n)*pointerSize) + c.Memset(ptr, 0, funcTypeHdrSize) + + ret := (*abi.FuncType)(ptr) + ret.Size_ = pointerSize + ret.Hash = uint32(abi.Func) // TODO(xsw): hash + ret.Kind_ = uint8(abi.Func) + ret.InCount = uint16(len(in)) + ret.OutCount = uint16(len(out)) + if variadic { + ret.OutCount |= 1 << 15 + } + + data := (**Type)(c.Advance(ptr, int(funcTypeHdrSize))) + params := unsafe.Slice(data, n) + copy(params, in) + copy(params[len(in):], out) + return ret +} + +// Imethod returns an interface method. +func Imethod(name string, typ *FuncType) abi.Imethod { + return abi.Imethod{ + Name_: name, + Typ_: typ, + } +} + +// Method returns a method. +func Method(name string, typ *FuncType, ifn, tfn abi.Text) abi.Method { + return abi.Method{ + Name_: name, + Mtyp_: typ, + Ifn_: ifn, + Tfn_: tfn, + } +} + +// Named returns a named type. +func Named(pkgPath, name string, underlying *Type, methods []abi.Method) *Type { + tflag := underlying.TFlag + size := typeHdrSize + n := len(methods) + if n > 0 || pkgPath != "" { + size += uncommonTypeHdrSize + uintptr(n)*methodSize + tflag |= abi.TFlagUncommon + } + ptr := AllocU(size) + + ret := (*Type)(ptr) + *ret = *underlying + ret.TFlag = tflag | abi.TFlagNamed + ret.Str_ = name + + xcount := 0 + for _, m := range methods { + if !m.Exported() { + break + } + xcount++ + } + + uncommon := (*abi.UncommonType)(c.Advance(ptr, int(typeHdrSize))) + uncommon.PkgPath_ = pkgPath + uncommon.Mcount = uint16(n) + uncommon.Xcount = uint16(xcount) + uncommon.Moff = uint32(uncommonTypeHdrSize) + + data := (*abi.Method)(c.Advance(ptr, int(typeHdrSize+uncommonTypeHdrSize))) + copy(unsafe.Slice(data, n), methods) + return ret +} + +// Interface returns an interface type. +func Interface(pkgPath string, methods []abi.Imethod) *Type { + ret := &abi.InterfaceType{ + Type: Type{ + Size_: unsafe.Sizeof(eface{}), + Hash: uint32(abi.Interface), // TODO(xsw): hash + Kind_: uint8(abi.Interface), + }, + PkgPath_: pkgPath, + Methods: methods, + } + return &ret.Type +} + +// NewItab returns a new itab. +func NewItab(inter *InterfaceType, typ *Type) *Itab { + n := len(inter.Methods) + size := itabHdrSize + uintptr(n)*pointerSize + ptr := AllocU(size) + + ret := (*Itab)(ptr) + ret.inter = inter + ret._type = typ + ret.hash = typ.Hash + + u := typ.Uncommon() + if u == nil { + ret.fun[0] = 0 + } else { + data := (*uintptr)(c.Advance(ptr, int(itabHdrSize))) + mthds := methods(u, inter.PkgPath_) + for i, m := range inter.Methods { + fn := findMethod(mthds, m) + if fn == nil { + ret.fun[0] = 0 + break + } + *c.Advance(data, i) = uintptr(fn) + } + } + return ret +} + +func findMethod(mthds []abi.Method, im abi.Imethod) abi.Text { + imName := im.Name_ + for _, m := range mthds { + mName := m.Name_ + if mName >= imName { + if mName == imName && m.Mtyp_ == im.Typ_ { + return m.Ifn_ + } + break + } + } + return nil +} + +func methods(u *abi.UncommonType, from string) []abi.Method { + if u.PkgPath_ == from { + return u.Methods() + } + return u.ExportedMethods() +} + +// ----------------------------------------------------------------------------- diff --git a/internal/runtime/z_type.go b/internal/runtime/z_type.go index 403c37b0..aa4431bb 100644 --- a/internal/runtime/z_type.go +++ b/internal/runtime/z_type.go @@ -20,104 +20,29 @@ import ( "unsafe" "github.com/goplus/llgo/internal/abi" - "github.com/goplus/llgo/internal/runtime/c" -) - -type ( - Eface = eface - Iface = iface - Itab = itab ) type Kind = abi.Kind type Type = abi.Type -type FuncType = abi.FuncType -type InterfaceType = abi.InterfaceType - // ----------------------------------------------------------------------------- -// Func returns a function type. -func Func(in, out []*Type, variadic bool) *FuncType { - const ( - funcTypeHdrSize = unsafe.Sizeof(abi.FuncType{}) - pointerSize = unsafe.Sizeof(uintptr(0)) - ) +/* +type Name = abi.Name - n := len(in) + len(out) - ptr := AllocU(funcTypeHdrSize + uintptr(n)*pointerSize) - c.Memset(ptr, 0, funcTypeHdrSize) +// NewName creates a new name. +func NewName(name string, exported bool) Name { + return abi.NewName(name, "", exported, false) +} - ret := (*abi.FuncType)(ptr) - ret.Size_ = pointerSize - ret.Hash = uint32(abi.Func) // TODO(xsw): hash - ret.Kind_ = uint8(abi.Func) - ret.InCount = uint16(len(in)) - ret.OutCount = uint16(len(out)) - if variadic { - ret.OutCount |= 1 << 15 - } - - data := (**Type)(c.Advance(ptr, int(funcTypeHdrSize))) - params := unsafe.Slice(data, n) - copy(params, in) - copy(params[len(in):], out) - return ret -} - -// Imethod returns an interface method. -func Imethod(name string, typ *FuncType, exported bool) abi.Imethod { - n := abi.NewName(name, "", exported, false) - return abi.Imethod{ - Name_: n, - Typ_: typ, - } -} - -// Method returns a method. -func Method(name string, typ *FuncType, fn abi.Text, exported bool) abi.Method { - n := abi.NewName(name, "", exported, false) - return abi.Method{ - Name_: n, - Mtyp_: typ, - Ifn_: fn, - Tfn_: fn, - } -} - -// ----------------------------------------------------------------------------- - -// Named returns a named type. -func Named(name string, typ *Type) *Type { - ret := *typ // TODO(xsw): named type - return &ret -} - -// Interface returns an interface type. -func Interface(pkgPath string) *Type { - // TODO(xsw): pkgPath - // npkg := abi.NewName(pkgPath, "", false, false) - ret := &abi.InterfaceType{ - Type: Type{ - Size_: unsafe.Sizeof(eface{}), - Hash: uint32(abi.Interface), // TODO(xsw): hash - Kind_: uint8(abi.Interface), - }, - //PkgPath: npkg, - Methods: nil, - } - return &ret.Type -} - -// NewItab returns a new itab. -func NewItab(inter *InterfaceType, typ *Type) *Itab { - return &itab{ - inter: inter, - _type: typ, - hash: typ.Hash, - //fun: nil, TODO(xsw) +// NewPkgName creates a package name. +func NewPkgName(pkgPath string) (ret Name) { + if len(pkgPath) > 0 { + ret = abi.NewName(pkgPath, "", false, false) } + return } +*/ // ----------------------------------------------------------------------------- @@ -180,31 +105,32 @@ func basicType(kind abi.Kind) *Type { // ----------------------------------------------------------------------------- // StructField returns a struct field. -func StructField(name string, typ *Type, off uintptr, tag string, exported, embedded bool) abi.StructField { - n := abi.NewName(name, tag, exported, embedded) +func StructField(name string, typ *Type, off uintptr, tag string, embedded bool) abi.StructField { return abi.StructField{ - Name: n, - Typ: typ, - Offset: off, + Name_: name, + Typ: typ, + Offset: off, + Tag_: tag, + Embedded_: embedded, } } // Struct returns a struct type. -func Struct(size uintptr, pkgPath string, fields ...abi.StructField) *Type { - // TODO(xsw): pkgPath - // npkg := abi.NewName(pkgPath, "", false, false) +func Struct(pkgPath string, size uintptr, fields ...abi.StructField) *Type { ret := &abi.StructType{ Type: Type{ Size_: size, Hash: uint32(abi.Struct), // TODO(xsw): hash Kind_: uint8(abi.Struct), }, - // PkgPath: npkg, - Fields: fields, + PkgPath_: pkgPath, + Fields: fields, } return &ret.Type } +// ----------------------------------------------------------------------------- + // Pointer returns a pointer type. func Pointer(elem *Type) *Type { ret := &abi.PtrType{ diff --git a/ssa/expr.go b/ssa/expr.go index 0258755c..5e7b50af 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -41,16 +41,6 @@ func (v Expr) IsNil() bool { return v.Type == nil } -// Do evaluates the delay expression and returns the result. -func (v Expr) Do(b Builder) Expr { // TODO(xsw): can we remove this method? - switch vt := v.Type; vt.kind { - case vkPhisExpr: - e := vt.raw.Type.(*phisExprTy) - return b.aggregateValue(e.Type, e.phis...) - } - return v -} - // ----------------------------------------------------------------------------- type pyVarTy struct { @@ -73,26 +63,6 @@ func pyVarExpr(mod Expr, name string) Expr { // ----------------------------------------------------------------------------- -type phisExprTy struct { - phis []llvm.Value - Type -} - -func (p phisExprTy) Underlying() types.Type { - panic("don't call") -} - -func (p phisExprTy) String() string { - return "phisExpr" -} - -func phisExpr(t Type, phis []llvm.Value) Expr { - tphi := &aType{raw: rawType{&phisExprTy{phis, t}}, kind: vkPhisExpr} - return Expr{Type: tphi} -} - -// ----------------------------------------------------------------------------- - func (p Program) Zero(t Type) Expr { var ret llvm.Value switch u := t.raw.Type.Underlying().(type) { @@ -121,6 +91,8 @@ func (p Program) Zero(t Type) Expr { flds[i] = p.Zero(p.rawType(u.Field(i).Type())).impl } ret = llvm.ConstStruct(flds, false) + case *types.Slice: + ret = p.Zero(p.rtType("Slice")).impl default: log.Panicln("todo:", u) } @@ -221,6 +193,12 @@ func (b Builder) Str(v string) (ret Expr) { return Expr{aggregateValue(b.impl, prog.rtString(), data, size), prog.String()} } +func (b Builder) pkgName(pkgPath string) Expr { + // TODO(xsw): use a global cache + // return b.Call(b.Pkg.rtFunc("NewPkgName"), b.Str(pkgPath)) + return b.Str(pkgPath) +} + // unsafeString(data *byte, size int) string func (b Builder) unsafeString(data, size llvm.Value) Expr { prog := b.Prog @@ -528,14 +506,6 @@ func llvmFields(vals []Expr, t *types.Struct, b Builder) (ret []llvm.Value) { return } -func llvmDelayValues(f func(i int) Expr, n int) []llvm.Value { - ret := make([]llvm.Value, n) - for i := 0; i < n; i++ { - ret[i] = f(i).impl - } - return ret -} - func llvmPredBlocks(preds []BasicBlock) []llvm.BasicBlock { ret := make([]llvm.BasicBlock, len(preds)) for i, v := range preds { @@ -544,60 +514,115 @@ func llvmPredBlocks(preds []BasicBlock) []llvm.BasicBlock { return ret } -// Phi represents a phi node. -type Phi struct { +type aPhi struct { Expr + // phis []llvm.Value } +// Phi represents a phi node. +type Phi = *aPhi + +/* +func (b Builder) newPhi(t Type, phis []llvm.Value) Phi { + ret := b.aggregateValue(t, phis...) + return &aPhi{ret, phis} +} +*/ + // AddIncoming adds incoming values to a phi node. -func (p Phi) AddIncoming(b Builder, preds []BasicBlock, f func(i int) Expr) { +func (p Phi) AddIncoming(b Builder, preds []BasicBlock, f func(i int, blk BasicBlock) Expr) { bs := llvmPredBlocks(preds) - if p.kind != vkPhisExpr { // normal phi node - vs := llvmDelayValues(f, len(preds)) - p.impl.AddIncoming(vs, bs) - return - } - e := p.raw.Type.(*phisExprTy) - phis := e.phis - vals := make([][]llvm.Value, len(phis)) - for iblk, blk := range preds { - last := blk.last.LastInstruction() - b.impl.SetInsertPointBefore(last) - impl := b.impl - val := f(iblk).impl - for i := range phis { - if iblk == 0 { - vals[i] = make([]llvm.Value, len(preds)) + /* + phis := p.phis + if phis != nil { + vals := make([][]llvm.Value, len(phis)) + for iblk, blk := range preds { + val := f(iblk, blk).impl + impl := b.impl + b.SetBlockEx(blk, BeforeLast, false) + for i := range phis { + if iblk == 0 { + vals[i] = make([]llvm.Value, len(preds)) + } + vals[i][iblk] = llvm.CreateExtractValue(impl, val, i) + } } - vals[i][iblk] = llvm.CreateExtractValue(impl, val, i) + for i, phi := range phis { + phi.AddIncoming(vals[i], bs) + } + } else */ + { + vals := make([]llvm.Value, len(preds)) + for iblk, blk := range preds { + vals[iblk] = f(iblk, blk).impl } - } - for i, phi := range phis { - phi.AddIncoming(vals[i], bs) + p.impl.AddIncoming(vals, bs) } } // Phi returns a phi node. func (b Builder) Phi(t Type) Phi { impl := b.impl - switch tund := t.raw.Type.Underlying().(type) { - case *types.Basic: - kind := tund.Kind() - switch kind { - case types.String: - prog := b.Prog - phis := make([]llvm.Value, 2) - phis[0] = llvm.CreatePHI(impl, prog.tyVoidPtr()) - phis[1] = llvm.CreatePHI(impl, prog.tyInt()) - return Phi{phisExpr(t, phis)} + /* + switch tund := t.raw.Type.Underlying().(type) { + case *types.Basic: + kind := tund.Kind() + switch kind { + case types.String: + phis := createStringPhis(impl, make([]llvm.Value, 0, 2), b.Prog) + return b.newPhi(t, phis) + } + case *types.Struct: + phis := createStrucPhis(impl, nil, tund, b.Prog) + return b.newPhi(t, phis) + default: + log.Panicf("todo: %T\n", tund) } - case *types.Struct: - panic("todo") - } + */ phi := llvm.CreatePHI(impl, t.ll) - return Phi{Expr{phi, t}} + return &aPhi{Expr{phi, t}} //, nil} } +/* +func createStringPhis(b llvm.Builder, phis []llvm.Value, prog Program) []llvm.Value { + phis = append(phis, llvm.CreatePHI(b, prog.tyVoidPtr())) + return append(phis, llvm.CreatePHI(b, prog.tyInt())) +} + +func createStrucPhis(b llvm.Builder, phis []llvm.Value, t *types.Struct, prog Program) []llvm.Value { + n := t.NumFields() + if phis == nil { + phis = make([]llvm.Value, 0, n) + } + for i := 0; i < n; i++ { + fld := t.Field(i) + switch tfld := fld.Type().Underlying().(type) { + case *types.Basic: + kind := tfld.Kind() + switch kind { + case types.String: + phis = createStringPhis(b, phis, prog) + default: + phis = createBasicPhi(b, phis, tfld, prog) + } + case *types.Pointer: + phis = createBasicPhi(b, phis, tfld, prog) + case *types.Struct: + phis = createStrucPhis(b, phis, tfld, prog) + default: + panic("todo") + } + } + return phis +} + +func createBasicPhi(b llvm.Builder, phis []llvm.Value, t types.Type, prog Program) []llvm.Value { + tll := prog.rawType(t).ll + phi := llvm.CreatePHI(b, tll) + return append(phis, phi) +} +*/ + // ----------------------------------------------------------------------------- // Advance returns the pointer ptr advanced by offset. diff --git a/ssa/interface.go b/ssa/interface.go index 51d8ab37..217d231a 100644 --- a/ssa/interface.go +++ b/ssa/interface.go @@ -59,10 +59,19 @@ func (b Builder) abiTypeOf(t types.Type) Expr { panic("todo") } +// func Named(pkgPath, name string, underlying *Type, methods []abi.Method) func (b Builder) abiNamedOf(t *types.Named) Expr { under := b.abiTypeOf(t.Underlying()) name := NameOf(t) - return b.Call(b.Pkg.rtFunc("Named"), b.Str(name), under) + + prog := b.Prog + pkg := b.Pkg + pkgPath := b.pkgName(pkg.Path()) + fn := pkg.rtFunc("Named") + tSlice := lastParamType(prog, fn) + // TODO(xsw): methods + methods := prog.Zero(tSlice) + return b.Call(fn, pkgPath, b.Str(name), under, methods) } func (b Builder) abiPointerOf(t *types.Pointer) Expr { @@ -70,7 +79,7 @@ func (b Builder) abiPointerOf(t *types.Pointer) Expr { return b.Call(b.Pkg.rtFunc("Pointer"), elem) } -// func Struct(size uintptr, pkgPath string, fields []abi.StructField) *abi.Type +// func Struct(pkgPath string, size uintptr, fields []abi.StructField) func (b Builder) abiStructOf(t *types.Struct) Expr { pkg := b.Pkg prog := b.Prog @@ -84,20 +93,24 @@ func (b Builder) abiStructOf(t *types.Struct) Expr { off := uintptr(prog.OffsetOf(typ, i)) flds[i] = b.structField(sfAbi, prog, f, off, t.Tag(i)) } - pkgPath := b.Str(pkg.Path()) - params := strucAbi.raw.Type.(*types.Signature).Params() - tSlice := prog.rawType(params.At(params.Len() - 1).Type().(*types.Slice)) + pkgPath := b.pkgName(pkg.Path()) + tSlice := lastParamType(prog, strucAbi) fldSlice := b.SliceLit(tSlice, flds...) - return b.Call(strucAbi, pkgPath, fldSlice) + size := prog.IntVal(prog.SizeOf(typ), prog.Uintptr()) + return b.Call(strucAbi, pkgPath, size, fldSlice) } -// func StructField(name string, typ *abi.Type, off uintptr, tag string, exported, embedded bool) abi.StructField +func lastParamType(prog Program, fn Expr) Type { + params := fn.raw.Type.(*types.Signature).Params() + return prog.rawType(params.At(params.Len() - 1).Type()) +} + +// func StructField(name string, typ *abi.Type, off uintptr, tag string, embedded bool) abi.StructField func (b Builder) structField(sfAbi Expr, prog Program, f *types.Var, offset uintptr, tag string) Expr { name := b.Str(f.Name()) typ := b.abiType(f.Type()) - exported := prog.Val(f.Exported()) embedded := prog.Val(f.Embedded()) - return b.Call(sfAbi, name, typ, prog.Val(offset), b.Str(tag), exported, embedded) + return b.Call(sfAbi, name, typ, prog.Val(offset), b.Str(tag), embedded) } // abiType returns the abi type of the specified type. @@ -296,21 +309,20 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) Expr { eq := b.BinOp(token.EQL, tx, tabi) if commaOk { prog := b.Prog - t := prog.Tuple(assertedTyp, prog.Bool()) + t := prog.Struct(assertedTyp, prog.Bool()) blks := b.Func.MakeBlocks(3) b.If(eq, blks[0], blks[1]) b.SetBlockEx(blks[2], AtEnd, false) phi := b.Phi(t) - phi.AddIncoming(b, blks[:2], func(i int) Expr { + phi.AddIncoming(b, blks[:2], func(i int, blk BasicBlock) Expr { + b.SetBlockEx(blk, AtEnd, false) if i == 0 { - b.SetBlockEx(blks[0], AtEnd, false) val := b.valFromData(assertedTyp, b.faceData(x.impl)) valTrue := aggregateValue(b.impl, t.ll, val.impl, prog.BoolVal(true).impl) b.Jump(blks[2]) return Expr{valTrue, t} } - b.SetBlockEx(blks[1], AtEnd, false) zero := prog.Zero(assertedTyp) valFalse := aggregateValue(b.impl, t.ll, zero.impl, prog.BoolVal(false).impl) b.Jump(blks[2]) diff --git a/ssa/package.go b/ssa/package.go index 6eb26db1..5df247db 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -19,6 +19,7 @@ package ssa import ( "go/token" "go/types" + "strconv" "unsafe" "github.com/goplus/llgo/ssa/abi" @@ -296,13 +297,13 @@ func (p Program) NewPackage(name, pkgPath string) Package { return ret } -// Tuple returns a tuple type. -func (p Program) Tuple(typs ...Type) Type { +// Struct returns a struct type. +func (p Program) Struct(typs ...Type) Type { els := make([]*types.Var, len(typs)) for i, t := range typs { - els[i] = types.NewParam(token.NoPos, nil, "", t.raw.Type) + els[i] = types.NewParam(token.NoPos, nil, "_llgo_f"+strconv.Itoa(i), t.raw.Type) } - return p.rawType(types.NewTuple(els...)) + return p.rawType(types.NewStruct(els, nil)) } /* diff --git a/ssa/ssa_test.go b/ssa/ssa_test.go index 3e23e756..b6123bd3 100644 --- a/ssa/ssa_test.go +++ b/ssa/ssa_test.go @@ -109,9 +109,7 @@ func TestCvtType(t *testing.T) { } func TestUserdefExpr(t *testing.T) { - b := &phisExprTy{} c := &pyVarTy{} - _ = b.String() _ = c.String() test := func(a types.Type) { defer func() { @@ -121,7 +119,6 @@ func TestUserdefExpr(t *testing.T) { }() a.Underlying() } - test(b) test(c) } diff --git a/ssa/stmt_builder.go b/ssa/stmt_builder.go index 8e2507de..178d6f3e 100644 --- a/ssa/stmt_builder.go +++ b/ssa/stmt_builder.go @@ -80,6 +80,7 @@ type InsertPoint int const ( AtEnd InsertPoint = iota AtStart + BeforeLast afterInit ) @@ -93,6 +94,8 @@ func (b Builder) SetBlockEx(blk BasicBlock, pos InsertPoint, setBlk bool) Builde b.impl.SetInsertPointAtEnd(blk.last) case AtStart: b.impl.SetInsertPointBefore(blk.first.FirstInstruction()) + case BeforeLast: + b.impl.SetInsertPointBefore(blk.last.LastInstruction()) case afterInit: b.impl.SetInsertPointBefore(instrAfterInit(blk.first)) default: diff --git a/ssa/type.go b/ssa/type.go index ece67e4c..2b1f3608 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -53,7 +53,6 @@ const ( vkEface vkIface vkStruct - vkPhisExpr = -1 ) // -----------------------------------------------------------------------------