Merge pull request #235 from xushiwei/q

runtime: iface; llgo/ssa: phi refactor; remove abi.Name
This commit is contained in:
xushiwei
2024-05-26 18:04:03 +08:00
committed by GitHub
20 changed files with 582 additions and 368 deletions

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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")

View File

@@ -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) {

View File

@@ -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

View File

@@ -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])

Binary file not shown.

View File

@@ -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]}
}
*/
// -----------------------------------------------------------------------------

View File

@@ -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

Binary file not shown.

View File

@@ -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,
}
}
*/

View File

@@ -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

205
internal/runtime/z_face.go Normal file
View File

@@ -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()
}
// -----------------------------------------------------------------------------

View File

@@ -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{

View File

@@ -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.

View File

@@ -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])

View File

@@ -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))
}
/*

View File

@@ -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)
}

View File

@@ -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:

View File

@@ -53,7 +53,6 @@ const (
vkEface
vkIface
vkStruct
vkPhisExpr = -1
)
// -----------------------------------------------------------------------------