diff --git a/cl/_testdefer/firstloop1/in.go b/cl/_testdefer/firstloop1/in.go new file mode 100644 index 00000000..d82d7663 --- /dev/null +++ b/cl/_testdefer/firstloop1/in.go @@ -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 + } + } +} diff --git a/cl/_testdefer/firstloop1/out.txt b/cl/_testdefer/firstloop1/out.txt new file mode 100644 index 00000000..92182937 --- /dev/null +++ b/cl/_testdefer/firstloop1/out.txt @@ -0,0 +1,7 @@ + 0: always + 6: cond + 3: loop + 1: loop + 4: loop + 2: cond + 5: cond diff --git a/cl/_testdefer/firstloop2/in.go b/cl/_testdefer/firstloop2/in.go new file mode 100644 index 00000000..bf611e58 --- /dev/null +++ b/cl/_testdefer/firstloop2/in.go @@ -0,0 +1,7 @@ +package foo + +func Loop() { + for i := 0; i < 3; i++ { + println(i) + } +} diff --git a/cl/_testdefer/firstloop2/out.txt b/cl/_testdefer/firstloop2/out.txt new file mode 100644 index 00000000..98b1e224 --- /dev/null +++ b/cl/_testdefer/firstloop2/out.txt @@ -0,0 +1,4 @@ + 0: always + 3: loop + 1: loop + 2: always diff --git a/cl/_testgo/defer/out.ll b/cl/_testgo/defer/out.ll index dddf331e..451897e6 100644 --- a/cl/_testgo/defer/out.ll +++ b/cl/_testgo/defer/out.ll @@ -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 diff --git a/cl/blocks/block_test.go b/cl/blocks/block_test.go index 2cad3c86..1ad8f7da 100644 --- a/cl/blocks/block_test.go +++ b/cl/blocks/block_test.go @@ -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 { diff --git a/ssa/eh.go b/ssa/eh.go index eb6d3be7..4367da5e 100644 --- a/ssa/eh.go +++ b/ssa/eh.go @@ -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_ }