Skip to content

Commit a029650

Browse files
authored
Merge pull request #1439 from visualfc/ssatype
ssa: fix types named cycle
2 parents aad42ea + b3c5e67 commit a029650

File tree

5 files changed

+170
-11
lines changed

5 files changed

+170
-11
lines changed

_demo/go/statefn/main.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package main
2+
3+
type stateFn func(*counter) stateFn
4+
5+
type counter struct {
6+
value int
7+
max int
8+
state stateFn
9+
}
10+
11+
func main() {
12+
c := &counter{max: 5, state: startState}
13+
14+
for c.state != nil {
15+
c.state = c.state(c)
16+
}
17+
}
18+
19+
func startState(c *counter) stateFn {
20+
println("start")
21+
return countState
22+
}
23+
24+
func countState(c *counter) stateFn {
25+
c.value++
26+
println("count:", c.value)
27+
28+
if c.value >= c.max {
29+
return endState
30+
}
31+
return countState
32+
}
33+
34+
func endState(c *counter) stateFn {
35+
println("end")
36+
return nil
37+
}

cl/_testgo/typerecur/in.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
type stateFn func(*counter) stateFn
4+
5+
type counter struct {
6+
value int
7+
max int
8+
state stateFn
9+
}
10+
11+
func countState(c *counter) stateFn {
12+
c.value++
13+
println("count:", c.value)
14+
15+
if c.value >= c.max {
16+
return nil
17+
}
18+
return countState
19+
}
20+
21+
func main() {
22+
c := &counter{max: 5, state: countState}
23+
24+
for c.state != nil {
25+
c.state = c.state(c)
26+
}
27+
}

cl/_testgo/typerecur/out.ll

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
; ModuleID = 'github.com/goplus/llgo/cl/_testgo/typerecur'
2+
source_filename = "github.com/goplus/llgo/cl/_testgo/typerecur"
3+
4+
%"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" = type { ptr, ptr }
5+
%"github.com/goplus/llgo/cl/_testgo/typerecur.counter" = type { i64, i64, %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" }
6+
%"github.com/goplus/llgo/runtime/internal/runtime.String" = type { ptr, i64 }
7+
8+
@"github.com/goplus/llgo/cl/_testgo/typerecur.init$guard" = global i1 false, align 1
9+
@0 = private unnamed_addr constant [6 x i8] c"count:", align 1
10+
11+
define %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" @"github.com/goplus/llgo/cl/_testgo/typerecur.countState"(ptr %0) {
12+
_llgo_0:
13+
%1 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/typerecur.counter", ptr %0, i32 0, i32 0
14+
%2 = load i64, ptr %1, align 4
15+
%3 = add i64 %2, 1
16+
%4 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/typerecur.counter", ptr %0, i32 0, i32 0
17+
store i64 %3, ptr %4, align 4
18+
%5 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/typerecur.counter", ptr %0, i32 0, i32 0
19+
%6 = load i64, ptr %5, align 4
20+
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintString"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @0, i64 6 })
21+
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintByte"(i8 32)
22+
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintInt"(i64 %6)
23+
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintByte"(i8 10)
24+
%7 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/typerecur.counter", ptr %0, i32 0, i32 0
25+
%8 = load i64, ptr %7, align 4
26+
%9 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/typerecur.counter", ptr %0, i32 0, i32 1
27+
%10 = load i64, ptr %9, align 4
28+
%11 = icmp sge i64 %8, %10
29+
br i1 %11, label %_llgo_1, label %_llgo_2
30+
31+
_llgo_1: ; preds = %_llgo_0
32+
ret %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" zeroinitializer
33+
34+
_llgo_2: ; preds = %_llgo_0
35+
ret %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" { ptr @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/typerecur.countState", ptr null }
36+
}
37+
38+
define void @"github.com/goplus/llgo/cl/_testgo/typerecur.init"() {
39+
_llgo_0:
40+
%0 = load i1, ptr @"github.com/goplus/llgo/cl/_testgo/typerecur.init$guard", align 1
41+
br i1 %0, label %_llgo_2, label %_llgo_1
42+
43+
_llgo_1: ; preds = %_llgo_0
44+
store i1 true, ptr @"github.com/goplus/llgo/cl/_testgo/typerecur.init$guard", align 1
45+
br label %_llgo_2
46+
47+
_llgo_2: ; preds = %_llgo_1, %_llgo_0
48+
ret void
49+
}
50+
51+
define void @"github.com/goplus/llgo/cl/_testgo/typerecur.main"() {
52+
_llgo_0:
53+
%0 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 32)
54+
%1 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/typerecur.counter", ptr %0, i32 0, i32 1
55+
%2 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/typerecur.counter", ptr %0, i32 0, i32 2
56+
store i64 5, ptr %1, align 4
57+
store %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" { ptr @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/typerecur.countState", ptr null }, ptr %2, align 8
58+
br label %_llgo_3
59+
60+
_llgo_1: ; preds = %_llgo_3
61+
%3 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/typerecur.counter", ptr %0, i32 0, i32 2
62+
%4 = load %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn", ptr %3, align 8
63+
%5 = extractvalue %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" %4, 1
64+
%6 = extractvalue %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" %4, 0
65+
%7 = call %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" %6(ptr %5, ptr %0)
66+
%8 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/typerecur.counter", ptr %0, i32 0, i32 2
67+
store %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" %7, ptr %8, align 8
68+
br label %_llgo_3
69+
70+
_llgo_2: ; preds = %_llgo_3
71+
ret void
72+
73+
_llgo_3: ; preds = %_llgo_1, %_llgo_0
74+
%9 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/typerecur.counter", ptr %0, i32 0, i32 2
75+
%10 = load %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn", ptr %9, align 8
76+
%11 = extractvalue %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" %10, 0
77+
%12 = icmp ne ptr %11, null
78+
br i1 %12, label %_llgo_1, label %_llgo_2
79+
}
80+
81+
declare void @"github.com/goplus/llgo/runtime/internal/runtime.PrintString"(%"github.com/goplus/llgo/runtime/internal/runtime.String")
82+
83+
declare void @"github.com/goplus/llgo/runtime/internal/runtime.PrintByte"(i8)
84+
85+
declare void @"github.com/goplus/llgo/runtime/internal/runtime.PrintInt"(i64)
86+
87+
define linkonce %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/typerecur.countState"(ptr %0, ptr %1) {
88+
_llgo_0:
89+
%2 = tail call %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" @"github.com/goplus/llgo/cl/_testgo/typerecur.countState"(ptr %1)
90+
ret %"github.com/goplus/llgo/cl/_testgo/typerecur.stateFn" %2
91+
}
92+
93+
declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64)

