mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: register abi, morestack work and mole whacking
Morestack works for non-pointer register parameters Within a function body, pointer-typed parameters are correctly tracked. Results still not hooked up. For #40724. Change-Id: Icaee0b51d0da54af983662d945d939b756088746 Reviewed-on: https://go-review.googlesource.com/c/go/+/294410 Trust: David Chase <drchase@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
868a110c56
commit
a2d92b5143
11 changed files with 175 additions and 57 deletions
|
|
@ -135,7 +135,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
|||
p.To.Index = REG_NONE
|
||||
}
|
||||
} else {
|
||||
// load_g_cx, below, always inserts the 1-instruction sequence. Rewrite it
|
||||
// load_g, below, always inserts the 1-instruction sequence. Rewrite it
|
||||
// as the 2-instruction sequence if necessary.
|
||||
// MOVQ 0(TLS), BX
|
||||
// becomes
|
||||
|
|
@ -644,8 +644,12 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||
regg = REGG // use the g register directly in ABIInternal
|
||||
} else {
|
||||
p = obj.Appendp(p, newprog)
|
||||
p = load_g_cx(ctxt, p, newprog) // load g into CX
|
||||
regg = REG_CX
|
||||
if ctxt.Arch.Family == sys.AMD64 {
|
||||
// Using this register means that stacksplit works w/ //go:registerparams even when objabi.Regabi_enabled == 0
|
||||
regg = REGG // == REG_R14
|
||||
}
|
||||
p = load_g(ctxt, p, newprog, regg) // load g into regg
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -963,7 +967,7 @@ func indir_cx(ctxt *obj.Link, a *obj.Addr) {
|
|||
// Overwriting p is unusual but it lets use this in both the
|
||||
// prologue (caller must call appendp first) and in the epilogue.
|
||||
// Returns last new instruction.
|
||||
func load_g_cx(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) *obj.Prog {
|
||||
func load_g(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, rg int16) *obj.Prog {
|
||||
p.As = AMOVQ
|
||||
if ctxt.Arch.PtrSize == 4 {
|
||||
p.As = AMOVL
|
||||
|
|
@ -972,7 +976,7 @@ func load_g_cx(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) *obj.Prog {
|
|||
p.From.Reg = REG_TLS
|
||||
p.From.Offset = 0
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_CX
|
||||
p.To.Reg = rg
|
||||
|
||||
next := p.Link
|
||||
progedit(ctxt, p, newprog)
|
||||
|
|
@ -1027,9 +1031,14 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
// unnecessarily. See issue #35470.
|
||||
p = ctxt.StartUnsafePoint(p, newprog)
|
||||
} else if framesize <= objabi.StackBig {
|
||||
tmp := int16(REG_AX) // use AX for 32-bit
|
||||
if ctxt.Arch.Family == sys.AMD64 {
|
||||
// for 64-bit, stay away from register ABI parameter registers, even w/o GOEXPERIMENT=regabi
|
||||
tmp = int16(REG_R13)
|
||||
}
|
||||
// large stack: SP-framesize <= stackguard-StackSmall
|
||||
// LEAQ -xxx(SP), AX
|
||||
// CMPQ AX, stackguard
|
||||
// LEAQ -xxx(SP), tmp
|
||||
// CMPQ tmp, stackguard
|
||||
p = obj.Appendp(p, newprog)
|
||||
|
||||
p.As = lea
|
||||
|
|
@ -1037,12 +1046,12 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
p.From.Reg = REG_SP
|
||||
p.From.Offset = -(int64(framesize) - objabi.StackSmall)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_AX
|
||||
p.To.Reg = tmp
|
||||
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = cmp
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_AX
|
||||
p.From.Reg = tmp
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Reg = rg
|
||||
p.To.Offset = 2 * int64(ctxt.Arch.PtrSize) // G.stackguard0
|
||||
|
|
@ -1052,6 +1061,12 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
|
||||
p = ctxt.StartUnsafePoint(p, newprog) // see the comment above
|
||||
} else {
|
||||
tmp1 := int16(REG_SI)
|
||||
tmp2 := int16(REG_AX)
|
||||
if ctxt.Arch.Family == sys.AMD64 {
|
||||
tmp1 = int16(REG_R13) // register ABI uses REG_SI and REG_AX for parameters.
|
||||
tmp2 = int16(REG_R12)
|
||||
}
|
||||
// Such a large stack we need to protect against wraparound.
|
||||
// If SP is close to zero:
|
||||
// SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
|
||||
|
|
@ -1060,12 +1075,12 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
//
|
||||
// Preemption sets stackguard to StackPreempt, a very large value.
|
||||
// That breaks the math above, so we have to check for that explicitly.
|
||||
// MOVQ stackguard, SI
|
||||
// MOVQ stackguard, tmp1
|
||||
// CMPQ SI, $StackPreempt
|
||||
// JEQ label-of-call-to-morestack
|
||||
// LEAQ StackGuard(SP), AX
|
||||
// SUBQ SI, AX
|
||||
// CMPQ AX, $(framesize+(StackGuard-StackSmall))
|
||||
// LEAQ StackGuard(SP), tmp2
|
||||
// SUBQ tmp1, tmp2
|
||||
// CMPQ tmp2, $(framesize+(StackGuard-StackSmall))
|
||||
|
||||
p = obj.Appendp(p, newprog)
|
||||
|
||||
|
|
@ -1077,14 +1092,14 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
p.From.Offset = 3 * int64(ctxt.Arch.PtrSize) // G.stackguard1
|
||||
}
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_SI
|
||||
p.To.Reg = tmp1
|
||||
|
||||
p = ctxt.StartUnsafePoint(p, newprog) // see the comment above
|
||||
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = cmp
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_SI
|
||||
p.From.Reg = tmp1
|
||||
p.To.Type = obj.TYPE_CONST
|
||||
p.To.Offset = objabi.StackPreempt
|
||||
if ctxt.Arch.Family == sys.I386 {
|
||||
|
|
@ -1102,19 +1117,19 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
p.From.Reg = REG_SP
|
||||
p.From.Offset = int64(objabi.StackGuard)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_AX
|
||||
p.To.Reg = tmp2
|
||||
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = sub
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_SI
|
||||
p.From.Reg = tmp1
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_AX
|
||||
p.To.Reg = tmp2
|
||||
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = cmp
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_AX
|
||||
p.From.Reg = tmp2
|
||||
p.To.Type = obj.TYPE_CONST
|
||||
p.To.Offset = int64(framesize) + (int64(objabi.StackGuard) - objabi.StackSmall)
|
||||
}
|
||||
|
|
@ -1139,7 +1154,7 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
|
||||
pcdata := ctxt.EmitEntryStackMap(cursym, spfix, newprog)
|
||||
spill := ctxt.StartUnsafePoint(pcdata, newprog)
|
||||
pcdata = ctxt.SpillRegisterArgs(spill, newprog)
|
||||
pcdata = cursym.Func().SpillRegisterArgs(spill, newprog)
|
||||
|
||||
call := obj.Appendp(pcdata, newprog)
|
||||
call.Pos = cursym.Func().Text.Pos
|
||||
|
|
@ -1164,7 +1179,7 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
progedit(ctxt, callend.Link, newprog)
|
||||
}
|
||||
|
||||
pcdata = ctxt.UnspillRegisterArgs(callend, newprog)
|
||||
pcdata = cursym.Func().UnspillRegisterArgs(callend, newprog)
|
||||
pcdata = ctxt.EndUnsafePoint(pcdata, newprog, -1)
|
||||
|
||||
jmp := obj.Appendp(pcdata, newprog)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue