diff --git a/cl/_testgo/tpindex/in.go b/cl/_testgo/tpindex/in.go new file mode 100644 index 000000000..e42a84cff --- /dev/null +++ b/cl/_testgo/tpindex/in.go @@ -0,0 +1,18 @@ +package main + +// The index function returns the index of the first occurrence of v in s, +// or -1 if not present. +func index[E comparable](s []E, v E) int { + for i, vs := range s { + if v == vs { + return i + } + } + return -1 +} + +func main() { + s := []int{1, 3, 5, 2, 4} + println(index(s, 3)) + println(index(s, 6)) +} diff --git a/cl/_testgo/tpindex/out.ll b/cl/_testgo/tpindex/out.ll new file mode 100644 index 000000000..058b05584 --- /dev/null +++ b/cl/_testgo/tpindex/out.ll @@ -0,0 +1,95 @@ +; ModuleID = 'main' +source_filename = "main" + +%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 } + +@"main.init$guard" = global i1 false, align 1 +@__llgo_argc = global i32 0, align 4 +@__llgo_argv = 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 + 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 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40) + %3 = getelementptr inbounds i64, ptr %2, i64 0 + store i64 1, ptr %3, align 4 + %4 = getelementptr inbounds i64, ptr %2, i64 1 + store i64 3, ptr %4, align 4 + %5 = getelementptr inbounds i64, ptr %2, i64 2 + store i64 5, ptr %5, align 4 + %6 = getelementptr inbounds i64, ptr %2, i64 3 + store i64 2, ptr %6, align 4 + %7 = getelementptr inbounds i64, ptr %2, i64 4 + store i64 4, ptr %7, align 4 + %8 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %8, i32 0, i32 0 + store ptr %2, ptr %9, align 8 + %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %8, i32 0, i32 1 + store i64 5, ptr %10, align 4 + %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %8, i32 0, i32 2 + store i64 5, ptr %11, align 4 + %12 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %8, align 8 + %13 = call i64 @"main.index[int]"(%"github.com/goplus/llgo/internal/runtime.Slice" %12, i64 3) + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %13) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %14 = call i64 @"main.index[int]"(%"github.com/goplus/llgo/internal/runtime.Slice" %12, i64 6) + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %14) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + ret i32 0 +} + +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) { +_llgo_0: + %2 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1 + br label %_llgo_1 + +_llgo_1: ; preds = %_llgo_2, %_llgo_0 + %3 = phi i64 [ -1, %_llgo_0 ], [ %4, %_llgo_2 ] + %4 = add i64 %3, 1 + %5 = icmp slt i64 %4, %2 + br i1 %5, label %_llgo_2, label %_llgo_3 + +_llgo_2: ; preds = %_llgo_1 + %6 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 + %7 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1 + %8 = icmp slt i64 %4, 0 + %9 = icmp sge i64 %4, %7 + %10 = or i1 %9, %8 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %10) + %11 = getelementptr inbounds i64, ptr %6, i64 %4 + %12 = load i64, ptr %11, align 4 + %13 = icmp eq i64 %1, %12 + br i1 %13, label %_llgo_4, label %_llgo_1 + +_llgo_3: ; preds = %_llgo_1 + ret i64 -1 + +_llgo_4: ; preds = %_llgo_2 + ret i64 %4 +} + +declare void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8) + +declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1) diff --git a/cl/_testgo/tprecur/in.go b/cl/_testgo/tprecur/in.go new file mode 100644 index 000000000..b7a984df4 --- /dev/null +++ b/cl/_testgo/tprecur/in.go @@ -0,0 +1,36 @@ +package main + +func main() { + recursive() +} + +func recursive() { + type T int + if got, want := recur1[T](5), T(110); got != want { + panic("error") + } +} + +type Integer interface { + ~int | ~int32 | ~int64 +} + +func recur1[T Integer](n T) T { + if n == 0 || n == 1 { + return T(1) + } else { + return n * recur2(n-1) + } +} + +func recur2[T Integer](n T) T { + list := make([]T, n) + for i, _ := range list { + list[i] = T(i + 1) + } + var sum T + for _, elt := range list { + sum += elt + } + return sum + recur1(n-1) +} diff --git a/cl/_testgo/tprecur/out.ll b/cl/_testgo/tprecur/out.ll new file mode 100644 index 000000000..a1e869f62 --- /dev/null +++ b/cl/_testgo/tprecur/out.ll @@ -0,0 +1,174 @@ +; ModuleID = 'main' +source_filename = "main" + +%"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.Slice" = type { ptr, i64, i64 } + +@"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 [5 x i8] c"error", align 1 +@_llgo_string = 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() + call void @main.recursive() + ret i32 0 +} + +define void @main.recursive() { +_llgo_0: + %0 = call i64 @"main.recur1[main.T]"(i64 5) + %1 = icmp ne i64 %0, 110 + br i1 %1, label %_llgo_1, label %_llgo_2 + +_llgo_1: ; preds = %_llgo_0 + %2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 0 + store ptr @0, ptr %3, align 8 + %4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 1 + store i64 5, ptr %4, align 4 + %5 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8 + %6 = load ptr, ptr @_llgo_string, align 8 + %7 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16) + store %"github.com/goplus/llgo/internal/runtime.String" %5, ptr %7, align 8 + %8 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8 + %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %8, i32 0, i32 0 + store ptr %6, ptr %9, align 8 + %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %8, i32 0, i32 1 + store ptr %7, ptr %10, align 8 + %11 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %8, align 8 + call void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface" %11) + unreachable + +_llgo_2: ; preds = %_llgo_0 + ret void +} + +declare void @"github.com/goplus/llgo/internal/runtime.init"() + +define i64 @"main.recur1[main.T]"(i64 %0) { +_llgo_0: + %1 = icmp eq i64 %0, 0 + br i1 %1, label %_llgo_1, label %_llgo_3 + +_llgo_1: ; preds = %_llgo_3, %_llgo_0 + ret i64 1 + +_llgo_2: ; preds = %_llgo_3 + %2 = sub i64 %0, 1 + %3 = call i64 @"main.recur2[main.T]"(i64 %2) + %4 = mul i64 %0, %3 + ret i64 %4 + +_llgo_3: ; preds = %_llgo_0 + %5 = icmp eq i64 %0, 1 + br i1 %5, label %_llgo_1, label %_llgo_2 +} + +define void @"main.init$after"() { +_llgo_0: + %0 = load ptr, ptr @_llgo_string, align 8 + %1 = icmp eq ptr %0, null + br i1 %1, label %_llgo_1, label %_llgo_2 + +_llgo_1: ; preds = %_llgo_0 + %2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24) + store ptr %2, ptr @_llgo_string, align 8 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +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.Panic"(%"github.com/goplus/llgo/internal/runtime.eface") + +define i64 @"main.recur2[main.T]"(i64 %0) { +_llgo_0: + %1 = mul i64 %0, 8 + %2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 %1) + %3 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %3, i32 0, i32 0 + store ptr %2, ptr %4, align 8 + %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %3, i32 0, i32 1 + store i64 %0, ptr %5, align 4 + %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %3, i32 0, i32 2 + store i64 %0, ptr %6, align 4 + %7 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %3, align 8 + %8 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 1 + br label %_llgo_1 + +_llgo_1: ; preds = %_llgo_2, %_llgo_0 + %9 = phi i64 [ -1, %_llgo_0 ], [ %10, %_llgo_2 ] + %10 = add i64 %9, 1 + %11 = icmp slt i64 %10, %8 + br i1 %11, label %_llgo_2, label %_llgo_3 + +_llgo_2: ; preds = %_llgo_1 + %12 = add i64 %10, 1 + %13 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0 + %14 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 1 + %15 = icmp slt i64 %10, 0 + %16 = icmp sge i64 %10, %14 + %17 = or i1 %16, %15 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %17) + %18 = getelementptr inbounds i64, ptr %13, i64 %10 + store i64 %12, ptr %18, align 4 + br label %_llgo_1 + +_llgo_3: ; preds = %_llgo_1 + %19 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 1 + br label %_llgo_4 + +_llgo_4: ; preds = %_llgo_5, %_llgo_3 + %20 = phi i64 [ 0, %_llgo_3 ], [ %31, %_llgo_5 ] + %21 = phi i64 [ -1, %_llgo_3 ], [ %22, %_llgo_5 ] + %22 = add i64 %21, 1 + %23 = icmp slt i64 %22, %19 + br i1 %23, label %_llgo_5, label %_llgo_6 + +_llgo_5: ; preds = %_llgo_4 + %24 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0 + %25 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 1 + %26 = icmp slt i64 %22, 0 + %27 = icmp sge i64 %22, %25 + %28 = or i1 %27, %26 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %28) + %29 = getelementptr inbounds i64, ptr %24, i64 %22 + %30 = load i64, ptr %29, align 4 + %31 = add i64 %20, %30 + br label %_llgo_4 + +_llgo_6: ; preds = %_llgo_4 + %32 = sub i64 %0, 1 + %33 = call i64 @"main.recur1[main.T]"(i64 %32) + %34 = add i64 %20, %33 + ret i64 %34 +} + +declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) + +declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1) diff --git a/cl/_testgo/tptypes/in.go b/cl/_testgo/tptypes/in.go new file mode 100644 index 000000000..2ff2b31af --- /dev/null +++ b/cl/_testgo/tptypes/in.go @@ -0,0 +1,63 @@ +package main + +type Data[T any] struct { + v T +} + +func (p *Data[T]) Set(v T) { + p.v = v +} + +func (p *(Data[T1])) Set2(v T1) { + p.v = v +} + +type sliceOf[E any] interface { + ~[]E +} + +type Slice[S sliceOf[T], T any] struct { + Data S +} + +func (p *Slice[S, T]) Append(t ...T) S { + p.Data = append(p.Data, t...) + return p.Data +} + +func (p *Slice[S1, T1]) Append2(t ...T1) S1 { + p.Data = append(p.Data, t...) + return p.Data +} + +type ( + DataInt = Data[int] + SliceInt = Slice[[]int, int] + DataString = Data[string] + SliceString = Slice[[]string, string] +) + +func main() { + println(DataInt{1}.v) + println(DataString{"hello"}.v) + println(Data[int]{100}.v) + println(Data[string]{"hello"}.v) + + // TODO + println(Data[struct { + X int + Y int + }]{}.v.X) + + v1 := SliceInt{} + v1.Append(100) + v2 := SliceString{} + v2.Append("hello") + v3 := Slice[[]int, int]{} + v3.Append([]int{1, 2, 3, 4}...) + v3.Append2([]int{1, 2, 3, 4}...) + + println(v1.Data, v1.Data[0]) + println(v2.Data, v2.Data[0]) + println(v3.Data, v3.Data[0]) +} diff --git a/cl/_testgo/tptypes/out.ll b/cl/_testgo/tptypes/out.ll new file mode 100644 index 000000000..3c2c94602 --- /dev/null +++ b/cl/_testgo/tptypes/out.ll @@ -0,0 +1,253 @@ +; ModuleID = 'main' +source_filename = "main" + +%"main.Data[int]" = type { i64 } +%"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.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 [5 x i8] c"hello", align 1 + +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 + 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.Data[int]", align 8 + %3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 8) + %4 = getelementptr inbounds %"main.Data[int]", ptr %3, i32 0, i32 0 + store i64 1, ptr %4, align 4 + %5 = load %"main.Data[int]", ptr %3, align 4 + %6 = extractvalue %"main.Data[int]" %5, 0 + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %6) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %7 = alloca %"main.Data[string]", align 8 + %8 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %7, i64 16) + %9 = getelementptr inbounds %"main.Data[string]", ptr %8, i32 0, i32 0 + %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 @0, ptr %11, align 8 + %12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %10, i32 0, i32 1 + store i64 5, ptr %12, align 4 + %13 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %10, align 8 + store %"github.com/goplus/llgo/internal/runtime.String" %13, ptr %9, align 8 + %14 = load %"main.Data[string]", ptr %8, align 8 + %15 = extractvalue %"main.Data[string]" %14, 0 + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %15) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %16 = alloca %"main.Data[int]", align 8 + %17 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %16, i64 8) + %18 = getelementptr inbounds %"main.Data[int]", ptr %17, i32 0, i32 0 + store i64 100, ptr %18, align 4 + %19 = load %"main.Data[int]", ptr %17, align 4 + %20 = extractvalue %"main.Data[int]" %19, 0 + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %20) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %21 = alloca %"main.Data[string]", align 8 + %22 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %21, i64 16) + %23 = getelementptr inbounds %"main.Data[string]", ptr %22, i32 0, i32 0 + %24 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %25 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 0 + store ptr @0, ptr %25, align 8 + %26 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 1 + store i64 5, ptr %26, align 4 + %27 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %24, align 8 + store %"github.com/goplus/llgo/internal/runtime.String" %27, ptr %23, align 8 + %28 = load %"main.Data[string]", ptr %22, align 8 + %29 = extractvalue %"main.Data[string]" %28, 0 + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %29) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 0) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %30 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 24) + %31 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8) + %32 = getelementptr inbounds i64, ptr %31, i64 0 + store i64 100, ptr %32, align 4 + %33 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %34 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %33, i32 0, i32 0 + store ptr %31, ptr %34, align 8 + %35 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %33, i32 0, i32 1 + store i64 1, ptr %35, align 4 + %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) + %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 + %42 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %43 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %42, i32 0, i32 0 + store ptr @0, ptr %43, align 8 + %44 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %42, i32 0, i32 1 + store i64 5, ptr %44, align 4 + %45 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %42, align 8 + store %"github.com/goplus/llgo/internal/runtime.String" %45, ptr %41, align 8 + %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 %40, ptr %47, align 8 + %48 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %46, i32 0, i32 1 + store i64 1, ptr %48, align 4 + %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) + %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 + store i64 1, ptr %54, align 4 + %55 = getelementptr inbounds i64, ptr %53, i64 1 + store i64 2, ptr %55, align 4 + %56 = getelementptr inbounds i64, ptr %53, i64 2 + store i64 3, ptr %56, align 4 + %57 = getelementptr inbounds i64, ptr %53, i64 3 + store i64 4, ptr %57, align 4 + %58 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %59 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %58, i32 0, i32 0 + store ptr %53, ptr %59, align 8 + %60 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %58, i32 0, i32 1 + store i64 4, ptr %60, align 4 + %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) + %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 + %66 = getelementptr inbounds i64, ptr %64, i64 1 + store i64 2, ptr %66, align 4 + %67 = getelementptr inbounds i64, ptr %64, i64 2 + store i64 3, ptr %67, align 4 + %68 = getelementptr inbounds i64, ptr %64, i64 3 + store i64 4, ptr %68, align 4 + %69 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %70 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %69, i32 0, i32 0 + store ptr %64, ptr %70, align 8 + %71 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %69, i32 0, i32 1 + store i64 4, ptr %71, align 4 + %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 + %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 + %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 + %81 = icmp sge i64 0, %80 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %81) + %82 = getelementptr inbounds i64, ptr %79, i64 0 + %83 = load i64, ptr %82, align 4 + call void @"github.com/goplus/llgo/internal/runtime.PrintSlice"(%"github.com/goplus/llgo/internal/runtime.Slice" %76) + 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 + %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 + %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 + %90 = icmp sge i64 0, %89 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %90) + %91 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %88, i64 0 + %92 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %91, align 8 + call void @"github.com/goplus/llgo/internal/runtime.PrintSlice"(%"github.com/goplus/llgo/internal/runtime.Slice" %85) + 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 + %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 + %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 + %99 = icmp sge i64 0, %98 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %99) + %100 = getelementptr inbounds i64, ptr %97, i64 0 + %101 = load i64, ptr %100, align 4 + call void @"github.com/goplus/llgo/internal/runtime.PrintSlice"(%"github.com/goplus/llgo/internal/runtime.Slice" %94) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %101) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + ret i32 0 +} + +declare void @"github.com/goplus/llgo/internal/runtime.init"() + +declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String") + +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) { +_llgo_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 + 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 + %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) { +_llgo_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 + 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 + %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) { +_llgo_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 + 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 + %9 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %8, align 8 + ret %"github.com/goplus/llgo/internal/runtime.Slice" %9 +} + +declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintSlice"(%"github.com/goplus/llgo/internal/runtime.Slice") + +declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.SliceAppend"(%"github.com/goplus/llgo/internal/runtime.Slice", ptr, i64, i64) diff --git a/cl/blocks/block_test.go b/cl/blocks/block_test.go index 1ad8f7dae..92b003991 100644 --- a/cl/blocks/block_test.go +++ b/cl/blocks/block_test.go @@ -104,7 +104,7 @@ func testBlockInfo(t *testing.T, src any, fname, expected, fn string) { pkg := types.NewPackage(name, name) imp := packages.NewImporter(fset) foo, _, err := ssautil.BuildPackage( - &types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions) + &types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions|ssa.InstantiateGenerics) if err != nil { t.Fatal("BuildPackage failed:", err) } diff --git a/cl/cltest/cltest.go b/cl/cltest/cltest.go index 7c6cb59a3..b58bae30c 100644 --- a/cl/cltest/cltest.go +++ b/cl/cltest/cltest.go @@ -139,7 +139,7 @@ func TestCompileEx(t *testing.T, src any, fname, expected string) { pkg := types.NewPackage(name, name) imp := packages.NewImporter(fset) foo, _, err := ssautil.BuildPackage( - &types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions) + &types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions|ssa.InstantiateGenerics) if err != nil { t.Fatal("BuildPackage failed:", err) } diff --git a/cl/import.go b/cl/import.go index 63d80bb49..fa00b6b56 100644 --- a/cl/import.go +++ b/cl/import.go @@ -277,14 +277,18 @@ func (p *context) initLink(line string, prefix int, f func(inPkgName string) (fu } } -func recvTypeName(t ast.Expr) string { - switch t := t.(type) { +func recvTypeName(typ ast.Expr) string { +retry: + switch t := typ.(type) { case *ast.Ident: return t.Name case *ast.IndexExpr: return trecvTypeName(t.X, t.Index) case *ast.IndexListExpr: return trecvTypeName(t.X, t.Indices...) + case *ast.ParenExpr: + typ = t.X + goto retry } panic("unreachable") } @@ -344,7 +348,17 @@ func funcName(pkg *types.Package, fn *ssa.Function) string { } else { recv = fn.Signature.Recv() } - return llssa.FuncName(pkg, fn.Name(), recv) + 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() + "[" + strings.Join(targs, ", ") + "]" + } else { + fnName = fn.Name() + } + return llssa.FuncName(pkg, fnName, recv) } func checkCgo(fnName string) bool { diff --git a/internal/build/build.go b/internal/build/build.go index e3e1da8ed..fb591d896 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -197,7 +197,7 @@ func isNeedRuntimeOrPyInit(pkg *packages.Package) (needRuntime, needPyInit bool) } const ( - ssaBuildMode = ssa.SanityCheckFunctions + ssaBuildMode = ssa.SanityCheckFunctions | ssa.InstantiateGenerics ) type context struct { diff --git a/internal/llgen/llgen.go b/internal/llgen/llgen.go index 2a62b6373..840bc1326 100644 --- a/internal/llgen/llgen.go +++ b/internal/llgen/llgen.go @@ -63,7 +63,7 @@ func Gen(pkgPath, inFile string, src any) string { pkg := types.NewPackage(pkgPath, name) imp := packages.NewImporter(fset) ssaPkg, _, err := ssautil.BuildPackage( - &types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions) + &types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions|ssa.InstantiateGenerics) check(err) if Verbose { diff --git a/internal/llgen/llgenf.go b/internal/llgen/llgenf.go index 916831dcf..43209a2cf 100644 --- a/internal/llgen/llgenf.go +++ b/internal/llgen/llgenf.go @@ -68,7 +68,7 @@ func GenFrom(fileOrPkg string) string { initial, err := packages.LoadEx(nil, prog.TypeSizes, cfg, fileOrPkg) check(err) - _, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions) + _, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions|ssa.InstantiateGenerics) pkg := initial[0] ssaPkg := pkgs[0] diff --git a/ssa/type.go b/ssa/type.go index 97986f95b..9ee05e189 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -19,6 +19,7 @@ package ssa import ( "fmt" "go/types" + "strings" "github.com/goplus/llgo/ssa/abi" "github.com/goplus/llvm" @@ -482,7 +483,16 @@ func (p Program) toNamed(raw *types.Named) Type { // NameOf returns the full name of a named type. func NameOf(typ *types.Named) string { - return abi.TypeName(typ.Obj()) + 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 } // FullName returns the full name of a package member.