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 %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
store ptr %3, ptr %6, align 8 store ptr %3, ptr %6, align 8
%7 = call i32 @pthread_setspecific(ptr %2, ptr %4) %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 i32 %0, ptr @__llgo_argc, align 4
store ptr %1, ptr @__llgo_argv, align 8 store ptr %1, ptr @__llgo_argv, align 8
call void @"github.com/goplus/llgo/internal/runtime.init"() call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.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 %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 %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %10, i32 0, i32 0
store ptr @0, ptr %11, align 8 store ptr @0, ptr %11, align 8

View File

@@ -37,8 +37,12 @@ import (
) )
func TestTestdefer(t *testing.T) { func TestTestdefer(t *testing.T) {
// debug = true fromDir(t, "", "../_testdefer", func(name string) string {
fromDir(t, "", "../_testdefer") if strings.HasPrefix(name, "firstloop") {
return "Loop"
}
return "main"
})
} }
func TestFirstLoop(t *testing.T) { 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() dir, err := os.Getwd()
if err != nil { if err != nil {
t.Fatal("Getwd failed:", err) t.Fatal("Getwd failed:", err)
@@ -68,12 +72,12 @@ func fromDir(t *testing.T, sel, relDir string) {
continue continue
} }
t.Run(name, func(t *testing.T) { 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) { if sel != "" && !strings.Contains(pkgDir, sel) {
return return
} }
@@ -85,10 +89,10 @@ func testFrom(t *testing.T, pkgDir, sel string) {
t.Fatal("ReadFile failed:", err) t.Fatal("ReadFile failed:", err)
} }
expected := string(b) 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() t.Helper()
fset := token.NewFileSet() fset := token.NewFileSet()
f, err := parser.ParseFile(fset, fname, src, parser.ParseComments) 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 { for _, member := range foo.Members {
switch f := member.(type) { switch f := member.(type) {
case *ssa.Function: case *ssa.Function:
if f.Name() == "main" { if f.Name() == fn {
f.WriteTo(os.Stderr) f.WriteTo(os.Stderr)
infos := Infos(f.Blocks) infos := Infos(f.Blocks)
if v := resultOf(infos); v != expected { 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) ptr := b.aggregateAlloca(prog.Defer(), zero.impl, link.impl)
deferData := Expr{ptr, prog.DeferPtr()} deferData := Expr{ptr, prog.DeferPtr()}
b.pthreadSetspecific(key, deferData) b.pthreadSetspecific(key, deferData)
b.SetBlockEx(b.blk, AtEnd, false)
self.defer_ = &aDefer{ self.defer_ = &aDefer{
key: key, key: key,
data: deferData, data: deferData,
@@ -149,6 +148,7 @@ func (b Builder) getDefer() *aDefer {
rundPtr: b.FieldAddr(deferData, 2), rundPtr: b.FieldAddr(deferData, 2),
procBlk: self.MakeBlock(), procBlk: self.MakeBlock(),
} }
b.SetBlockEx(b.blk, AtEnd, false)
} }
return self.defer_ return self.defer_
} }