From 389750d7d8496b1d863ffe53e252536ec06046ae Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sun, 28 Jul 2024 18:51:07 +0800 Subject: [PATCH 1/4] ssa: panicBlk (todo) --- internal/runtime/z_rt.go | 9 +++-- ssa/eh.go | 83 ++++++++++++++++++++++++---------------- 2 files changed, 55 insertions(+), 37 deletions(-) diff --git a/internal/runtime/z_rt.go b/internal/runtime/z_rt.go index c100ade5..fa43c104 100644 --- a/internal/runtime/z_rt.go +++ b/internal/runtime/z_rt.go @@ -30,6 +30,7 @@ type Defer struct { Addr unsafe.Pointer // sigjmpbuf Bits uintptr Link *Defer + Reth unsafe.Pointer // block address after Rethrow Rund unsafe.Pointer // block address after RunDefers } @@ -82,10 +83,6 @@ func init() { // ----------------------------------------------------------------------------- -func unpackEface(i any) *eface { - return (*eface)(unsafe.Pointer(&i)) -} - // TracePanic prints panic message. func TracePanic(v any) { print("panic: ") @@ -94,6 +91,10 @@ func TracePanic(v any) { } /* +func unpackEface(i any) *eface { + return (*eface)(unsafe.Pointer(&i)) +} + func stringTracef(fp c.FilePtr, format *c.Char, s String) { cs := c.Alloca(uintptr(s.len) + 1) c.Fprintf(fp, format, CStrCopy(cs, s)) diff --git a/ssa/eh.go b/ssa/eh.go index dfbfcb89..28f8ea71 100644 --- a/ssa/eh.go +++ b/ssa/eh.go @@ -86,14 +86,17 @@ func (p Function) deferInitBuilder() (b Builder, next BasicBlock) { } type aDefer struct { - nextBit int // next defer bit - key Expr // pthread TLS key - data Expr // pointer to runtime.Defer - bitsPtr Expr // pointer to defer bits - rundPtr Expr // pointer to RunDefers index - procBlk BasicBlock // deferProc block - runsNext []BasicBlock // next blocks of RunDefers - stmts []func(bits Expr) + nextBit int // next defer bit + key Expr // pthread TLS key + data Expr // pointer to runtime.Defer + bitsPtr Expr // pointer to defer bits + rethPtr Expr // next block of Rethrow + rundPtr Expr // next block of RunDefers + procBlk BasicBlock // deferProc block + panicBlk BasicBlock // panic block (runDefers and rethrow) + rethsNext []BasicBlock // next blocks of Rethrow + rundsNext []BasicBlock // next blocks of RunDefers + stmts []func(bits Expr) } func (p Package) keyInit(name string) { @@ -124,53 +127,60 @@ const ( // 0: addr sigjmpbuf // 1: bits uintptr // 2: link *Defer - // 3: rund voidptr + // 3: reth voidptr: block address after Rethrow + // 4: rund voidptr: block address after RunDefers deferSigjmpbuf = iota deferBits deferLink - deferRund + deferRethrow + deferRunDefers ) func (b Builder) getDefer(kind DoAction) *aDefer { self := b.Func if self.defer_ == nil { // TODO(xsw): check if in pkg.init - var next, rundBlk BasicBlock + var next, panicBlk BasicBlock if kind != DeferAlways { b, next = self.deferInitBuilder() } + prog := b.Prog + blks := self.MakeBlocks(2) + procBlk, rethrowBlk := blks[0], blks[1] + key := b.deferKey() zero := prog.Val(uintptr(0)) link := Expr{b.pthreadGetspecific(key).impl, prog.DeferPtr()} jb := b.AllocaSigjmpBuf() - ptr := b.aggregateAlloca(prog.Defer(), jb.impl, zero.impl, link.impl) + ptr := b.aggregateAlloca(prog.Defer(), jb.impl, zero.impl, link.impl, procBlk.Addr().impl) deferData := Expr{ptr, prog.DeferPtr()} b.pthreadSetspecific(key, deferData) - blks := self.MakeBlocks(2) - procBlk, rethrowBlk := blks[0], blks[1] bitsPtr := b.FieldAddr(deferData, deferBits) - rundPtr := b.FieldAddr(deferData, deferRund) - self.defer_ = &aDefer{ - key: key, - data: deferData, - bitsPtr: bitsPtr, - rundPtr: rundPtr, - procBlk: procBlk, - runsNext: []BasicBlock{rethrowBlk}, - } + rethPtr := b.FieldAddr(deferData, deferRethrow) + rundPtr := b.FieldAddr(deferData, deferRunDefers) + czero := prog.IntVal(0, prog.CInt()) retval := b.Sigsetjmp(jb, czero) if kind != DeferAlways { - rundBlk = self.MakeBlock() + panicBlk = self.MakeBlock() } else { blks = self.MakeBlocks(2) - next, rundBlk = blks[0], blks[1] + next, panicBlk = blks[0], blks[1] + } + b.If(b.BinOp(token.EQL, retval, czero), next, panicBlk) + + self.defer_ = &aDefer{ + key: key, + data: deferData, + bitsPtr: bitsPtr, + rethPtr: rethPtr, + rundPtr: rundPtr, + procBlk: procBlk, + panicBlk: panicBlk, + rethsNext: []BasicBlock{procBlk}, + rundsNext: []BasicBlock{rethrowBlk}, } - b.If(b.BinOp(token.EQL, retval, czero), next, rundBlk) - b.SetBlockEx(rundBlk, AtEnd, false) // exec runDefers and rethrow - b.Store(rundPtr, rethrowBlk.Addr()) - b.Jump(procBlk) b.SetBlockEx(rethrowBlk, AtEnd, false) // rethrow b.Call(b.Pkg.rtFunc("Rethrow"), link) @@ -229,7 +239,7 @@ func (b Builder) Defer(kind DoAction, fn Expr, args ...Expr) { func (b Builder) RunDefers() { self := b.getDefer(DeferInCond) blk := b.Func.MakeBlock() - self.runsNext = append(self.runsNext, blk) + self.rundsNext = append(self.rundsNext, blk) b.Store(self.rundPtr, blk.Addr()) b.Jump(self.procBlk) @@ -243,11 +253,14 @@ func (p Function) endDefer(b Builder) { if self == nil { return } - nexts := self.runsNext + procBlk := self.procBlk + panicBlk := self.panicBlk + rundPtr := self.rundPtr + nexts := self.rundsNext if len(nexts) == 0 { return } - b.SetBlockEx(self.procBlk, AtEnd, true) + b.SetBlockEx(procBlk, AtEnd, true) bits := b.Load(self.bitsPtr) stmts := self.stmts for i := len(stmts) - 1; i >= 0; i-- { @@ -256,7 +269,11 @@ func (p Function) endDefer(b Builder) { link := b.getField(b.Load(self.data), deferLink) b.pthreadSetspecific(self.key, link) - b.IndirectJump(b.Load(self.rundPtr), nexts) + b.IndirectJump(b.Load(rundPtr), nexts) + + b.SetBlockEx(panicBlk, AtEnd, false) // exec runDefers and rethrow + b.Store(rundPtr, nexts[0].Addr()) // nexts[0] is rethrowBlk + b.Jump(procBlk) } // ----------------------------------------------------------------------------- From fa0ce2a14c530f2b04be6b1172b28f72ae18da10 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sun, 28 Jul 2024 18:57:46 +0800 Subject: [PATCH 2/4] ssa: panicBlk use IndirectJump --- ssa/eh.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ssa/eh.go b/ssa/eh.go index 28f8ea71..269dd2a0 100644 --- a/ssa/eh.go +++ b/ssa/eh.go @@ -255,6 +255,7 @@ func (p Function) endDefer(b Builder) { } procBlk := self.procBlk panicBlk := self.panicBlk + rethPtr := self.rethPtr rundPtr := self.rundPtr nexts := self.rundsNext if len(nexts) == 0 { @@ -273,7 +274,7 @@ func (p Function) endDefer(b Builder) { b.SetBlockEx(panicBlk, AtEnd, false) // exec runDefers and rethrow b.Store(rundPtr, nexts[0].Addr()) // nexts[0] is rethrowBlk - b.Jump(procBlk) + b.IndirectJump(b.Load(rethPtr), self.rethsNext) } // ----------------------------------------------------------------------------- From 5007d49c83b8c4f563fc2af3e4a16280ea18066b Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sun, 28 Jul 2024 19:53:04 +0800 Subject: [PATCH 3/4] ssa: endDefer --- ssa/eh.go | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/ssa/eh.go b/ssa/eh.go index 269dd2a0..2e996101 100644 --- a/ssa/eh.go +++ b/ssa/eh.go @@ -94,7 +94,6 @@ type aDefer struct { rundPtr Expr // next block of RunDefers procBlk BasicBlock // deferProc block panicBlk BasicBlock // panic block (runDefers and rethrow) - rethsNext []BasicBlock // next blocks of Rethrow rundsNext []BasicBlock // next blocks of RunDefers stmts []func(bits Expr) } @@ -178,7 +177,6 @@ func (b Builder) getDefer(kind DoAction) *aDefer { rundPtr: rundPtr, procBlk: procBlk, panicBlk: panicBlk, - rethsNext: []BasicBlock{procBlk}, rundsNext: []BasicBlock{rethrowBlk}, } @@ -253,28 +251,42 @@ func (p Function) endDefer(b Builder) { if self == nil { return } - procBlk := self.procBlk - panicBlk := self.panicBlk - rethPtr := self.rethPtr - rundPtr := self.rundPtr nexts := self.rundsNext if len(nexts) == 0 { return } - b.SetBlockEx(procBlk, AtEnd, true) - bits := b.Load(self.bitsPtr) - stmts := self.stmts - for i := len(stmts) - 1; i >= 0; i-- { - stmts[i](bits) - } + rethrowBlk := nexts[0] + procBlk := self.procBlk + panicBlk := self.panicBlk + rethPtr := self.rethPtr + rundPtr := self.rundPtr + bitsPtr := self.bitsPtr + + stmts := self.stmts + n := len(stmts) + rethsNext := make([]BasicBlock, n+1) + blks := p.MakeBlocks(n - 1) + copy(rethsNext[1:], blks) + rethsNext[0] = rethrowBlk + rethsNext[n] = procBlk + + for i := n - 1; i >= 0; i-- { + rethNext := rethsNext[i] + b.SetBlockEx(rethsNext[i+1], AtEnd, true) + b.Store(rethPtr, rethNext.Addr()) + stmts[i](b.Load(bitsPtr)) + if i != 0 { + b.Jump(rethNext) + } + } link := b.getField(b.Load(self.data), deferLink) b.pthreadSetspecific(self.key, link) b.IndirectJump(b.Load(rundPtr), nexts) - b.SetBlockEx(panicBlk, AtEnd, false) // exec runDefers and rethrow - b.Store(rundPtr, nexts[0].Addr()) // nexts[0] is rethrowBlk - b.IndirectJump(b.Load(rethPtr), self.rethsNext) + b.SetBlockEx(panicBlk, AtEnd, false) // panicBlk: exec runDefers and rethrow + b.Store(rundPtr, rethrowBlk.Addr()) + b.IndirectJump(b.Load(rethPtr), rethsNext) } // ----------------------------------------------------------------------------- From 0d468e0df43224ceb3d5ff4baea7f17a610b9539 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sun, 28 Jul 2024 20:00:53 +0800 Subject: [PATCH 4/4] cl/_testgo: defer5 --- cl/_testgo/defer5/in.go | 17 +++++++++++++++++ cl/_testgo/defer5/out.ll | 1 + 2 files changed, 18 insertions(+) create mode 100644 cl/_testgo/defer5/in.go create mode 100644 cl/_testgo/defer5/out.ll diff --git a/cl/_testgo/defer5/in.go b/cl/_testgo/defer5/in.go new file mode 100644 index 00000000..114e7fb9 --- /dev/null +++ b/cl/_testgo/defer5/in.go @@ -0,0 +1,17 @@ +package main + +func main() { + defer println("A") + defer func() { + if e := recover(); e != nil { + println("in defer 1") + panic("panic in defer 1") + } + }() + defer func() { + println("in defer 2") + panic("panic in defer 2") + }() + defer println("B") + panic("panic in main") +} diff --git a/cl/_testgo/defer5/out.ll b/cl/_testgo/defer5/out.ll new file mode 100644 index 00000000..1c8a0e79 --- /dev/null +++ b/cl/_testgo/defer5/out.ll @@ -0,0 +1 @@ +; \ No newline at end of file