deferInit bugfix

This commit is contained in:
xushiwei
2024-06-03 01:32:25 +08:00
parent 56a5a7d72e
commit 2c799a8ccf
6 changed files with 63 additions and 95 deletions

View File

@@ -4,24 +4,15 @@ func f(s string) bool {
return len(s) > 2 return len(s) > 2
} }
func fail() {
panic("error")
}
func main() { func main() {
defer func() { defer func() {
println("hi") println("hi")
/*
if e := recover(); e != nil {
println(e.(string))
}
*/
}() }()
if s := "hello"; f(s) { if s := "hello"; f(s) {
defer println(s) defer println(s)
} else { } else {
defer println("world") defer println("world")
fail() return
} }
defer println("bye") defer println("bye")
} }

View File

@@ -2,20 +2,17 @@
source_filename = "main" source_filename = "main"
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } %"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
%"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr }
%"github.com/goplus/llgo/internal/runtime.Defer" = type { { ptr, ptr }, i64, ptr, i64 } %"github.com/goplus/llgo/internal/runtime.Defer" = type { { ptr, ptr }, i64, ptr, i64 }
@"main.init$guard" = global ptr null @"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [6 x i8] c"error\00", align 1
@_llgo_string = linkonce global ptr null
@__llgo_argc = global ptr null @__llgo_argc = global ptr null
@__llgo_argv = global ptr null @__llgo_argv = global ptr null
@__llgo_defer = linkonce global ptr null @__llgo_defer = linkonce global ptr null
@0 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
@1 = private unnamed_addr constant [6 x i8] c"hello\00", align 1 @1 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
@2 = private unnamed_addr constant [6 x i8] c"hello\00", align 1 @2 = private unnamed_addr constant [4 x i8] c"bye\00", align 1
@3 = private unnamed_addr constant [4 x i8] c"bye\00", align 1 @3 = private unnamed_addr constant [6 x i8] c"world\00", align 1
@4 = private unnamed_addr constant [6 x i8] c"world\00", align 1 @4 = private unnamed_addr constant [3 x i8] c"hi\00", align 1
@5 = private unnamed_addr constant [3 x i8] c"hi\00", align 1
define i1 @main.f(%"github.com/goplus/llgo/internal/runtime.String" %0) { define i1 @main.f(%"github.com/goplus/llgo/internal/runtime.String" %0) {
_llgo_0: _llgo_0:
@@ -24,27 +21,6 @@ _llgo_0:
ret i1 %2 ret i1 %2
} }
define void @main.fail() {
_llgo_0:
%0 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 0
store ptr @0, ptr %1, align 8
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 1
store i64 5, ptr %2, align 4
%3 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %0, align 8
%4 = load ptr, ptr @_llgo_string, align 8
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %3, ptr %5, align 8
%6 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %6, i32 0, i32 0
store ptr %4, ptr %7, align 8
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %6, i32 0, i32 1
store ptr %5, ptr %8, align 8
%9 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %6, align 8
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.eface" %9)
unreachable
}
define void @main.init() { define void @main.init() {
_llgo_0: _llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1 %0 = load i1, ptr @"main.init$guard", align 1
@@ -82,12 +58,12 @@ _llgo_0:
store i64 %12, ptr %9, align 4 store i64 %12, ptr %9, align 4
%13 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %13 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %13, i32 0, i32 0 %14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %13, i32 0, i32 0
store ptr @1, ptr %14, align 8 store ptr @0, ptr %14, align 8
%15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %13, i32 0, i32 1 %15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %13, i32 0, i32 1
store i64 5, ptr %15, align 4 store i64 5, ptr %15, align 4
%16 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %13, align 8 %16 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %13, align 8
%17 = call i1 @main.f(%"github.com/goplus/llgo/internal/runtime.String" %16) %17 = call i1 @main.f(%"github.com/goplus/llgo/internal/runtime.String" %16)
br i1 %17, label %_llgo_2, label %_llgo_4 br i1 %17, label %_llgo_2, label %_llgo_3
_llgo_1: ; No predecessors! _llgo_1: ; No predecessors!
ret i32 0 ret i32 0
@@ -95,19 +71,16 @@ _llgo_1: ; No predecessors!
_llgo_2: ; preds = %_llgo_0 _llgo_2: ; preds = %_llgo_0
%18 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %18 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 0 %19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 0
store ptr @2, ptr %19, align 8 store ptr @1, ptr %19, align 8
%20 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 1 %20 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 1
store i64 5, ptr %20, align 4 store i64 5, ptr %20, align 4
%21 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %18, align 8 %21 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %18, align 8
%22 = load i64, ptr %9, align 4 %22 = load i64, ptr %9, align 4
%23 = or i64 %22, 2 %23 = or i64 %22, 2
store i64 %23, ptr %9, align 4 store i64 %23, ptr %9, align 4
br label %_llgo_3
_llgo_3: ; preds = %_llgo_4, %_llgo_2
%24 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %24 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%25 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 0 %25 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 0
store ptr @3, ptr %25, align 8 store ptr @2, ptr %25, align 8
%26 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 1 %26 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 1
store i64 3, ptr %26, align 4 store i64 3, ptr %26, align 4
%27 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %24, align 8 %27 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %24, align 8
@@ -115,36 +88,39 @@ _llgo_3: ; preds = %_llgo_4, %_llgo_2
%29 = or i64 %28, 4 %29 = or i64 %28, 4
store i64 %29, ptr %9, align 4 store i64 %29, ptr %9, align 4
store i64 0, ptr %10, align 4 store i64 0, ptr %10, align 4
br label %_llgo_5 br label %_llgo_4
_llgo_4: ; preds = %_llgo_0 _llgo_3: ; preds = %_llgo_0
%30 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %30 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%31 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %30, i32 0, i32 0 %31 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %30, i32 0, i32 0
store ptr @4, ptr %31, align 8 store ptr @3, ptr %31, align 8
%32 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %30, i32 0, i32 1 %32 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %30, i32 0, i32 1
store i64 5, ptr %32, align 4 store i64 5, ptr %32, align 4
%33 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %30, align 8 %33 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %30, align 8
%34 = load i64, ptr %9, align 4 %34 = load i64, ptr %9, align 4
%35 = or i64 %34, 8 %35 = or i64 %34, 8
store i64 %35, ptr %9, align 4 store i64 %35, ptr %9, align 4
call void @main.fail() store i64 1, ptr %10, align 4
br label %_llgo_3 br label %_llgo_4
_llgo_5: ; preds = %_llgo_3 _llgo_4: ; preds = %_llgo_3, %_llgo_2
%36 = load i64, ptr %9, align 4 %36 = load i64, ptr %9, align 4
%37 = and i64 %36, 8 %37 = and i64 %36, 8
%38 = icmp ne i64 %37, 0 %38 = icmp ne i64 %37, 0
br i1 %38, label %_llgo_7, label %_llgo_8 br i1 %38, label %_llgo_7, label %_llgo_8
_llgo_5: ; preds = %_llgo_14
ret i32 0
_llgo_6: ; preds = %_llgo_14 _llgo_6: ; preds = %_llgo_14
ret i32 0 ret i32 0
_llgo_7: ; preds = %_llgo_5 _llgo_7: ; preds = %_llgo_4
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %33) call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %33)
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
br label %_llgo_8 br label %_llgo_8
_llgo_8: ; preds = %_llgo_7, %_llgo_5 _llgo_8: ; preds = %_llgo_7, %_llgo_4
%39 = and i64 %36, 4 %39 = and i64 %36, 4
%40 = icmp ne i64 %39, 0 %40 = icmp ne i64 %39, 0
br i1 %40, label %_llgo_9, label %_llgo_10 br i1 %40, label %_llgo_9, label %_llgo_10
@@ -178,47 +154,18 @@ _llgo_14: ; preds = %_llgo_13, %_llgo_12
%46 = extractvalue %"github.com/goplus/llgo/internal/runtime.Defer" %45, 2 %46 = extractvalue %"github.com/goplus/llgo/internal/runtime.Defer" %45, 2
%47 = call i32 @pthread_setspecific(ptr %2, ptr %46) %47 = call i32 @pthread_setspecific(ptr %2, ptr %46)
%48 = load i64, ptr %10, align 4 %48 = load i64, ptr %10, align 4
switch i64 %48, label %_llgo_6 [ switch i64 %48, label %_llgo_5 [
i64 1, label %_llgo_6
] ]
} }
define void @"main.init$after"() {
_llgo_0:
%0 = load ptr, ptr @_llgo_string, align 8
%1 = icmp eq ptr %0, null
br i1 %1, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24)
store ptr %2, ptr @_llgo_string, align 8
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
%3 = load ptr, ptr @__llgo_defer, align 8
%4 = icmp eq ptr %3, null
br i1 %4, label %_llgo_3, label %_llgo_4
_llgo_3: ; preds = %_llgo_2
%5 = call i32 @pthread_key_create(ptr @__llgo_defer, ptr null)
br label %_llgo_4
_llgo_4: ; preds = %_llgo_3, %_llgo_2
ret void
}
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64)
declare void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.eface")
declare void @"github.com/goplus/llgo/internal/runtime.init"() declare void @"github.com/goplus/llgo/internal/runtime.init"()
define void @"main.main$1"() { define void @"main.main$1"() {
_llgo_0: _llgo_0:
%0 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %0 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 0 %1 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 0
store ptr @5, ptr %1, align 8 store ptr @4, ptr %1, align 8
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 1 %2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 1
store i64 2, ptr %2, align 4 store i64 2, ptr %2, align 4
%3 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %0, align 8 %3 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %0, align 8
@@ -235,4 +182,18 @@ declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com
declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8) declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8)
define void @"main.init$after"() {
_llgo_0:
%0 = load ptr, ptr @__llgo_defer, align 8
%1 = icmp eq ptr %0, null
br i1 %1, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
%2 = call i32 @pthread_key_create(ptr @__llgo_defer, ptr null)
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
declare i32 @pthread_key_create(ptr, ptr) declare i32 @pthread_key_create(ptr, ptr)

View File

@@ -247,10 +247,12 @@ func newParams(fn Type, prog Program) (params []Type, hasVArg bool) {
return return
} }
/*
// Name returns the function's name. // Name returns the function's name.
func (p Function) Name() string { func (p Function) Name() string {
return p.impl.Name() return p.impl.Name()
} }
*/
// Params returns the function's ith parameter. // Params returns the function's ith parameter.
func (p Function) Param(i int) Expr { func (p Function) Param(i int) Expr {

View File

@@ -131,14 +131,14 @@ type aProgram struct {
rtSliceTy llvm.Type rtSliceTy llvm.Type
rtMapTy llvm.Type rtMapTy llvm.Type
anyTy Type anyTy Type
voidTy Type voidTy Type
voidPtr Type voidPtr Type
voidPPtr Type voidPPtr Type
boolTy Type boolTy Type
cstrTy Type cstrTy Type
cintTy Type cintTy Type
cintPtr Type //cintPtr Type
stringTy Type stringTy Type
uintptrTy Type uintptrTy Type
intTy Type intTy Type
@@ -444,6 +444,7 @@ func (p Program) Any() Type {
return p.anyTy return p.anyTy
} }
/*
// Eface returns the empty interface type. // Eface returns the empty interface type.
// It is equivalent to Any. // It is equivalent to Any.
func (p Program) Eface() Type { func (p Program) Eface() Type {
@@ -457,6 +458,7 @@ func (p Program) CIntPtr() Type {
} }
return p.cintPtr return p.cintPtr
} }
*/
// CInt returns c.Int type. // CInt returns c.Int type.
func (p Program) CInt() Type { func (p Program) CInt() Type {
@@ -649,13 +651,13 @@ func (p Package) afterBuilder() Builder {
// AfterInit is called after the package is initialized (init all packages that depends on). // AfterInit is called after the package is initialized (init all packages that depends on).
func (p Package) AfterInit(b Builder, ret BasicBlock) { func (p Package) AfterInit(b Builder, ret BasicBlock) {
p.deferInit()
doAfterb := p.afterb != nil doAfterb := p.afterb != nil
doPyLoadModSyms := p.pyHasModSyms() doPyLoadModSyms := p.pyHasModSyms()
if doAfterb || doPyLoadModSyms { if doAfterb || doPyLoadModSyms {
b.SetBlockEx(ret, afterInit, false) b.SetBlockEx(ret, afterInit, false)
if doAfterb { if doAfterb {
afterb := Builder(p.afterb) afterb := Builder(p.afterb)
p.deferInit(afterb)
afterb.Return() afterb.Return()
b.Call(afterb.Func.Expr) b.Call(afterb.Func.Expr)
} }

View File

@@ -27,6 +27,16 @@ import (
"github.com/goplus/llvm" "github.com/goplus/llvm"
) )
func TestEndDefer(t *testing.T) {
prog := NewProgram(nil)
pkg := prog.NewPackage("foo", "foo")
sigMain := types.NewSignatureType(nil, nil, nil, nil, nil, false)
fn := pkg.NewFunc("main", sigMain, InC)
b := fn.MakeBody(1)
fn.defer_ = &aDefer{}
fn.endDefer(b)
}
func TestUnsafeString(t *testing.T) { func TestUnsafeString(t *testing.T) {
prog := NewProgram(nil) prog := NewProgram(nil)
prog.SetRuntime(func() *types.Package { prog.SetRuntime(func() *types.Package {
@@ -187,6 +197,7 @@ func TestVar(t *testing.T) {
if pkg.NewVar("a", types.Typ[types.Int], InGo) != a { if pkg.NewVar("a", types.Typ[types.Int], InGo) != a {
t.Fatal("NewVar(a) failed") t.Fatal("NewVar(a) failed")
} }
pkg.NewVarEx("a", prog.Type(types.Typ[types.Int], InGo))
a.Init(prog.Val(100)) a.Init(prog.Val(100))
b := pkg.NewVar("b", types.Typ[types.Int], InGo) b := pkg.NewVar("b", types.Typ[types.Int], InGo)
b.Init(a.Expr) b.Init(a.Expr)

View File

@@ -163,7 +163,7 @@ func (p Program) tyDeferFunc() *types.Signature {
} }
*/ */
func (p Package) deferInit(b Builder) { func (p Package) deferInit() {
keyVar := p.VarOf(deferKey) keyVar := p.VarOf(deferKey)
if keyVar == nil { if keyVar == nil {
return return
@@ -173,6 +173,7 @@ func (p Package) deferInit(b Builder) {
keyVar.Init(keyNil) keyVar.Init(keyNil)
keyVar.impl.SetLinkage(llvm.LinkOnceAnyLinkage) keyVar.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
b := p.afterBuilder()
eq := b.BinOp(token.EQL, b.Load(keyVar.Expr), keyNil) eq := b.BinOp(token.EQL, b.Load(keyVar.Expr), keyNil)
b.IfThen(eq, func() { b.IfThen(eq, func() {
b.pthreadKeyCreate(keyVar.Expr, prog.Null(prog.VoidPtr())) b.pthreadKeyCreate(keyVar.Expr, prog.Null(prog.VoidPtr()))