cmd/internal/obj: rip out argp adjustment for wrapper frames

The previous CL made this adjustment unnecessary. The argp field
is no longer used by the runtime.

Change-Id: I3491eeef4103c6653ec345d604c0acd290af9e8f
Reviewed-on: https://go-review.googlesource.com/c/go/+/685356
Reviewed-by: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
Keith Randall 2025-07-01 15:00:13 -07:00
parent 7b50024330
commit 6f6c6c5782
11 changed files with 8 additions and 842 deletions

View file

@ -350,117 +350,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p.To.Reg = REGSP p.To.Reg = REGSP
p.Spadj = autosize p.Spadj = autosize
if cursym.Func().Text.From.Sym.Wrapper() {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOVW g_panic(g), R1
// CMP $0, R1
// B.NE checkargp
// end:
// NOP
// ... function ...
// checkargp:
// MOVW panic_argp(R1), R2
// ADD $(autosize+4), R13, R3
// CMP R2, R3
// B.NE end
// ADD $4, R13, R4
// MOVW R4, panic_argp(R1)
// B end
//
// The NOP is needed to give the jumps somewhere to land.
// It is a liblink NOP, not an ARM NOP: it encodes to 0 instruction bytes.
p = obj.Appendp(p, newprog)
p.As = AMOVW
p.From.Type = obj.TYPE_MEM
p.From.Reg = REGG
p.From.Offset = 4 * int64(ctxt.Arch.PtrSize) // G.panic
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R1
p = obj.Appendp(p, newprog)
p.As = ACMP
p.From.Type = obj.TYPE_CONST
p.From.Offset = 0
p.Reg = REG_R1
// B.NE checkargp
bne := obj.Appendp(p, newprog)
bne.As = ABNE
bne.To.Type = obj.TYPE_BRANCH
// end: NOP
end := obj.Appendp(bne, newprog)
end.As = obj.ANOP
// find end of function
var last *obj.Prog
for last = end; last.Link != nil; last = last.Link {
}
// MOVW panic_argp(R1), R2
mov := obj.Appendp(last, newprog)
mov.As = AMOVW
mov.From.Type = obj.TYPE_MEM
mov.From.Reg = REG_R1
mov.From.Offset = 0 // Panic.argp
mov.To.Type = obj.TYPE_REG
mov.To.Reg = REG_R2
// B.NE branch target is MOVW above
bne.To.SetTarget(mov)
// ADD $(autosize+4), R13, R3
p = obj.Appendp(mov, newprog)
p.As = AADD
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(autosize) + 4
p.Reg = REG_R13
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R3
// CMP R2, R3
p = obj.Appendp(p, newprog)
p.As = ACMP
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_R2
p.Reg = REG_R3
// B.NE end
p = obj.Appendp(p, newprog)
p.As = ABNE
p.To.Type = obj.TYPE_BRANCH
p.To.SetTarget(end)
// ADD $4, R13, R4
p = obj.Appendp(p, newprog)
p.As = AADD
p.From.Type = obj.TYPE_CONST
p.From.Offset = 4
p.Reg = REG_R13
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R4
// MOVW R4, panic_argp(R1)
p = obj.Appendp(p, newprog)
p.As = AMOVW
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_R4
p.To.Type = obj.TYPE_MEM
p.To.Reg = REG_R1
p.To.Offset = 0 // Panic.argp
// B end
p = obj.Appendp(p, newprog)
p.As = AB
p.To.Type = obj.TYPE_BRANCH
p.To.SetTarget(end)
// reset for subsequent passes
p = end
}
case obj.ARET: case obj.ARET:
nocache(p) nocache(p)
if cursym.Func().Text.Mark&LEAF != 0 { if cursym.Func().Text.Mark&LEAF != 0 {

View file

@ -733,111 +733,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q1.To.Type = obj.TYPE_REG q1.To.Type = obj.TYPE_REG
q1.To.Reg = REGFP q1.To.Reg = REGFP
if c.cursym.Func().Text.From.Sym.Wrapper() {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOV g_panic(g), RT1
// CBNZ checkargp
// end:
// NOP
// ... function body ...
// checkargp:
// MOV panic_argp(RT1), RT2
// ADD $(autosize+8), RSP, R20
// CMP RT2, R20
// BNE end
// ADD $8, RSP, R20
// MOVD R20, panic_argp(RT1)
// B end
//
// The NOP is needed to give the jumps somewhere to land.
// It is a liblink NOP, not an ARM64 NOP: it encodes to 0 instruction bytes.
q = q1
// MOV g_panic(g), RT1
q = obj.Appendp(q, c.newprog)
q.As = AMOVD
q.From.Type = obj.TYPE_MEM
q.From.Reg = REGG
q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic
q.To.Type = obj.TYPE_REG
q.To.Reg = REGRT1
// CBNZ RT1, checkargp
cbnz := obj.Appendp(q, c.newprog)
cbnz.As = ACBNZ
cbnz.From.Type = obj.TYPE_REG
cbnz.From.Reg = REGRT1
cbnz.To.Type = obj.TYPE_BRANCH
// Empty branch target at the top of the function body
end := obj.Appendp(cbnz, c.newprog)
end.As = obj.ANOP
// find the end of the function
var last *obj.Prog
for last = end; last.Link != nil; last = last.Link {
}
// MOV panic_argp(RT1), RT2
mov := obj.Appendp(last, c.newprog)
mov.As = AMOVD
mov.From.Type = obj.TYPE_MEM
mov.From.Reg = REGRT1
mov.From.Offset = 0 // Panic.argp
mov.To.Type = obj.TYPE_REG
mov.To.Reg = REGRT2
// CBNZ branches to the MOV above
cbnz.To.SetTarget(mov)
// ADD $(autosize+8), SP, R20
q = obj.Appendp(mov, c.newprog)
q.As = AADD
q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(c.autosize) + 8
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R20
// CMP RT2, R20
q = obj.Appendp(q, c.newprog)
q.As = ACMP
q.From.Type = obj.TYPE_REG
q.From.Reg = REGRT2
q.Reg = REG_R20
// BNE end
q = obj.Appendp(q, c.newprog)
q.As = ABNE
q.To.Type = obj.TYPE_BRANCH
q.To.SetTarget(end)
// ADD $8, SP, R20
q = obj.Appendp(q, c.newprog)
q.As = AADD
q.From.Type = obj.TYPE_CONST
q.From.Offset = 8
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R20
// MOV R20, panic_argp(RT1)
q = obj.Appendp(q, c.newprog)
q.As = AMOVD
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R20
q.To.Type = obj.TYPE_MEM
q.To.Reg = REGRT1
q.To.Offset = 0 // Panic.argp
// B end
q = obj.Appendp(q, c.newprog)
q.As = AB
q.To.Type = obj.TYPE_BRANCH
q.To.SetTarget(end)
}
case obj.ARET: case obj.ARET:
nocache(p) nocache(p)
if p.From.Type == obj.TYPE_CONST { if p.From.Type == obj.TYPE_CONST {

View file

@ -301,8 +301,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
var q *obj.Prog var q *obj.Prog
var q1 *obj.Prog var q1 *obj.Prog
autosize := int32(0) autosize := int32(0)
var p1 *obj.Prog
var p2 *obj.Prog
for p := c.cursym.Func().Text; p != nil; p = p.Link { for p := c.cursym.Func().Text; p != nil; p = p.Link {
o := p.As o := p.As
switch o { switch o {
@ -401,90 +399,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q.To.Reg = REGSP q.To.Reg = REGSP
} }
if c.cursym.Func().Text.From.Sym.Wrapper() && c.cursym.Func().Text.Mark&LEAF == 0 {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOV g_panic(g), R20
// BEQ R20, end
// MOV panic_argp(R20), R24
// ADD $(autosize+FIXED_FRAME), R3, R30
// BNE R24, R30, end
// ADD $FIXED_FRAME, R3, R24
// MOV R24, panic_argp(R20)
// end:
// NOP
//
// The NOP is needed to give the jumps somewhere to land.
// It is a liblink NOP, not a hardware NOP: it encodes to 0 instruction bytes.
//
// We don't generate this for leaves because that means the wrapped
// function was inlined into the wrapper.
q = obj.Appendp(q, newprog)
q.As = mov
q.From.Type = obj.TYPE_MEM
q.From.Reg = REGG
q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R20
q = obj.Appendp(q, newprog)
q.As = ABEQ
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R20
q.To.Type = obj.TYPE_BRANCH
q.Mark |= BRANCH
p1 = q
q = obj.Appendp(q, newprog)
q.As = mov
q.From.Type = obj.TYPE_MEM
q.From.Reg = REG_R20
q.From.Offset = 0 // Panic.argp
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R24
q = obj.Appendp(q, newprog)
q.As = add
q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(autosize) + ctxt.Arch.FixedFrameSize
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R30
q = obj.Appendp(q, newprog)
q.As = ABNE
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R24
q.Reg = REG_R30
q.To.Type = obj.TYPE_BRANCH
q.Mark |= BRANCH
p2 = q
q = obj.Appendp(q, newprog)
q.As = add
q.From.Type = obj.TYPE_CONST
q.From.Offset = ctxt.Arch.FixedFrameSize
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R24
q = obj.Appendp(q, newprog)
q.As = mov
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R24
q.To.Type = obj.TYPE_MEM
q.To.Reg = REG_R20
q.To.Offset = 0 // Panic.argp
q = obj.Appendp(q, newprog)
q.As = obj.ANOP
p1.To.SetTarget(q)
p2.To.SetTarget(q)
}
case ARET: case ARET:
if p.From.Type == obj.TYPE_CONST { if p.From.Type == obj.TYPE_CONST {
ctxt.Diag("using BECOME (%v) is not supported!", p) ctxt.Diag("using BECOME (%v) is not supported!", p)

View file

@ -267,7 +267,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
var q1 *obj.Prog var q1 *obj.Prog
autosize := int32(0) autosize := int32(0)
var p1 *obj.Prog var p1 *obj.Prog
var p2 *obj.Prog
for p := c.cursym.Func().Text; p != nil; p = p.Link { for p := c.cursym.Func().Text; p != nil; p = p.Link {
o := p.As o := p.As
switch o { switch o {
@ -359,90 +358,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q.To.Reg = REGSP q.To.Reg = REGSP
} }
if c.cursym.Func().Text.From.Sym.Wrapper() && c.cursym.Func().Text.Mark&LEAF == 0 {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOV g_panic(g), R1
// BEQ R1, end
// MOV panic_argp(R1), R2
// ADD $(autosize+FIXED_FRAME), R29, R3
// BNE R2, R3, end
// ADD $FIXED_FRAME, R29, R2
// MOV R2, panic_argp(R1)
// end:
// NOP
//
// The NOP is needed to give the jumps somewhere to land.
// It is a liblink NOP, not an mips NOP: it encodes to 0 instruction bytes.
//
// We don't generate this for leafs because that means the wrapped
// function was inlined into the wrapper.
q = obj.Appendp(q, newprog)
q.As = mov
q.From.Type = obj.TYPE_MEM
q.From.Reg = REGG
q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R1
q = obj.Appendp(q, newprog)
q.As = ABEQ
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R1
q.To.Type = obj.TYPE_BRANCH
q.Mark |= BRANCH
p1 = q
q = obj.Appendp(q, newprog)
q.As = mov
q.From.Type = obj.TYPE_MEM
q.From.Reg = REG_R1
q.From.Offset = 0 // Panic.argp
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R2
q = obj.Appendp(q, newprog)
q.As = add
q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(autosize) + ctxt.Arch.FixedFrameSize
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R3
q = obj.Appendp(q, newprog)
q.As = ABNE
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R2
q.Reg = REG_R3
q.To.Type = obj.TYPE_BRANCH
q.Mark |= BRANCH
p2 = q
q = obj.Appendp(q, newprog)
q.As = add
q.From.Type = obj.TYPE_CONST
q.From.Offset = ctxt.Arch.FixedFrameSize
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R2
q = obj.Appendp(q, newprog)
q.As = mov
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R2
q.To.Type = obj.TYPE_MEM
q.To.Reg = REG_R1
q.To.Offset = 0 // Panic.argp
q = obj.Appendp(q, newprog)
q.As = obj.ANOP
p1.To.SetTarget(q)
p2.To.SetTarget(q)
}
case ARET: case ARET:
if p.From.Type == obj.TYPE_CONST { if p.From.Type == obj.TYPE_CONST {
ctxt.Diag("using BECOME (%v) is not supported!", p) ctxt.Diag("using BECOME (%v) is not supported!", p)

View file

@ -806,8 +806,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
} }
autosize := int32(0) autosize := int32(0)
var p1 *obj.Prog
var p2 *obj.Prog
for p := c.cursym.Func().Text; p != nil; p = p.Link { for p := c.cursym.Func().Text; p != nil; p = p.Link {
o := p.As o := p.As
switch o { switch o {
@ -967,96 +965,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q.To.Offset = 24 q.To.Offset = 24
} }
if c.cursym.Func().Text.From.Sym.Wrapper() {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOVD g_panic(g), R22
// CMP R22, $0
// BEQ end
// MOVD panic_argp(R22), R23
// ADD $(autosize+8), R1, R24
// CMP R23, R24
// BNE end
// ADD $8, R1, R25
// MOVD R25, panic_argp(R22)
// end:
// NOP
//
// The NOP is needed to give the jumps somewhere to land.
// It is a liblink NOP, not a ppc64 NOP: it encodes to 0 instruction bytes.
q = obj.Appendp(q, c.newprog)
q.As = AMOVD
q.From.Type = obj.TYPE_MEM
q.From.Reg = REGG
q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R22
q = obj.Appendp(q, c.newprog)
q.As = ACMP
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R22
q.To.Type = obj.TYPE_CONST
q.To.Offset = 0
q = obj.Appendp(q, c.newprog)
q.As = ABEQ
q.To.Type = obj.TYPE_BRANCH
p1 = q
q = obj.Appendp(q, c.newprog)
q.As = AMOVD
q.From.Type = obj.TYPE_MEM
q.From.Reg = REG_R22
q.From.Offset = 0 // Panic.argp
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R23
q = obj.Appendp(q, c.newprog)
q.As = AADD
q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(autosize) + c.ctxt.Arch.FixedFrameSize
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R24
q = obj.Appendp(q, c.newprog)
q.As = ACMP
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R23
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R24
q = obj.Appendp(q, c.newprog)
q.As = ABNE
q.To.Type = obj.TYPE_BRANCH
p2 = q
q = obj.Appendp(q, c.newprog)
q.As = AADD
q.From.Type = obj.TYPE_CONST
q.From.Offset = c.ctxt.Arch.FixedFrameSize
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R25
q = obj.Appendp(q, c.newprog)
q.As = AMOVD
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R25
q.To.Type = obj.TYPE_MEM
q.To.Reg = REG_R22
q.To.Offset = 0 // Panic.argp
q = obj.Appendp(q, c.newprog)
q.As = obj.ANOP
p1.To.SetTarget(q)
p2.To.SetTarget(q)
}
case obj.ARET: case obj.ARET:
if p.From.Type == obj.TYPE_CONST { if p.From.Type == obj.TYPE_CONST {
c.ctxt.Diag("using BECOME (%v) is not supported!", p) c.ctxt.Diag("using BECOME (%v) is not supported!", p)

View file

@ -564,85 +564,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0} prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
} }
if cursym.Func().Text.From.Sym.Wrapper() {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOV g_panic(g), X5
// BNE X5, ZERO, adjust
// end:
// NOP
// ...rest of function..
// adjust:
// MOV panic_argp(X5), X6
// ADD $(autosize+FIXED_FRAME), SP, X7
// BNE X6, X7, end
// ADD $FIXED_FRAME, SP, X6
// MOV X6, panic_argp(X5)
// JMP end
//
// The NOP is needed to give the jumps somewhere to land.
ldpanic := obj.Appendp(prologue, newprog)
ldpanic.As = AMOV
ldpanic.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REGG, Offset: 4 * int64(ctxt.Arch.PtrSize)} // G.panic
ldpanic.Reg = obj.REG_NONE
ldpanic.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X5}
bneadj := obj.Appendp(ldpanic, newprog)
bneadj.As = ABNE
bneadj.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X5}
bneadj.Reg = REG_ZERO
bneadj.To.Type = obj.TYPE_BRANCH
endadj := obj.Appendp(bneadj, newprog)
endadj.As = obj.ANOP
last := endadj
for last.Link != nil {
last = last.Link
}
getargp := obj.Appendp(last, newprog)
getargp.As = AMOV
getargp.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X5, Offset: 0} // Panic.argp
getargp.Reg = obj.REG_NONE
getargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
bneadj.To.SetTarget(getargp)
calcargp := obj.Appendp(getargp, newprog)
calcargp.As = AADDI
calcargp.From = obj.Addr{Type: obj.TYPE_CONST, Offset: stacksize + ctxt.Arch.FixedFrameSize}
calcargp.Reg = REG_SP
calcargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X7}
testargp := obj.Appendp(calcargp, newprog)
testargp.As = ABNE
testargp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
testargp.Reg = REG_X7
testargp.To.Type = obj.TYPE_BRANCH
testargp.To.SetTarget(endadj)
adjargp := obj.Appendp(testargp, newprog)
adjargp.As = AADDI
adjargp.From = obj.Addr{Type: obj.TYPE_CONST, Offset: int64(ctxt.Arch.PtrSize)}
adjargp.Reg = REG_SP
adjargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
setargp := obj.Appendp(adjargp, newprog)
setargp.As = AMOV
setargp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
setargp.Reg = obj.REG_NONE
setargp.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X5, Offset: 0} // Panic.argp
godone := obj.Appendp(setargp, newprog)
godone.As = AJAL
godone.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
godone.To.Type = obj.TYPE_BRANCH
godone.To.SetTarget(endadj)
}
// Update stack-based offsets. // Update stack-based offsets.
for p := cursym.Func().Text; p != nil; p = p.Link { for p := cursym.Func().Text; p != nil; p = p.Link {
stackOffset(&p.From, stacksize) stackOffset(&p.From, stacksize)

View file

@ -384,96 +384,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
break break
} }
if c.cursym.Func().Text.From.Sym.Wrapper() {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOVD g_panic(g), R3
// CMP R3, $0
// BEQ end
// MOVD panic_argp(R3), R4
// ADD $(autosize+8), R1, R5
// CMP R4, R5
// BNE end
// ADD $8, R1, R6
// MOVD R6, panic_argp(R3)
// end:
// NOP
//
// The NOP is needed to give the jumps somewhere to land.
// It is a liblink NOP, not a s390x NOP: it encodes to 0 instruction bytes.
q = obj.Appendp(q, c.newprog)
q.As = AMOVD
q.From.Type = obj.TYPE_MEM
q.From.Reg = REGG
q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R3
q = obj.Appendp(q, c.newprog)
q.As = ACMP
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R3
q.To.Type = obj.TYPE_CONST
q.To.Offset = 0
q = obj.Appendp(q, c.newprog)
q.As = ABEQ
q.To.Type = obj.TYPE_BRANCH
p1 := q
q = obj.Appendp(q, c.newprog)
q.As = AMOVD
q.From.Type = obj.TYPE_MEM
q.From.Reg = REG_R3
q.From.Offset = 0 // Panic.argp
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R4
q = obj.Appendp(q, c.newprog)
q.As = AADD
q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(autosize) + c.ctxt.Arch.FixedFrameSize
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R5
q = obj.Appendp(q, c.newprog)
q.As = ACMP
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R4
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R5
q = obj.Appendp(q, c.newprog)
q.As = ABNE
q.To.Type = obj.TYPE_BRANCH
p2 := q
q = obj.Appendp(q, c.newprog)
q.As = AADD
q.From.Type = obj.TYPE_CONST
q.From.Offset = c.ctxt.Arch.FixedFrameSize
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R6
q = obj.Appendp(q, c.newprog)
q.As = AMOVD
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R6
q.To.Type = obj.TYPE_MEM
q.To.Reg = REG_R3
q.To.Offset = 0 // Panic.argp
q = obj.Appendp(q, c.newprog)
q.As = obj.ANOP
p1.To.SetTarget(q)
p2.To.SetTarget(q)
}
case obj.ARET: case obj.ARET:
retTarget := p.To.Sym retTarget := p.To.Sym

View file

@ -202,59 +202,6 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
framesize = 0 framesize = 0
} else if s.Func().WasmExport != nil { } else if s.Func().WasmExport != nil {
genWasmExportWrapper(s, appendp) genWasmExportWrapper(s, appendp)
} else if s.Func().Text.From.Sym.Wrapper() {
// if g._panic != nil && g._panic.argp == FP {
// g._panic.argp = bottom-of-frame
// }
//
// MOVD g_panic(g), R0
// Get R0
// I64Eqz
// Not
// If
// Get SP
// I64ExtendI32U
// I64Const $framesize+8
// I64Add
// I64Load panic_argp(R0)
// I64Eq
// If
// MOVD SP, panic_argp(R0)
// End
// End
gpanic := obj.Addr{
Type: obj.TYPE_MEM,
Reg: REGG,
Offset: 4 * 8, // g_panic
}
panicargp := obj.Addr{
Type: obj.TYPE_MEM,
Reg: REG_R0,
Offset: 0, // panic.argp
}
p := s.Func().Text
p = appendp(p, AMOVD, gpanic, regAddr(REG_R0))
p = appendp(p, AGet, regAddr(REG_R0))
p = appendp(p, AI64Eqz)
p = appendp(p, ANot)
p = appendp(p, AIf)
p = appendp(p, AGet, regAddr(REG_SP))
p = appendp(p, AI64ExtendI32U)
p = appendp(p, AI64Const, constAddr(framesize+8))
p = appendp(p, AI64Add)
p = appendp(p, AI64Load, panicargp)
p = appendp(p, AI64Eq)
p = appendp(p, AIf)
p = appendp(p, AMOVD, regAddr(REG_SP), panicargp)
p = appendp(p, AEnd)
p = appendp(p, AEnd)
} }
if framesize > 0 && s.Func().WasmExport == nil { // genWasmExportWrapper has its own prologue generation if framesize > 0 && s.Func().WasmExport == nil { // genWasmExportWrapper has its own prologue generation

View file

@ -676,20 +676,9 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
} }
} }
var regEntryTmp0, regEntryTmp1 int16
if ctxt.Arch.Family == sys.AMD64 {
regEntryTmp0, regEntryTmp1 = REGENTRYTMP0, REGENTRYTMP1
} else {
regEntryTmp0, regEntryTmp1 = REG_BX, REG_DI
}
var regg int16
if !p.From.Sym.NoSplit() { if !p.From.Sym.NoSplit() {
// Emit split check and load G register // Emit split check.
p, regg = stacksplit(ctxt, cursym, p, newprog, autoffset, int32(textarg)) p = stacksplit(ctxt, cursym, p, newprog, autoffset, int32(textarg))
} else if p.From.Sym.Wrapper() {
// Load G register for the wrapper code
p, regg = loadG(ctxt, cursym, p, newprog)
} }
if bpsize > 0 { if bpsize > 0 {
@ -731,123 +720,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p.Pos = p.Pos.WithXlogue(src.PosPrologueEnd) p.Pos = p.Pos.WithXlogue(src.PosPrologueEnd)
} }
if cursym.Func().Text.From.Sym.Wrapper() {
// if g._panic != nil && g._panic.argp == FP {
// g._panic.argp = bottom-of-frame
// }
//
// MOVQ g_panic(g), regEntryTmp0
// TESTQ regEntryTmp0, regEntryTmp0
// JNE checkargp
// end:
// NOP
// ... rest of function ...
// checkargp:
// LEAQ (autoffset+8)(SP), regEntryTmp1
// CMPQ panic_argp(regEntryTmp0), regEntryTmp1
// JNE end
// MOVQ SP, panic_argp(regEntryTmp0)
// JMP end
//
// The NOP is needed to give the jumps somewhere to land.
// It is a liblink NOP, not an x86 NOP: it encodes to 0 instruction bytes.
//
// The layout is chosen to help static branch prediction:
// Both conditional jumps are unlikely, so they are arranged to be forward jumps.
// MOVQ g_panic(g), regEntryTmp0
p = obj.Appendp(p, newprog)
p.As = AMOVQ
p.From.Type = obj.TYPE_MEM
p.From.Reg = regg
p.From.Offset = 4 * int64(ctxt.Arch.PtrSize) // g_panic
p.To.Type = obj.TYPE_REG
p.To.Reg = regEntryTmp0
if ctxt.Arch.Family == sys.I386 {
p.As = AMOVL
}
// TESTQ regEntryTmp0, regEntryTmp0
p = obj.Appendp(p, newprog)
p.As = ATESTQ
p.From.Type = obj.TYPE_REG
p.From.Reg = regEntryTmp0
p.To.Type = obj.TYPE_REG
p.To.Reg = regEntryTmp0
if ctxt.Arch.Family == sys.I386 {
p.As = ATESTL
}
// JNE checkargp (checkargp to be resolved later)
jne := obj.Appendp(p, newprog)
jne.As = AJNE
jne.To.Type = obj.TYPE_BRANCH
// end:
// NOP
end := obj.Appendp(jne, newprog)
end.As = obj.ANOP
// Fast forward to end of function.
var last *obj.Prog
for last = end; last.Link != nil; last = last.Link {
}
// LEAQ (autoffset+8)(SP), regEntryTmp1
p = obj.Appendp(last, newprog)
p.As = ALEAQ
p.From.Type = obj.TYPE_MEM
p.From.Reg = REG_SP
p.From.Offset = int64(autoffset) + int64(ctxt.Arch.RegSize)
p.To.Type = obj.TYPE_REG
p.To.Reg = regEntryTmp1
if ctxt.Arch.Family == sys.I386 {
p.As = ALEAL
}
// Set jne branch target.
jne.To.SetTarget(p)
// CMPQ panic_argp(regEntryTmp0), regEntryTmp1
p = obj.Appendp(p, newprog)
p.As = ACMPQ
p.From.Type = obj.TYPE_MEM
p.From.Reg = regEntryTmp0
p.From.Offset = 0 // Panic.argp
p.To.Type = obj.TYPE_REG
p.To.Reg = regEntryTmp1
if ctxt.Arch.Family == sys.I386 {
p.As = ACMPL
}
// JNE end
p = obj.Appendp(p, newprog)
p.As = AJNE
p.To.Type = obj.TYPE_BRANCH
p.To.SetTarget(end)
// MOVQ SP, panic_argp(regEntryTmp0)
p = obj.Appendp(p, newprog)
p.As = AMOVQ
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_SP
p.To.Type = obj.TYPE_MEM
p.To.Reg = regEntryTmp0
p.To.Offset = 0 // Panic.argp
if ctxt.Arch.Family == sys.I386 {
p.As = AMOVL
}
// JMP end
p = obj.Appendp(p, newprog)
p.As = obj.AJMP
p.To.Type = obj.TYPE_BRANCH
p.To.SetTarget(end)
// Reset p for following code.
p = end
}
var deltasp int32 var deltasp int32
for p = cursym.Func().Text; p != nil; p = p.Link { for p = cursym.Func().Text; p != nil; p = p.Link {
pcsize := ctxt.Arch.RegSize pcsize := ctxt.Arch.RegSize
@ -1028,8 +900,8 @@ func loadG(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgAlloc)
// Append code to p to check for stack split. // Append code to p to check for stack split.
// Appends to (does not overwrite) p. // Appends to (does not overwrite) p.
// Assumes g is in rg. // Assumes g is in rg.
// Returns last new instruction and G register. // Returns last new instruction.
func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgAlloc, framesize int32, textarg int32) (*obj.Prog, int16) { func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgAlloc, framesize int32, textarg int32) *obj.Prog {
cmp := ACMPQ cmp := ACMPQ
lea := ALEAQ lea := ALEAQ
mov := AMOVQ mov := AMOVQ
@ -1243,7 +1115,7 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
q1.To.SetTarget(spill) q1.To.SetTarget(spill)
} }
return end, rg return end
} }
func isR15(r int16) bool { func isR15(r int16) bool {

View file

@ -959,10 +959,6 @@ func (p *_panic) nextDefer() (func(), bool) {
} }
} }
// The assembler adjusts p.argp in wrapper functions that shouldn't
// be visible to recover(), so we need to restore it each iteration.
p.argp = add(p.startSP, sys.MinFrameSize)
for { for {
for p.deferBitsPtr != nil { for p.deferBitsPtr != nil {
bits := *p.deferBitsPtr bits := *p.deferBitsPtr

View file

@ -1000,14 +1000,13 @@ type _defer struct {
// //
// A _panic value must only ever live on the stack. // A _panic value must only ever live on the stack.
// //
// The argp and link fields are stack pointers, but don't need special // The gopanicFP and link fields are stack pointers, but don't need special
// handling during stack growth: because they are pointer-typed and // handling during stack growth: because they are pointer-typed and
// _panic values only live on the stack, regular stack pointer // _panic values only live on the stack, regular stack pointer
// adjustment takes care of them. // adjustment takes care of them.
type _panic struct { type _panic struct {
argp unsafe.Pointer // pointer to arguments of deferred call run during panic; cannot move - known to liblink arg any // argument to panic
arg any // argument to panic link *_panic // link to earlier panic
link *_panic // link to earlier panic
// startPC and startSP track where _panic.start was called. // startPC and startSP track where _panic.start was called.
startPC uintptr startPC uintptr