cmd/internal/obj: set morestack arg spilling and regabi prologue on riscv64

This CL spill arg registers before calling morestack, unspill
after.
Also, avoid X11,X12,X13 in function prologue, which may carry
live argument value.

Change-Id: I7a2841fbe306f62a7765e212f9f0be5c11ce7f8c
Reviewed-on: https://go-review.googlesource.com/c/go/+/396655
Trust: mzh <mzh@golangcn.org>
Run-TryBot: mzh <mzh@golangcn.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
Meng Zhuo 2022-03-29 19:14:24 +08:00 committed by mzh
parent 2de2f6df64
commit 6c17529af7

View File

@ -415,17 +415,17 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
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), X11
// BNE X11, ZERO, adjust
// MOV g_panic(g), X5
// BNE X5, ZERO, adjust
// end:
// NOP
// ...rest of function..
// adjust:
// MOV panic_argp(X11), X12
// ADD $(autosize+FIXED_FRAME), SP, X13
// BNE X12, X13, end
// ADD $FIXED_FRAME, SP, X12
// MOV X12, panic_argp(X11)
// 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.
@ -435,11 +435,11 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
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_X11}
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_X11}
bneadj.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X5}
bneadj.Reg = REG_ZERO
bneadj.To.Type = obj.TYPE_BRANCH
@ -453,9 +453,9 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
getargp := obj.Appendp(last, newprog)
getargp.As = AMOV
getargp.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X11, Offset: 0} // Panic.argp
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_X12}
getargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
bneadj.To.SetTarget(getargp)
@ -463,12 +463,12 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
calcargp.As = AADDI
calcargp.From = obj.Addr{Type: obj.TYPE_CONST, Offset: stacksize + ctxt.FixedFrameSize()}
calcargp.Reg = REG_SP
calcargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X13}
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_X12}
testargp.Reg = REG_X13
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)
@ -476,13 +476,13 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
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_X12}
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_X12}
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_X11, Offset: 0} // Panic.argp
setargp.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X5, Offset: 0} // Panic.argp
godone := obj.Appendp(setargp, newprog)
godone.As = AJAL
@ -732,6 +732,11 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgA
// Save LR and REGCTXT
const frameSize = 16
p = ctxt.StartUnsafePoint(p, newprog)
// Spill Arguments. This has to happen before we open
// any more frame space.
p = cursym.Func().SpillRegisterArgs(p, newprog)
// MOV LR, -16(SP)
p = obj.Appendp(p, newprog)
p.As = AMOV
@ -778,13 +783,15 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgA
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
p.Spadj = -frameSize
// Unspill arguments
p = cursym.Func().UnspillRegisterArgs(p, newprog)
p = ctxt.EndUnsafePoint(p, newprog, -1)
}
// Jump back to here after morestack returns.
startPred := p
// MOV g_stackguard(g), X10
// MOV g_stackguard(g), X6
p = obj.Appendp(p, newprog)
p.As = AMOV
p.From.Type = obj.TYPE_MEM
@ -794,7 +801,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgA
p.From.Offset = 3 * int64(ctxt.Arch.PtrSize) // G.stackguard1
}
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_X10
p.To.Reg = REG_X6
// Mark the stack bound check and morestack call async nonpreemptible.
// If we get preempted here, when resumed the preemption request is
@ -811,7 +818,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgA
p = obj.Appendp(p, newprog)
p.As = ABLTU
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_X10
p.From.Reg = REG_X6
p.Reg = REG_SP
p.To.Type = obj.TYPE_BRANCH
to_done = p
@ -826,52 +833,56 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgA
// stack guard to incorrectly succeed. We explicitly
// guard against underflow.
//
// MOV $(framesize-StackSmall), X11
// BLTU SP, X11, label-of-call-to-morestack
// MOV $(framesize-StackSmall), X7
// BLTU SP, X7, label-of-call-to-morestack
p = obj.Appendp(p, newprog)
p.As = AMOV
p.From.Type = obj.TYPE_CONST
p.From.Offset = offset
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_X11
p.To.Reg = REG_X7
p = obj.Appendp(p, newprog)
p.As = ABLTU
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_SP
p.Reg = REG_X11
p.Reg = REG_X7
p.To.Type = obj.TYPE_BRANCH
to_more = p
}
// Check against the stack guard. We've ensured this won't underflow.
// ADD $-(framesize-StackSmall), SP, X11
// // if X11 > stackguard { goto done }
// BLTU stackguard, X11, done
// ADD $-(framesize-StackSmall), SP, X7
// // if X7 > stackguard { goto done }
// BLTU stackguard, X7, done
p = obj.Appendp(p, newprog)
p.As = AADDI
p.From.Type = obj.TYPE_CONST
p.From.Offset = -offset
p.Reg = REG_SP
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_X11
p.To.Reg = REG_X7
p = obj.Appendp(p, newprog)
p.As = ABLTU
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_X10
p.Reg = REG_X11
p.From.Reg = REG_X6
p.Reg = REG_X7
p.To.Type = obj.TYPE_BRANCH
to_done = p
}
// Spill the register args that could be clobbered by the
// morestack code
p = ctxt.EmitEntryStackMap(cursym, p, newprog)
p = cursym.Func().SpillRegisterArgs(p, newprog)
// CALL runtime.morestack(SB)
p = obj.Appendp(p, newprog)
p.As = obj.ACALL
p.To.Type = obj.TYPE_BRANCH
if cursym.CFunc() {
p.To.Sym = ctxt.Lookup("runtime.morestackc")
} else if !cursym.Func().Text.From.Sym.NeedCtxt() {
@ -884,6 +895,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgA
}
jalToSym(ctxt, p, REG_X5)
p = cursym.Func().UnspillRegisterArgs(p, newprog)
p = ctxt.EndUnsafePoint(p, newprog, -1)
// JMP start