ssa/package.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ type aProgram struct {
120120
target *Target
121121
td llvm.TargetData
122122
// tm llvm.TargetMachine
123-
named map[string]llvm.Type
123+
named map[string]Type
124124
fnnamed map[string]int
125125

126126
intType llvm.Type
@@ -261,7 +261,7 @@ func NewProgram(target *Target) Program {
261261
return &aProgram{
262262
ctx: ctx, gocvt: newGoTypes(), fnsCompiled: fnsCompiled,
263263
target: target, td: td, is32Bits: is32Bits,
264-
ptrSize: td.PointerSize(), named: make(map[string]llvm.Type), fnnamed: make(map[string]int),
264+
ptrSize: td.PointerSize(), named: make(map[string]Type), fnnamed: make(map[string]int),
265265
linkname: make(map[string]string),
266266
}
267267
}

ssa/type.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -397,15 +397,14 @@ func (p Program) toType(raw types.Type) Type {
397397
panic(fmt.Sprintf("toLLVMType: todo - %T\n", raw))
398398
}
399399

400-
func (p Program) toLLVMNamedStruct(name string, raw *types.Struct) llvm.Type {
401-
if typ, ok := p.named[name]; ok {
402-
return typ
403-
}
400+
func (p Program) toLLVMNamedStruct(name string, raw *types.Named, st *types.Struct, kind valueKind) Type {
404401
t := p.ctx.StructCreateNamed(name)
405-
p.named[name] = t
406-
fields := p.toLLVMFields(raw)
402+
typ := &aType{t, rawType{raw}, kind}
403+
p.named[name] = typ
404+
p.typs.Set(raw, typ)
405+
fields := p.toLLVMFields(st)
407406
t.StructSetBody(fields, false)
408-
return t
407+
return typ
409408
}
410409

411410
func (p Program) toLLVMStruct(raw *types.Struct) (ret llvm.Type, kind valueKind) {
@@ -504,14 +503,17 @@ func (p Program) llvmNameOf(named *types.Named) (name string) {
504503
}
505504

506505
func (p Program) toNamed(raw *types.Named) Type {
506+
name := p.llvmNameOf(raw)
507+
if typ, ok := p.named[name]; ok {
508+
return typ
509+
}
507510
switch t := raw.Underlying().(type) {
508511
case *types.Struct:
509-
name := p.llvmNameOf(raw)
510512
kind := vkStruct
511513
if IsClosure(t) {
512514
kind = vkClosure
513515
}
514-
return &aType{p.toLLVMNamedStruct(name, t), rawType{raw}, kind}
516+
return p.toLLVMNamedStruct(name, raw, t, kind)
515517
default:
516518
typ := p.rawType(t)
517519
return &aType{typ.ll, rawType{raw}, typ.kind}

0 commit comments

Comments
 (0)