Skip to content

Commit

Permalink
Merge pull request #351 from visualfc/instance
Browse files Browse the repository at this point in the history
build: instantiate generics
  • Loading branch information
xushiwei authored Jun 18, 2024
2 parents 2b49117 + d59075e commit fbf50d4
Show file tree
Hide file tree
Showing 13 changed files with 672 additions and 9 deletions.
18 changes: 18 additions & 0 deletions cl/_testgo/tpindex/in.go
Original file line number Diff line number Diff line change
@@ -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))
}
95 changes: 95 additions & 0 deletions cl/_testgo/tpindex/out.ll
Original file line number Diff line number Diff line change
@@ -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)
36 changes: 36 additions & 0 deletions cl/_testgo/tprecur/in.go
Original file line number Diff line number Diff line change
@@ -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)
}
174 changes: 174 additions & 0 deletions cl/_testgo/tprecur/out.ll
Original file line number Diff line number Diff line change
@@ -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)
63 changes: 63 additions & 0 deletions cl/_testgo/tptypes/in.go
Original file line number Diff line number Diff line change
@@ -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])
}
Loading

0 comments on commit fbf50d4

Please sign in to comment.