llgo/ssa: getDefer fix

This commit is contained in:
xushiwei
2024-06-08 20:09:56 +08:00
parent 32bfb3d57e
commit 63c03bb28c
7 changed files with 49 additions and 11 deletions

View File

@@ -0,0 +1,16 @@
package foo
func f(s string) bool {
return len(s) > 2
}
func Loop() {
for i := 0; i < 3; i++ {
if s := "hello"; f(s) {
defer println(s)
} else {
defer println("world")
return
}
}
}

View File

@@ -0,0 +1,7 @@
0: always
6: cond
3: loop
1: loop
4: loop
2: cond
5: cond

View File

@@ -0,0 +1,7 @@
package foo
func Loop() {
for i := 0; i < 3; i++ {
println(i)
}
}

View File

@@ -0,0 +1,4 @@
0: always
3: loop
1: loop
2: always

View File

@@ -45,12 +45,12 @@ _llgo_0:
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
store ptr %3, ptr %6, align 8
%7 = call i32 @pthread_setspecific(ptr %2, ptr %4)
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 0
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 2
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()
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 0
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 2
%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

View File

@@ -37,8 +37,12 @@ import (
)
func TestTestdefer(t *testing.T) {
// debug = true
fromDir(t, "", "../_testdefer")
fromDir(t, "", "../_testdefer", func(name string) string {
if strings.HasPrefix(name, "firstloop") {
return "Loop"
}
return "main"
})
}
func TestFirstLoop(t *testing.T) {
@@ -52,7 +56,7 @@ func TestFirstLoop(t *testing.T) {
}
}
func fromDir(t *testing.T, sel, relDir string) {
func fromDir(t *testing.T, sel, relDir string, fn func(string) string) {
dir, err := os.Getwd()
if err != nil {
t.Fatal("Getwd failed:", err)
@@ -68,12 +72,12 @@ func fromDir(t *testing.T, sel, relDir string) {
continue
}
t.Run(name, func(t *testing.T) {
testFrom(t, dir+"/"+name, sel)
testFrom(t, dir+"/"+name, sel, fn(name))
})
}
}
func testFrom(t *testing.T, pkgDir, sel string) {
func testFrom(t *testing.T, pkgDir, sel, fn string) {
if sel != "" && !strings.Contains(pkgDir, sel) {
return
}
@@ -85,10 +89,10 @@ func testFrom(t *testing.T, pkgDir, sel string) {
t.Fatal("ReadFile failed:", err)
}
expected := string(b)
testBlockInfo(t, nil, in, expected)
testBlockInfo(t, nil, in, expected, fn)
}
func testBlockInfo(t *testing.T, src any, fname, expected string) {
func testBlockInfo(t *testing.T, src any, fname, expected, fn string) {
t.Helper()
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, fname, src, parser.ParseComments)
@@ -109,7 +113,7 @@ func testBlockInfo(t *testing.T, src any, fname, expected string) {
for _, member := range foo.Members {
switch f := member.(type) {
case *ssa.Function:
if f.Name() == "main" {
if f.Name() == fn {
f.WriteTo(os.Stderr)
infos := Infos(f.Blocks)
if v := resultOf(infos); v != expected {

View File

@@ -141,7 +141,6 @@ func (b Builder) getDefer() *aDefer {
ptr := b.aggregateAlloca(prog.Defer(), zero.impl, link.impl)
deferData := Expr{ptr, prog.DeferPtr()}
b.pthreadSetspecific(key, deferData)
b.SetBlockEx(b.blk, AtEnd, false)
self.defer_ = &aDefer{
key: key,
data: deferData,
@@ -149,6 +148,7 @@ func (b Builder) getDefer() *aDefer {
rundPtr: b.FieldAddr(deferData, 2),
procBlk: self.MakeBlock(),
}
b.SetBlockEx(b.blk, AtEnd, false)
}
return self.defer_
}