ssa: rely on runtime thread defer TLS

This commit is contained in:
Li Jie
2025-10-15 16:31:43 +08:00
parent 30bde9f6b5
commit cb173f91d0
5 changed files with 9 additions and 37 deletions

View File

@@ -1 +1 @@
; ;

View File

@@ -1 +1 @@
; ;

View File

@@ -29,6 +29,11 @@ func SetThreadDefer(head *Defer) {
deferTLS.Set(head) deferTLS.Set(head)
} }
// GetThreadDefer returns the current thread's defer chain head.
func GetThreadDefer() *Defer {
return deferTLS.Get()
}
// ClearThreadDefer resets the current thread's defer chain to nil. // ClearThreadDefer resets the current thread's defer chain to nil.
func ClearThreadDefer() { func ClearThreadDefer() {
deferTLS.Clear() deferTLS.Clear()

View File

@@ -149,10 +149,6 @@ func (b Builder) Longjmp(jb, retval Expr) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
const (
deferKey = "__llgo_defer"
)
func (p Function) deferInitBuilder() (b Builder, next BasicBlock) { func (p Function) deferInitBuilder() (b Builder, next BasicBlock) {
b = p.NewBuilder() b = p.NewBuilder()
next = b.setBlockMoveLast(p.blks[0]) next = b.setBlockMoveLast(p.blks[0])
@@ -162,7 +158,6 @@ func (p Function) deferInitBuilder() (b Builder, next BasicBlock) {
type aDefer struct { type aDefer struct {
nextBit int // next defer bit nextBit int // next defer bit
key Expr // pthread TLS key
data Expr // pointer to runtime.Defer data Expr // pointer to runtime.Defer
bitsPtr Expr // pointer to defer bits bitsPtr Expr // pointer to defer bits
rethPtr Expr // next block of Rethrow rethPtr Expr // next block of Rethrow
@@ -174,30 +169,6 @@ type aDefer struct {
stmts []func(bits Expr) stmts []func(bits Expr)
} }
func (p Package) keyInit(name string) {
keyVar := p.VarOf(name)
if keyVar == nil {
return
}
prog := p.Prog
keyVar.InitNil()
keyVar.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
b := p.afterBuilder()
eq := b.BinOp(token.EQL, b.Load(keyVar.Expr), prog.IntVal(0, prog.CInt()))
b.IfThen(eq, func() {
b.pthreadKeyCreate(keyVar.Expr, prog.Nil(prog.VoidPtr()))
})
}
func (p Package) newKey(name string) Global {
return p.NewVarEx(name, p.Prog.CIntPtr())
}
func (b Builder) deferKey() Expr {
return b.Load(b.Pkg.newKey(deferKey).Expr)
}
const ( const (
// 0: addr sigjmpbuf // 0: addr sigjmpbuf
// 1: bits uintptr // 1: bits uintptr
@@ -230,9 +201,8 @@ func (b Builder) getDefer(kind DoAction) *aDefer {
blks := self.MakeBlocks(2) blks := self.MakeBlocks(2)
procBlk, rethrowBlk := blks[0], blks[1] procBlk, rethrowBlk := blks[0], blks[1]
key := b.deferKey()
zero := prog.Val(uintptr(0)) zero := prog.Val(uintptr(0))
link := Expr{b.pthreadGetspecific(key).impl, prog.DeferPtr()} link := b.Call(b.Pkg.rtFunc("GetThreadDefer"))
jb := b.AllocaSigjmpBuf() jb := b.AllocaSigjmpBuf()
ptr := b.aggregateAllocU(prog.Defer(), jb.impl, zero.impl, link.impl, procBlk.Addr().impl) ptr := b.aggregateAllocU(prog.Defer(), jb.impl, zero.impl, link.impl, procBlk.Addr().impl)
deferData := Expr{ptr, prog.DeferPtr()} deferData := Expr{ptr, prog.DeferPtr()}
@@ -256,7 +226,6 @@ func (b Builder) getDefer(kind DoAction) *aDefer {
b.If(b.BinOp(token.EQL, retval, czero), next, panicBlk) b.If(b.BinOp(token.EQL, retval, czero), next, panicBlk)
self.defer_ = &aDefer{ self.defer_ = &aDefer{
key: key,
data: deferData, data: deferData,
bitsPtr: bitsPtr, bitsPtr: bitsPtr,
rethPtr: rethPtr, rethPtr: rethPtr,
@@ -281,8 +250,7 @@ func (b Builder) getDefer(kind DoAction) *aDefer {
// DeferData returns the defer data (*runtime.Defer). // DeferData returns the defer data (*runtime.Defer).
func (b Builder) DeferData() Expr { func (b Builder) DeferData() Expr {
key := b.deferKey() return b.Call(b.Pkg.rtFunc("GetThreadDefer"))
return Expr{b.pthreadGetspecific(key).impl, b.Prog.DeferPtr()}
} }
// Defer emits a defer instruction. // Defer emits a defer instruction.

View File

@@ -798,7 +798,6 @@ 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.keyInit(deferKey)
doAfterb := p.afterb != nil doAfterb := p.afterb != nil
doPyLoadModSyms := p.pyHasModSyms() doPyLoadModSyms := p.pyHasModSyms()
if doAfterb || doPyLoadModSyms { if doAfterb || doPyLoadModSyms {