From 3435b6c4a44146a0733dcdba269de7906f913798 Mon Sep 17 00:00:00 2001 From: visualfc Date: Fri, 9 Aug 2024 22:23:48 +0800 Subject: [PATCH] cl: makeInterface check instance named --- cl/_testgo/tpindex/out.ll | 2 +- cl/_testgo/tprecur/out.ll | 4 +- cl/_testgo/tptypes/out.ll | 48 ++-- cl/_testrt/tpabi/in.go | 38 +++ cl/_testrt/tpabi/out.ll | 477 ++++++++++++++++++++++++++++++++++++++ cl/compile.go | 22 +- cl/import.go | 17 +- cl/instr.go | 2 +- ssa/abi/abi.go | 22 +- ssa/abitype.go | 5 +- ssa/decl.go | 7 +- ssa/type.go | 32 +-- 12 files changed, 618 insertions(+), 58 deletions(-) create mode 100644 cl/_testrt/tpabi/in.go create mode 100644 cl/_testrt/tpabi/out.ll diff --git a/cl/_testgo/tpindex/out.ll b/cl/_testgo/tpindex/out.ll index 058b0558..2c69dd98 100644 --- a/cl/_testgo/tpindex/out.ll +++ b/cl/_testgo/tpindex/out.ll @@ -58,7 +58,7 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"() declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) -define i64 @"main.index[int]"(%"github.com/goplus/llgo/internal/runtime.Slice" %0, i64 %1) { +define linkonce i64 @"main.index[int]"(%"github.com/goplus/llgo/internal/runtime.Slice" %0, i64 %1) { _llgo_0: %2 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1 br label %_llgo_1 diff --git a/cl/_testgo/tprecur/out.ll b/cl/_testgo/tprecur/out.ll index 6cd1f48f..f721b0e0 100644 --- a/cl/_testgo/tprecur/out.ll +++ b/cl/_testgo/tprecur/out.ll @@ -66,7 +66,7 @@ _llgo_2: ; preds = %_llgo_0 declare void @"github.com/goplus/llgo/internal/runtime.init"() -define i64 @"main.recur1[main.T]"(i64 %0) { +define linkonce i64 @"main.recur1[main.T]"(i64 %0) { _llgo_0: %1 = icmp eq i64 %0, 0 br i1 %1, label %_llgo_1, label %_llgo_3 @@ -106,7 +106,7 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64) declare void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface") -define i64 @"main.recur2[main.T]"(i64 %0) { +define linkonce i64 @"main.recur2[main.T]"(i64 %0) { _llgo_0: %1 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.MakeSlice"(i64 %0, i64 %0, i64 8) %2 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %1, 1 diff --git a/cl/_testgo/tptypes/out.ll b/cl/_testgo/tptypes/out.ll index 3c2c9460..1d75c083 100644 --- a/cl/_testgo/tptypes/out.ll +++ b/cl/_testgo/tptypes/out.ll @@ -5,8 +5,8 @@ source_filename = "main" %"main.Data[string]" = type { %"github.com/goplus/llgo/internal/runtime.String" } %"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } %"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 } -%"main.Slice[[]int, int]" = type { %"github.com/goplus/llgo/internal/runtime.Slice" } -%"main.Slice[[]string, string]" = type { %"github.com/goplus/llgo/internal/runtime.Slice" } +%"main.Slice[[]int,int]" = type { %"github.com/goplus/llgo/internal/runtime.Slice" } +%"main.Slice[[]string,string]" = type { %"github.com/goplus/llgo/internal/runtime.Slice" } @"main.init$guard" = global i1 false, align 1 @__llgo_argc = global i32 0, align 4 @@ -90,7 +90,7 @@ _llgo_0: %36 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %33, i32 0, i32 2 store i64 1, ptr %36, align 4 %37 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %33, align 8 - %38 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice).Append[[]int, int]"(ptr %30, %"github.com/goplus/llgo/internal/runtime.Slice" %37) + %38 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice[[]int,int]).Append"(ptr %30, %"github.com/goplus/llgo/internal/runtime.Slice" %37) %39 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 24) %40 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 16) %41 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %40, i64 0 @@ -109,7 +109,7 @@ _llgo_0: %49 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %46, i32 0, i32 2 store i64 1, ptr %49, align 4 %50 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %46, align 8 - %51 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice).Append[[]string, string]"(ptr %39, %"github.com/goplus/llgo/internal/runtime.Slice" %50) + %51 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice[[]string,string]).Append"(ptr %39, %"github.com/goplus/llgo/internal/runtime.Slice" %50) %52 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 24) %53 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32) %54 = getelementptr inbounds i64, ptr %53, i64 0 @@ -128,7 +128,7 @@ _llgo_0: %61 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %58, i32 0, i32 2 store i64 4, ptr %61, align 4 %62 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %58, align 8 - %63 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice).Append[[]int, int]"(ptr %52, %"github.com/goplus/llgo/internal/runtime.Slice" %62) + %63 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice[[]int,int]).Append"(ptr %52, %"github.com/goplus/llgo/internal/runtime.Slice" %62) %64 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32) %65 = getelementptr inbounds i64, ptr %64, i64 0 store i64 1, ptr %65, align 4 @@ -146,10 +146,10 @@ _llgo_0: %72 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %69, i32 0, i32 2 store i64 4, ptr %72, align 4 %73 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %69, align 8 - %74 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice).Append2[[]int, int]"(ptr %52, %"github.com/goplus/llgo/internal/runtime.Slice" %73) - %75 = getelementptr inbounds %"main.Slice[[]int, int]", ptr %30, i32 0, i32 0 + %74 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice[[]int,int]).Append2"(ptr %52, %"github.com/goplus/llgo/internal/runtime.Slice" %73) + %75 = getelementptr inbounds %"main.Slice[[]int,int]", ptr %30, i32 0, i32 0 %76 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %75, align 8 - %77 = getelementptr inbounds %"main.Slice[[]int, int]", ptr %30, i32 0, i32 0 + %77 = getelementptr inbounds %"main.Slice[[]int,int]", ptr %30, i32 0, i32 0 %78 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %77, align 8 %79 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %78, 0 %80 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %78, 1 @@ -161,9 +161,9 @@ _llgo_0: call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %83) call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) - %84 = getelementptr inbounds %"main.Slice[[]string, string]", ptr %39, i32 0, i32 0 + %84 = getelementptr inbounds %"main.Slice[[]string,string]", ptr %39, i32 0, i32 0 %85 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %84, align 8 - %86 = getelementptr inbounds %"main.Slice[[]string, string]", ptr %39, i32 0, i32 0 + %86 = getelementptr inbounds %"main.Slice[[]string,string]", ptr %39, i32 0, i32 0 %87 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %86, align 8 %88 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %87, 0 %89 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %87, 1 @@ -175,9 +175,9 @@ _llgo_0: call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %92) call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) - %93 = getelementptr inbounds %"main.Slice[[]int, int]", ptr %52, i32 0, i32 0 + %93 = getelementptr inbounds %"main.Slice[[]int,int]", ptr %52, i32 0, i32 0 %94 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %93, align 8 - %95 = getelementptr inbounds %"main.Slice[[]int, int]", ptr %52, i32 0, i32 0 + %95 = getelementptr inbounds %"main.Slice[[]int,int]", ptr %52, i32 0, i32 0 %96 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %95, align 8 %97 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %96, 0 %98 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %96, 1 @@ -204,44 +204,44 @@ declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) -define %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice).Append[[]int, int]"(ptr %0, %"github.com/goplus/llgo/internal/runtime.Slice" %1) { +define linkonce %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice[[]int,int]).Append"(ptr %0, %"github.com/goplus/llgo/internal/runtime.Slice" %1) { _llgo_0: - %2 = getelementptr inbounds %"main.Slice[[]int, int]", ptr %0, i32 0, i32 0 + %2 = getelementptr inbounds %"main.Slice[[]int,int]", ptr %0, i32 0, i32 0 %3 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %2, align 8 %4 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %1, 0 %5 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %1, 1 %6 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.SliceAppend"(%"github.com/goplus/llgo/internal/runtime.Slice" %3, ptr %4, i64 %5, i64 8) - %7 = getelementptr inbounds %"main.Slice[[]int, int]", ptr %0, i32 0, i32 0 + %7 = getelementptr inbounds %"main.Slice[[]int,int]", ptr %0, i32 0, i32 0 store %"github.com/goplus/llgo/internal/runtime.Slice" %6, ptr %7, align 8 - %8 = getelementptr inbounds %"main.Slice[[]int, int]", ptr %0, i32 0, i32 0 + %8 = getelementptr inbounds %"main.Slice[[]int,int]", ptr %0, i32 0, i32 0 %9 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %8, align 8 ret %"github.com/goplus/llgo/internal/runtime.Slice" %9 } -define %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice).Append[[]string, string]"(ptr %0, %"github.com/goplus/llgo/internal/runtime.Slice" %1) { +define linkonce %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice[[]string,string]).Append"(ptr %0, %"github.com/goplus/llgo/internal/runtime.Slice" %1) { _llgo_0: - %2 = getelementptr inbounds %"main.Slice[[]string, string]", ptr %0, i32 0, i32 0 + %2 = getelementptr inbounds %"main.Slice[[]string,string]", ptr %0, i32 0, i32 0 %3 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %2, align 8 %4 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %1, 0 %5 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %1, 1 %6 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.SliceAppend"(%"github.com/goplus/llgo/internal/runtime.Slice" %3, ptr %4, i64 %5, i64 16) - %7 = getelementptr inbounds %"main.Slice[[]string, string]", ptr %0, i32 0, i32 0 + %7 = getelementptr inbounds %"main.Slice[[]string,string]", ptr %0, i32 0, i32 0 store %"github.com/goplus/llgo/internal/runtime.Slice" %6, ptr %7, align 8 - %8 = getelementptr inbounds %"main.Slice[[]string, string]", ptr %0, i32 0, i32 0 + %8 = getelementptr inbounds %"main.Slice[[]string,string]", ptr %0, i32 0, i32 0 %9 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %8, align 8 ret %"github.com/goplus/llgo/internal/runtime.Slice" %9 } -define %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice).Append2[[]int, int]"(ptr %0, %"github.com/goplus/llgo/internal/runtime.Slice" %1) { +define linkonce %"github.com/goplus/llgo/internal/runtime.Slice" @"main.(*Slice[[]int,int]).Append2"(ptr %0, %"github.com/goplus/llgo/internal/runtime.Slice" %1) { _llgo_0: - %2 = getelementptr inbounds %"main.Slice[[]int, int]", ptr %0, i32 0, i32 0 + %2 = getelementptr inbounds %"main.Slice[[]int,int]", ptr %0, i32 0, i32 0 %3 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %2, align 8 %4 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %1, 0 %5 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %1, 1 %6 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.SliceAppend"(%"github.com/goplus/llgo/internal/runtime.Slice" %3, ptr %4, i64 %5, i64 8) - %7 = getelementptr inbounds %"main.Slice[[]int, int]", ptr %0, i32 0, i32 0 + %7 = getelementptr inbounds %"main.Slice[[]int,int]", ptr %0, i32 0, i32 0 store %"github.com/goplus/llgo/internal/runtime.Slice" %6, ptr %7, align 8 - %8 = getelementptr inbounds %"main.Slice[[]int, int]", ptr %0, i32 0, i32 0 + %8 = getelementptr inbounds %"main.Slice[[]int,int]", ptr %0, i32 0, i32 0 %9 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %8, align 8 ret %"github.com/goplus/llgo/internal/runtime.Slice" %9 } diff --git a/cl/_testrt/tpabi/in.go b/cl/_testrt/tpabi/in.go new file mode 100644 index 00000000..aa15799b --- /dev/null +++ b/cl/_testrt/tpabi/in.go @@ -0,0 +1,38 @@ +package main + +import "github.com/goplus/llgo/c" + +type T[M, N any] struct { + m M + n N +} + +func (t *T[M, N]) Demo() { + println(t.m, t.n) +} + +func (t T[M, N]) Info() { + println(t.m, t.n) +} + +type I interface { + Demo() +} + +type K[N any] [4]N + +//llgo:link (*K).Advance llgo.advance +func (t *K[N]) Advance(n int) *K[N] { + return nil +} + +func main() { + var a any = T[string, int]{"a", 1} + println(a.(T[string, int]).m) + var i I = &T[string, int]{"hello", 100} + i.Demo() + + k := &K[int]{1, 2, 3, 4} + println(c.Advance(k, 1)) + println(k.Advance(1)) +} diff --git a/cl/_testrt/tpabi/out.ll b/cl/_testrt/tpabi/out.ll new file mode 100644 index 00000000..aaf414b2 --- /dev/null +++ b/cl/_testrt/tpabi/out.ll @@ -0,0 +1,477 @@ +; ModuleID = 'main' +source_filename = "main" + +%"main.T[string,int]" = type { %"github.com/goplus/llgo/internal/runtime.String", i64 } +%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } +%"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr } +%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, 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 } +%"github.com/goplus/llgo/internal/abi.Method" = type { %"github.com/goplus/llgo/internal/runtime.String", ptr, ptr, ptr } +%"github.com/goplus/llgo/internal/abi.Imethod" = type { %"github.com/goplus/llgo/internal/runtime.String", ptr } + +@"main.init$guard" = global i1 false, align 1 +@__llgo_argc = global i32 0, align 4 +@__llgo_argv = global ptr null, align 8 +@0 = private unnamed_addr constant [1 x i8] c"a", align 1 +@"_llgo_main.T[string,int]" = linkonce global ptr null, align 8 +@"main.struct$A2OTYqQyUOqOQ-i_F5iXeAKWtxeWGEuyeN7HCfULCDk" = global ptr null, align 8 +@1 = private unnamed_addr constant [1 x i8] c"m", align 1 +@2 = private unnamed_addr constant [1 x i8] c"n", align 1 +@3 = private unnamed_addr constant [4 x i8] c"main", align 1 +@4 = private unnamed_addr constant [4 x i8] c"Demo", align 1 +@"_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac" = linkonce global ptr null, align 8 +@5 = private unnamed_addr constant [4 x i8] c"Info", align 1 +@6 = private unnamed_addr constant [13 x i8] c"T[string,int]", align 1 +@7 = private unnamed_addr constant [21 x i8] c"type assertion failed", align 1 +@_llgo_string = linkonce global ptr null, align 8 +@8 = private unnamed_addr constant [5 x i8] c"hello", align 1 +@"*_llgo_main.T[string,int]" = linkonce global ptr null, align 8 +@"_llgo_iface$BP0p_lUsEd-IbbtJVukGmgrdQkqzcoYzSiwgUvgFvUs" = linkonce global ptr null, align 8 + +define void @main.init() { +_llgo_0: + %0 = load i1, ptr @"main.init$guard", align 1 + br i1 %0, label %_llgo_2, label %_llgo_1 + +_llgo_1: ; preds = %_llgo_0 + store i1 true, ptr @"main.init$guard", align 1 + call void @"main.init$after"() + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +define i32 @main(i32 %0, ptr %1) { +_llgo_0: + store i32 %0, ptr @__llgo_argc, align 4 + store ptr %1, ptr @__llgo_argv, align 8 + call void @"github.com/goplus/llgo/internal/runtime.init"() + call void @main.init() + %2 = alloca %"main.T[string,int]", align 8 + %3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 24) + %4 = getelementptr inbounds %"main.T[string,int]", ptr %3, i32 0, i32 0 + %5 = getelementptr inbounds %"main.T[string,int]", ptr %3, i32 0, i32 1 + %6 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %6, i32 0, i32 0 + store ptr @0, ptr %7, align 8 + %8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %6, i32 0, i32 1 + store i64 1, ptr %8, align 4 + %9 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %6, align 8 + store %"github.com/goplus/llgo/internal/runtime.String" %9, ptr %4, align 8 + store i64 1, ptr %5, align 4 + %10 = load %"main.T[string,int]", ptr %3, align 8 + %11 = load ptr, ptr @"_llgo_main.T[string,int]", align 8 + %12 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 24) + store %"main.T[string,int]" %10, ptr %12, align 8 + %13 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8 + %14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %13, i32 0, i32 0 + store ptr %11, ptr %14, align 8 + %15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %13, i32 0, i32 1 + store ptr %12, ptr %15, align 8 + %16 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %13, align 8 + %17 = extractvalue %"github.com/goplus/llgo/internal/runtime.eface" %16, 0 + %18 = load ptr, ptr @"_llgo_main.T[string,int]", align 8 + %19 = icmp eq ptr %17, %18 + br i1 %19, label %_llgo_1, label %_llgo_2 + +_llgo_1: ; preds = %_llgo_0 + %20 = extractvalue %"github.com/goplus/llgo/internal/runtime.eface" %16, 1 + %21 = load %"main.T[string,int]", ptr %20, align 8 + %22 = extractvalue %"main.T[string,int]" %21, 0 + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %22) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %23 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 24) + %24 = getelementptr inbounds %"main.T[string,int]", ptr %23, i32 0, i32 0 + %25 = getelementptr inbounds %"main.T[string,int]", ptr %23, i32 0, i32 1 + %26 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %26, i32 0, i32 0 + store ptr @8, ptr %27, align 8 + %28 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %26, i32 0, i32 1 + store i64 5, ptr %28, align 4 + %29 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %26, align 8 + store %"github.com/goplus/llgo/internal/runtime.String" %29, ptr %24, align 8 + store i64 100, ptr %25, align 4 + %30 = load ptr, ptr @"*_llgo_main.T[string,int]", align 8 + %31 = load ptr, ptr @"_llgo_iface$BP0p_lUsEd-IbbtJVukGmgrdQkqzcoYzSiwgUvgFvUs", align 8 + %32 = call ptr @"github.com/goplus/llgo/internal/runtime.NewItab"(ptr %31, ptr %30) + %33 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8 + %34 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %33, i32 0, i32 0 + store ptr %32, ptr %34, align 8 + %35 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %33, i32 0, i32 1 + store ptr %23, ptr %35, align 8 + %36 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %33, align 8 + %37 = call ptr @"github.com/goplus/llgo/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/internal/runtime.iface" %36) + %38 = extractvalue %"github.com/goplus/llgo/internal/runtime.iface" %36, 0 + %39 = getelementptr ptr, ptr %38, i64 3 + %40 = load ptr, ptr %39, align 8 + %41 = alloca { ptr, ptr }, align 8 + %42 = getelementptr inbounds { ptr, ptr }, ptr %41, i32 0, i32 0 + store ptr %40, ptr %42, align 8 + %43 = getelementptr inbounds { ptr, ptr }, ptr %41, i32 0, i32 1 + store ptr %37, ptr %43, align 8 + %44 = load { ptr, ptr }, ptr %41, align 8 + %45 = extractvalue { ptr, ptr } %44, 1 + %46 = extractvalue { ptr, ptr } %44, 0 + call void %46(ptr %45) + %47 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32) + %48 = getelementptr inbounds i64, ptr %47, i64 0 + %49 = getelementptr inbounds i64, ptr %47, i64 1 + %50 = getelementptr inbounds i64, ptr %47, i64 2 + %51 = getelementptr inbounds i64, ptr %47, i64 3 + store i64 1, ptr %48, align 4 + store i64 2, ptr %49, align 4 + store i64 3, ptr %50, align 4 + store i64 4, ptr %51, align 4 + %52 = getelementptr [4 x i64], ptr %47, i64 1 + call void @"github.com/goplus/llgo/internal/runtime.PrintPointer"(ptr %52) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %53 = getelementptr [4 x i64], ptr %47, i64 1 + call void @"github.com/goplus/llgo/internal/runtime.PrintPointer"(ptr %53) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + ret i32 0 + +_llgo_2: ; preds = %_llgo_0 + %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 @7, ptr %55, align 8 + %56 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %54, i32 0, i32 1 + store i64 21, ptr %56, align 4 + %57 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %54, align 8 + %58 = load ptr, ptr @_llgo_string, align 8 + %59 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16) + store %"github.com/goplus/llgo/internal/runtime.String" %57, ptr %59, align 8 + %60 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8 + %61 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %60, i32 0, i32 0 + store ptr %58, ptr %61, align 8 + %62 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %60, i32 0, i32 1 + store ptr %59, ptr %62, align 8 + %63 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %60, align 8 + call void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface" %63) + unreachable +} + +declare void @"github.com/goplus/llgo/internal/runtime.init"() + +declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64) + +define linkonce void @"main.T[string,int].Info"(%"main.T[string,int]" %0) { +_llgo_0: + %1 = alloca %"main.T[string,int]", align 8 + %2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 24) + store %"main.T[string,int]" %0, ptr %2, align 8 + %3 = getelementptr inbounds %"main.T[string,int]", ptr %2, i32 0, i32 0 + %4 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %3, align 8 + %5 = getelementptr inbounds %"main.T[string,int]", ptr %2, i32 0, i32 1 + %6 = load i64, ptr %5, align 4 + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %4) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %6) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + ret void +} + +define linkonce void @"main.(*T[string,int]).Demo"(ptr %0) { +_llgo_0: + %1 = getelementptr inbounds %"main.T[string,int]", ptr %0, i32 0, i32 0 + %2 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %1, align 8 + %3 = getelementptr inbounds %"main.T[string,int]", ptr %0, i32 0, i32 1 + %4 = load i64, ptr %3, align 4 + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %2) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %4) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + ret void +} + +define void @"main.(*T[string,int]).Info"(ptr %0) { +_llgo_0: + %1 = load %"main.T[string,int]", ptr %0, align 8 + call void @"main.T[string,int].Info"(%"main.T[string,int]" %1) + ret void +} + +define void @"main.init$after"() { +_llgo_0: + %0 = call ptr @"github.com/goplus/llgo/internal/runtime.NewNamed"(i64 25, i64 24, i64 1, i64 2) + %1 = load ptr, ptr @"_llgo_main.T[string,int]", align 8 + %2 = icmp eq ptr %1, null + br i1 %2, label %_llgo_1, label %_llgo_2 + +_llgo_1: ; preds = %_llgo_0 + store ptr %0, ptr @"_llgo_main.T[string,int]", align 8 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + %3 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 0 + store ptr @1, ptr %4, align 8 + %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1 + store i64 1, ptr %5, align 4 + %6 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %3, align 8 + %7 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %7, i32 0, i32 0 + store ptr null, ptr %8, align 8 + %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 ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24) + %12 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %6, ptr %11, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %10, i1 false) + %13 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %13, i32 0, i32 0 + store ptr @2, ptr %14, align 8 + %15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %13, i32 0, i32 1 + store i64 1, ptr %15, align 4 + %16 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %13, align 8 + %17 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %18 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %17, i32 0, i32 0 + store ptr null, ptr %18, align 8 + %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 ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 34) + %22 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %16, ptr %21, i64 16, %"github.com/goplus/llgo/internal/runtime.String" %20, i1 false) + %23 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %24 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %23, i32 0, i32 0 + store ptr @3, ptr %24, align 8 + %25 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %23, i32 0, i32 1 + store i64 4, ptr %25, align 4 + %26 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %23, align 8 + %27 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 112) + %28 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %27, i64 0 + store %"github.com/goplus/llgo/internal/abi.StructField" %12, ptr %28, align 8 + %29 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %27, i64 1 + store %"github.com/goplus/llgo/internal/abi.StructField" %22, ptr %29, align 8 + %30 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %31 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %30, i32 0, i32 0 + store ptr %27, ptr %31, align 8 + %32 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %30, i32 0, i32 1 + store i64 2, ptr %32, align 4 + %33 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %30, i32 0, i32 2 + store i64 2, ptr %33, align 4 + %34 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %30, align 8 + %35 = call ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String" %26, i64 24, %"github.com/goplus/llgo/internal/runtime.Slice" %34) + store ptr %35, ptr @"main.struct$A2OTYqQyUOqOQ-i_F5iXeAKWtxeWGEuyeN7HCfULCDk", align 8 + %36 = load ptr, ptr @"main.struct$A2OTYqQyUOqOQ-i_F5iXeAKWtxeWGEuyeN7HCfULCDk", align 8 + br i1 %2, label %_llgo_3, label %_llgo_4 + +_llgo_3: ; preds = %_llgo_2 + %37 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %38 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %37, i32 0, i32 0 + store ptr @4, ptr %38, align 8 + %39 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %37, i32 0, i32 1 + store i64 4, ptr %39, align 4 + %40 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %37, align 8 + %41 = load ptr, ptr @"_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac", align 8 + %42 = icmp eq ptr %41, null + br i1 %42, label %_llgo_5, label %_llgo_6 + +_llgo_4: ; preds = %_llgo_6, %_llgo_2 + %43 = load ptr, ptr @_llgo_string, align 8 + %44 = icmp eq ptr %43, null + br i1 %44, label %_llgo_7, label %_llgo_8 + +_llgo_5: ; preds = %_llgo_3 + %45 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 0) + %46 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %47 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %46, i32 0, i32 0 + store ptr %45, ptr %47, align 8 + %48 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %46, i32 0, i32 1 + store i64 0, ptr %48, align 4 + %49 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %46, i32 0, i32 2 + store i64 0, ptr %49, align 4 + %50 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %46, align 8 + %51 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 0) + %52 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %53 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %52, i32 0, i32 0 + store ptr %51, ptr %53, align 8 + %54 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %52, i32 0, i32 1 + store i64 0, ptr %54, align 4 + %55 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %52, i32 0, i32 2 + store i64 0, ptr %55, align 4 + %56 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %52, align 8 + %57 = call ptr @"github.com/goplus/llgo/internal/runtime.Func"(%"github.com/goplus/llgo/internal/runtime.Slice" %50, %"github.com/goplus/llgo/internal/runtime.Slice" %56, i1 false) + call void @"github.com/goplus/llgo/internal/runtime.SetDirectIface"(ptr %57) + store ptr %57, ptr @"_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac", align 8 + br label %_llgo_6 + +_llgo_6: ; preds = %_llgo_5, %_llgo_3 + %58 = load ptr, ptr @"_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac", align 8 + %59 = alloca %"github.com/goplus/llgo/internal/abi.Method", align 8 + %60 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Method", ptr %59, i32 0, i32 0 + store %"github.com/goplus/llgo/internal/runtime.String" %40, ptr %60, align 8 + %61 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Method", ptr %59, i32 0, i32 1 + store ptr %58, ptr %61, align 8 + %62 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Method", ptr %59, i32 0, i32 2 + store ptr @"main.(*T[string,int]).Demo", ptr %62, align 8 + %63 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Method", ptr %59, i32 0, i32 3 + store ptr @"main.(*T[string,int]).Demo", ptr %63, align 8 + %64 = load %"github.com/goplus/llgo/internal/abi.Method", ptr %59, align 8 + %65 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %66 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %65, i32 0, i32 0 + store ptr @5, ptr %66, align 8 + %67 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %65, i32 0, i32 1 + store i64 4, ptr %67, align 4 + %68 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %65, align 8 + %69 = load ptr, ptr @"_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac", align 8 + %70 = alloca %"github.com/goplus/llgo/internal/abi.Method", align 8 + %71 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Method", ptr %70, i32 0, i32 0 + store %"github.com/goplus/llgo/internal/runtime.String" %68, ptr %71, align 8 + %72 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Method", ptr %70, i32 0, i32 1 + store ptr %69, ptr %72, align 8 + %73 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Method", ptr %70, i32 0, i32 2 + store ptr @"main.(*T[string,int]).Info", ptr %73, align 8 + %74 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Method", ptr %70, i32 0, i32 3 + store ptr @"main.(*T[string,int]).Info", ptr %74, align 8 + %75 = load %"github.com/goplus/llgo/internal/abi.Method", ptr %70, align 8 + %76 = alloca %"github.com/goplus/llgo/internal/abi.Method", align 8 + %77 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Method", ptr %76, i32 0, i32 0 + store %"github.com/goplus/llgo/internal/runtime.String" %68, ptr %77, align 8 + %78 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Method", ptr %76, i32 0, i32 1 + store ptr %69, ptr %78, align 8 + %79 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Method", ptr %76, i32 0, i32 2 + store ptr @"main.(*T[string,int]).Info", ptr %79, align 8 + %80 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Method", ptr %76, i32 0, i32 3 + store ptr @"main.T[string,int].Info", ptr %80, align 8 + %81 = load %"github.com/goplus/llgo/internal/abi.Method", ptr %76, align 8 + %82 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 40) + %83 = getelementptr %"github.com/goplus/llgo/internal/abi.Method", ptr %82, i64 0 + store %"github.com/goplus/llgo/internal/abi.Method" %81, ptr %83, align 8 + %84 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %85 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %84, i32 0, i32 0 + store ptr %82, ptr %85, align 8 + %86 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %84, i32 0, i32 1 + store i64 1, ptr %86, align 4 + %87 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %84, i32 0, i32 2 + store i64 1, ptr %87, align 4 + %88 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %84, align 8 + %89 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 80) + %90 = getelementptr %"github.com/goplus/llgo/internal/abi.Method", ptr %89, i64 0 + store %"github.com/goplus/llgo/internal/abi.Method" %64, ptr %90, align 8 + %91 = getelementptr %"github.com/goplus/llgo/internal/abi.Method", ptr %89, i64 1 + store %"github.com/goplus/llgo/internal/abi.Method" %75, ptr %91, align 8 + %92 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %93 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %92, i32 0, i32 0 + store ptr %89, ptr %93, align 8 + %94 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %92, i32 0, i32 1 + store i64 2, ptr %94, align 4 + %95 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %92, i32 0, i32 2 + store i64 2, ptr %95, align 4 + %96 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %92, align 8 + %97 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %98 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %97, i32 0, i32 0 + store ptr @3, ptr %98, align 8 + %99 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %97, i32 0, i32 1 + store i64 4, ptr %99, align 4 + %100 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %97, align 8 + %101 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %102 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %101, i32 0, i32 0 + store ptr @6, ptr %102, align 8 + %103 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %101, i32 0, i32 1 + store i64 13, ptr %103, align 4 + %104 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %101, align 8 + call void @"github.com/goplus/llgo/internal/runtime.InitNamed"(ptr %0, %"github.com/goplus/llgo/internal/runtime.String" %100, %"github.com/goplus/llgo/internal/runtime.String" %104, ptr %36, %"github.com/goplus/llgo/internal/runtime.Slice" %88, %"github.com/goplus/llgo/internal/runtime.Slice" %96) + br label %_llgo_4 + +_llgo_7: ; preds = %_llgo_4 + %105 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24) + store ptr %105, ptr @_llgo_string, align 8 + br label %_llgo_8 + +_llgo_8: ; preds = %_llgo_7, %_llgo_4 + %106 = load ptr, ptr @"*_llgo_main.T[string,int]", align 8 + %107 = icmp eq ptr %106, null + br i1 %107, label %_llgo_9, label %_llgo_10 + +_llgo_9: ; preds = %_llgo_8 + %108 = call ptr @"github.com/goplus/llgo/internal/runtime.PointerTo"(ptr %0) + call void @"github.com/goplus/llgo/internal/runtime.SetDirectIface"(ptr %108) + store ptr %108, ptr @"*_llgo_main.T[string,int]", align 8 + br label %_llgo_10 + +_llgo_10: ; preds = %_llgo_9, %_llgo_8 + %109 = load ptr, ptr @"_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac", align 8 + %110 = load ptr, ptr @"_llgo_iface$BP0p_lUsEd-IbbtJVukGmgrdQkqzcoYzSiwgUvgFvUs", align 8 + %111 = icmp eq ptr %110, null + br i1 %111, label %_llgo_11, label %_llgo_12 + +_llgo_11: ; preds = %_llgo_10 + %112 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %113 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %112, i32 0, i32 0 + store ptr @4, ptr %113, align 8 + %114 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %112, i32 0, i32 1 + store i64 4, ptr %114, align 4 + %115 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %112, align 8 + %116 = alloca %"github.com/goplus/llgo/internal/abi.Imethod", align 8 + %117 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Imethod", ptr %116, i32 0, i32 0 + store %"github.com/goplus/llgo/internal/runtime.String" %115, ptr %117, align 8 + %118 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Imethod", ptr %116, i32 0, i32 1 + store ptr %109, ptr %118, align 8 + %119 = load %"github.com/goplus/llgo/internal/abi.Imethod", ptr %116, align 8 + %120 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 24) + %121 = getelementptr %"github.com/goplus/llgo/internal/abi.Imethod", ptr %120, i64 0 + store %"github.com/goplus/llgo/internal/abi.Imethod" %119, ptr %121, align 8 + %122 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %123 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %122, i32 0, i32 0 + store ptr %120, ptr %123, align 8 + %124 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %122, i32 0, i32 1 + store i64 1, ptr %124, align 4 + %125 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %122, i32 0, i32 2 + store i64 1, ptr %125, align 4 + %126 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %122, align 8 + %127 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %128 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %127, i32 0, i32 0 + store ptr @3, ptr %128, align 8 + %129 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %127, i32 0, i32 1 + store i64 4, ptr %129, align 4 + %130 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %127, align 8 + %131 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %132 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %131, i32 0, i32 0 + store ptr null, ptr %132, align 8 + %133 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %131, i32 0, i32 1 + store i64 0, ptr %133, align 4 + %134 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %131, align 8 + %135 = call ptr @"github.com/goplus/llgo/internal/runtime.Interface"(%"github.com/goplus/llgo/internal/runtime.String" %130, %"github.com/goplus/llgo/internal/runtime.String" %134, %"github.com/goplus/llgo/internal/runtime.Slice" %126) + store ptr %135, ptr @"_llgo_iface$BP0p_lUsEd-IbbtJVukGmgrdQkqzcoYzSiwgUvgFvUs", align 8 + br label %_llgo_12 + +_llgo_12: ; preds = %_llgo_11, %_llgo_10 + ret void +} + +declare ptr @"github.com/goplus/llgo/internal/runtime.NewNamed"(i64, i64, i64, i64) + +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) + +declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) + +declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64) + +declare void @"github.com/goplus/llgo/internal/runtime.InitNamed"(ptr, %"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String", ptr, %"github.com/goplus/llgo/internal/runtime.Slice", %"github.com/goplus/llgo/internal/runtime.Slice") + +declare ptr @"github.com/goplus/llgo/internal/runtime.Func"(%"github.com/goplus/llgo/internal/runtime.Slice", %"github.com/goplus/llgo/internal/runtime.Slice", i1) + +declare void @"github.com/goplus/llgo/internal/runtime.SetDirectIface"(ptr) + +declare void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface") + +declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String") + +declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8) + +declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) + +declare ptr @"github.com/goplus/llgo/internal/runtime.PointerTo"(ptr) + +declare ptr @"github.com/goplus/llgo/internal/runtime.Interface"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.Slice") + +declare ptr @"github.com/goplus/llgo/internal/runtime.NewItab"(ptr, ptr) + +declare ptr @"github.com/goplus/llgo/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/internal/runtime.iface") + +declare void @"github.com/goplus/llgo/internal/runtime.PrintPointer"(ptr) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64) diff --git a/cl/compile.go b/cl/compile.go index 58a841c4..bf0bf358 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -95,6 +95,8 @@ type context struct { bvals map[ssa.Value]llssa.Expr // block values vargs map[*ssa.Alloc][]llssa.Expr // varargs + instNamed map[*types.Named]none // makeInterface named + patches Patches blkInfos []blocks.Info @@ -228,7 +230,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun results := types.NewTuple(ret) sig = types.NewSignatureType(nil, nil, nil, params, results, false) } - fn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), hasCtx) + fn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), hasCtx, f.Origin() != nil) } if nblk := len(f.Blocks); nblk > 0 { @@ -546,6 +548,7 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue } } prog := p.prog + p.checkInstanceNamed(v.X.Type()) t := prog.Type(v.Type(), llssa.InGo) x := p.compileValue(b, v.X) ret = b.MakeInterface(t, x) @@ -616,6 +619,22 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue return ret } +func (p *context) checkInstanceNamed(typ types.Type) { + if pt, ok := typ.(*types.Pointer); ok { + typ = pt.Elem() + } + named, ok := typ.(*types.Named) + if !ok || named.TypeArgs() == nil { + return + } + if _, ok := p.instNamed[named]; ok { + return + } + p.instNamed[named] = none{} + p.compileMethods(p.pkg, typ) + p.compileMethods(p.pkg, types.NewPointer(typ)) +} + func (p *context) jumpTo(v *ssa.Jump) llssa.BasicBlock { fn := p.fn succs := v.Block().Succs @@ -814,6 +833,7 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [ loaded: map[*types.Package]*pkgInfo{ types.Unsafe: {kind: PkgDeclOnly}, // TODO(xsw): PkgNoInit or PkgDeclOnly? }, + instNamed: make(map[*types.Named]none), } ctx.initPyModule() ctx.initFiles(pkgPath, files) diff --git a/cl/import.go b/cl/import.go index 6729b7cf..751414b9 100644 --- a/cl/import.go +++ b/cl/import.go @@ -340,7 +340,7 @@ func typesFuncName(pkgPath string, fn *types.Func) (fullName, inPkgName string) // fullName: // - func: pkg.name // - method: pkg.(T).name, pkg.(*T).name -func funcName(pkg *types.Package, fn *ssa.Function) string { +func funcName(pkg *types.Package, fn *ssa.Function, org bool) string { var recv *types.Var parent := fn.Parent() if parent != nil { // closure in method @@ -350,15 +350,14 @@ func funcName(pkg *types.Package, fn *ssa.Function) string { } var fnName string if org := fn.Origin(); org != nil { - targs := make([]string, len(fn.TypeArgs())) - for i, t := range fn.TypeArgs() { - targs[i] = types.TypeString(t, llssa.PathOf) + fnName = org.Name() + if fn.Signature.Recv() == nil { + fnName += llssa.TypeArgs(fn.TypeArgs()) } - fnName = org.Name() + "[" + strings.Join(targs, ", ") + "]" } else { fnName = fn.Name() } - return llssa.FuncName(pkg, fnName, recv) + return llssa.FuncName(pkg, fnName, recv, org) } func checkCgo(fnName string) bool { @@ -421,7 +420,7 @@ func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, strin if origin := fn.Origin(); origin != nil { pkg = origin.Pkg.Pkg p.ensureLoaded(pkg) - orgName = funcName(pkg, origin) + orgName = funcName(pkg, origin, true) } else { if fnPkg := fn.Pkg; fnPkg != nil { pkg = fnPkg.Pkg @@ -429,7 +428,7 @@ func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, strin pkg = p.goTyps } p.ensureLoaded(pkg) - orgName = funcName(pkg, fn) + orgName = funcName(pkg, fn, false) if ignore && ignoreName(orgName) || checkCgo(fn.Name()) { return nil, orgName, ignoredFunc } @@ -446,7 +445,7 @@ func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, strin } return pkg, v, goFunc } - return pkg, funcName(pkg, fn), goFunc + return pkg, funcName(pkg, fn, false), goFunc } const ( diff --git a/cl/instr.go b/cl/instr.go index 3585569c..34a764b5 100644 --- a/cl/instr.go +++ b/cl/instr.go @@ -265,7 +265,7 @@ func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObj return nil, nil, ignoredFunc } sig := fn.Signature - aFn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false) + aFn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false, fn.Origin() != nil) } } return diff --git a/ssa/abi/abi.go b/ssa/abi/abi.go index 38a5db75..e5317ff4 100644 --- a/ssa/abi/abi.go +++ b/ssa/abi/abi.go @@ -167,7 +167,7 @@ func (b *Builder) TypeName(t types.Type) (ret string, pub bool) { case *types.Named: o := t.Obj() pkg := o.Pkg() - return "_llgo_" + FullName(pkg, o.Name()), (pkg == nil || o.Exported()) + return "_llgo_" + FullName(pkg, NamedName(t)), (pkg == nil || o.Exported()) case *types.Interface: if t.Empty() { return "_llgo_any", true @@ -194,6 +194,26 @@ func (b *Builder) TypeName(t types.Type) (ret string, pub bool) { return } +func NamedName(t *types.Named) string { + if targs := t.TypeArgs(); targs != nil { + n := targs.Len() + infos := make([]string, n) + for i := 0; i < n; i++ { + infos[i] = types.TypeString(targs.At(i), PathOf) + } + return t.Obj().Name() + "[" + strings.Join(infos, ",") + "]" + } + return t.Obj().Name() +} + +func TypeArgs(typeArgs []types.Type) string { + targs := make([]string, len(typeArgs)) + for i, t := range typeArgs { + targs[i] = types.TypeString(t, PathOf) + } + return "[" + strings.Join(targs, ",") + "]" +} + const ( PatchPathPrefix = "github.com/goplus/llgo/internal/lib/" ) diff --git a/ssa/abitype.go b/ssa/abitype.go index 2d6a875e..50912370 100644 --- a/ssa/abitype.go +++ b/ssa/abitype.go @@ -153,7 +153,7 @@ func (b Builder) abiMethodOf(mPkg *types.Package, mName string, mSig *types.Sign } func (b Builder) abiMthd(mPkg *types.Package, mName string, mSig *types.Signature, name, abiTyp, ifn llvm.Value) (ret Expr, tfn llvm.Value) { - fullName := FuncName(mPkg, mName, mSig.Recv()) + fullName := FuncName(mPkg, mName, mSig.Recv(), false) if b.Pkg.fnlink != nil { fullName = b.Pkg.fnlink(fullName) } @@ -230,7 +230,8 @@ func (b Builder) abiInitNamed(ret Expr, t *types.Named) func() Expr { pkg := b.Pkg prog := b.Prog path := abi.PathOf(t.Obj().Pkg()) - name := t.Obj().Name() + name := abi.NamedName(t) + //targs := abi.NamedTypeArgs(t) var initNamed = pkg.rtFunc("InitNamed") var tSlice = lastParamType(prog, initNamed) mset := typeutil.IntuitiveMethodSet(t, nil) diff --git a/ssa/decl.go b/ssa/decl.go index 89128409..96751a37 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -180,11 +180,11 @@ type Function = *aFunction // NewFunc creates a new function. func (p Package) NewFunc(name string, sig *types.Signature, bg Background) Function { - return p.NewFuncEx(name, sig, bg, false) + return p.NewFuncEx(name, sig, bg, false, false) } // NewFuncEx creates a new function. -func (p Package) NewFuncEx(name string, sig *types.Signature, bg Background, hasFreeVars bool) Function { +func (p Package) NewFuncEx(name string, sig *types.Signature, bg Background, hasFreeVars bool, instantiated bool) Function { if v, ok := p.fns[name]; ok { return v } @@ -193,6 +193,9 @@ func (p Package) NewFuncEx(name string, sig *types.Signature, bg Background, has log.Println("NewFunc", name, t.raw.Type, "hasFreeVars:", hasFreeVars) } fn := llvm.AddFunction(p.mod, name, t.ll) + if instantiated { + fn.SetLinkage(llvm.LinkOnceAnyLinkage) + } ret := newFunction(fn, t, p, p.Prog, hasFreeVars) p.fns[name] = ret return ret diff --git a/ssa/type.go b/ssa/type.go index 5e2dcf88..122041c9 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -19,7 +19,6 @@ package ssa import ( "fmt" "go/types" - "strings" "github.com/goplus/llgo/ssa/abi" "github.com/goplus/llvm" @@ -515,16 +514,7 @@ func (p Program) toNamed(raw *types.Named) Type { // NameOf returns the full name of a named type. func NameOf(typ *types.Named) string { - name := abi.TypeName(typ.Obj()) - if targs := typ.TypeArgs(); targs != nil { - n := targs.Len() - args := make([]string, n) - for i := 0; i < n; i++ { - args[i] = types.TypeString(targs.At(i), PathOf) - } - name += "[" + strings.Join(args, ", ") + "]" - } - return name + return abi.FullName(typ.Obj().Pkg(), abi.NamedName(typ)) } // FullName returns the full name of a package member. @@ -540,14 +530,22 @@ func PathOf(pkg *types.Package) string { // FuncName: // - func: pkg.name // - method: pkg.T.name, pkg.(*T).name -func FuncName(pkg *types.Package, name string, recv *types.Var) string { +func FuncName(pkg *types.Package, name string, recv *types.Var, org bool) string { if recv != nil { var tName string t := recv.Type() - if tp, ok := t.(*types.Pointer); ok { - tName = "(*" + tp.Elem().(*types.Named).Obj().Name() + ")" + if org { + if tp, ok := t.(*types.Pointer); ok { + tName = "(*" + tp.Elem().(*types.Named).Obj().Name() + ")" + } else { + tName = t.(*types.Named).Obj().Name() + } } else { - tName = t.(*types.Named).Obj().Name() + if tp, ok := t.(*types.Pointer); ok { + tName = "(*" + abi.NamedName(tp.Elem().(*types.Named)) + ")" + } else { + tName = abi.NamedName(t.(*types.Named)) + } } return PathOf(pkg) + "." + tName + "." + name } @@ -558,4 +556,8 @@ func FuncName(pkg *types.Package, name string, recv *types.Var) string { return ret } +func TypeArgs(typeArgs []types.Type) string { + return abi.TypeArgs(typeArgs) +} + // -----------------------------------------------------------------------------