llgo/ssa: getDefer fix
This commit is contained in:
16
cl/_testdefer/firstloop1/in.go
Normal file
16
cl/_testdefer/firstloop1/in.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
cl/_testdefer/firstloop1/out.txt
Normal file
7
cl/_testdefer/firstloop1/out.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
0: always
|
||||||
|
6: cond
|
||||||
|
3: loop
|
||||||
|
1: loop
|
||||||
|
4: loop
|
||||||
|
2: cond
|
||||||
|
5: cond
|
||||||
7
cl/_testdefer/firstloop2/in.go
Normal file
7
cl/_testdefer/firstloop2/in.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
func Loop() {
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
println(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
4
cl/_testdefer/firstloop2/out.txt
Normal file
4
cl/_testdefer/firstloop2/out.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
0: always
|
||||||
|
3: loop
|
||||||
|
1: loop
|
||||||
|
2: always
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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_
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user