mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.typeparams] Revert "[dev.typeparams] runtime,cmd/compile,cmd/link: replace jmpdefer with a loop"
This reverts CL 227652. I'm reverting CL 337651 and this builds on top of it. Change-Id: I03ce363be44c2a3defff2e43e7b1aad83386820d Reviewed-on: https://go-review.googlesource.com/c/go/+/338709 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
parent
40e561d933
commit
e3e9f0bb2d
31 changed files with 324 additions and 39 deletions
|
|
@ -129,6 +129,8 @@ var (
|
|||
morestackNoCtxt *obj.LSym
|
||||
gcWriteBarrier *obj.LSym
|
||||
sigpanic *obj.LSym
|
||||
deferreturn *obj.LSym
|
||||
jmpdefer *obj.LSym
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -141,6 +143,10 @@ func instinit(ctxt *obj.Link) {
|
|||
morestackNoCtxt = ctxt.Lookup("runtime.morestack_noctxt")
|
||||
gcWriteBarrier = ctxt.LookupABI("runtime.gcWriteBarrier", obj.ABIInternal)
|
||||
sigpanic = ctxt.LookupABI("runtime.sigpanic", obj.ABIInternal)
|
||||
deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal)
|
||||
// jmpdefer is defined in assembly as ABI0. The compiler will
|
||||
// generate a direct ABI0 call from Go, so look for that.
|
||||
jmpdefer = ctxt.LookupABI(`"".jmpdefer`, obj.ABI0)
|
||||
}
|
||||
|
||||
func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
|
||||
|
|
@ -417,6 +423,12 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
|
|||
pcAfterCall-- // sigpanic expects to be called without advancing the pc
|
||||
}
|
||||
|
||||
// jmpdefer manipulates the return address on the stack so deferreturn gets called repeatedly.
|
||||
// Model this in WebAssembly with a loop.
|
||||
if call.To.Sym == deferreturn {
|
||||
p = appendp(p, ALoop)
|
||||
}
|
||||
|
||||
// SP -= 8
|
||||
p = appendp(p, AGet, regAddr(REG_SP))
|
||||
p = appendp(p, AI32Const, constAddr(8))
|
||||
|
|
@ -467,6 +479,15 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
|
|||
break
|
||||
}
|
||||
|
||||
// jmpdefer removes the frame of deferreturn from the Go stack.
|
||||
// However, its WebAssembly function still returns normally,
|
||||
// so we need to return from deferreturn without removing its
|
||||
// stack frame (no RET), because the frame is already gone.
|
||||
if call.To.Sym == jmpdefer {
|
||||
p = appendp(p, AReturn)
|
||||
break
|
||||
}
|
||||
|
||||
// return value of call is on the top of the stack, indicating whether to unwind the WebAssembly stack
|
||||
if call.As == ACALLNORESUME && call.To.Sym != sigpanic { // sigpanic unwinds the stack, but it never resumes
|
||||
// trying to unwind WebAssembly stack but call has no resume point, terminate with error
|
||||
|
|
@ -479,6 +500,21 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
|
|||
unwindExitBranches = append(unwindExitBranches, p)
|
||||
}
|
||||
|
||||
// jump to before the call if jmpdefer has reset the return address to the call's PC
|
||||
if call.To.Sym == deferreturn {
|
||||
// get PC_B from -8(SP)
|
||||
p = appendp(p, AGet, regAddr(REG_SP))
|
||||
p = appendp(p, AI32Const, constAddr(8))
|
||||
p = appendp(p, AI32Sub)
|
||||
p = appendp(p, AI32Load16U, constAddr(0))
|
||||
p = appendp(p, ATee, regAddr(REG_PC_B))
|
||||
|
||||
p = appendp(p, AI32Const, constAddr(call.Pc))
|
||||
p = appendp(p, AI32Eq)
|
||||
p = appendp(p, ABrIf, constAddr(0))
|
||||
p = appendp(p, AEnd) // end of Loop
|
||||
}
|
||||
|
||||
case obj.ARET, ARETUNWIND:
|
||||
ret := *p
|
||||
p.As = obj.ANOP
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue