var to_done, to_more *obj.Prog
if framesize <= objabi.StackSmall {
- // small stack: SP < stackguard
- // BLTU SP, stackguard, done
+ // small stack
+ // // if SP > stackguard { goto done }
+ // BLTU stackguard, SP, done
p = obj.Appendp(p, newprog)
p.As = ABLTU
p.From.Type = obj.TYPE_REG
p.Reg = REG_SP
p.To.Type = obj.TYPE_BRANCH
to_done = p
- } else if framesize <= objabi.StackBig {
+ } else {
// large stack: SP-framesize < stackguard-StackSmall
- // ADD $-(framesize-StackSmall), SP, X11
- // BLTU X11, stackguard, done
- p = obj.Appendp(p, newprog)
- // TODO(sorear): logic inconsistent with comment, but both match all non-x86 arches
- p.As = AADDI
- p.From.Type = obj.TYPE_CONST
- p.From.Offset = -(int64(framesize) - objabi.StackSmall)
- p.Reg = REG_SP
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_X11
+ offset := int64(framesize) - objabi.StackSmall
+ if framesize > objabi.StackBig {
+ // Such a large stack we need to protect against underflow.
+ // The runtime guarantees SP > objabi.StackBig, but
+ // framesize is large enough that SP-framesize may
+ // underflow, causing a direct comparison with the
+ // stack guard to incorrectly succeed. We explicitly
+ // guard against underflow.
+ //
+ // MOV $(framesize-StackSmall), X11
+ // BLTU SP, X11, label-of-call-to-morestack
- p = obj.Appendp(p, newprog)
- p.As = ABLTU
- p.From.Type = obj.TYPE_REG
- p.From.Reg = REG_X10
- p.Reg = REG_X11
- p.To.Type = obj.TYPE_BRANCH
- to_done = p
- } else {
- // Such a large stack we need to protect against wraparound.
- // If SP is close to zero:
- // SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
- // The +StackGuard on both sides is required to keep the left side positive:
- // SP is allowed to be slightly below stackguard. See stack.h.
- //
- // Preemption sets stackguard to StackPreempt, a very large value.
- // That breaks the math above, so we have to check for that explicitly.
- // // stackguard is X10
- // MOV $StackPreempt, X11
- // BEQ X10, X11, more
- // ADD $StackGuard, SP, X11
- // SUB X10, X11
- // MOV $(framesize+(StackGuard-StackSmall)), X10
- // BGTU X11, X10, done
- p = obj.Appendp(p, newprog)
- p.As = AMOV
- p.From.Type = obj.TYPE_CONST
- p.From.Offset = objabi.StackPreempt
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_X11
+ 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 = obj.Appendp(p, newprog)
- to_more = p
- p.As = ABEQ
- p.From.Type = obj.TYPE_REG
- p.From.Reg = REG_X10
- p.Reg = REG_X11
- p.To.Type = obj.TYPE_BRANCH
+ p = obj.Appendp(p, newprog)
+ p.As = ABLTU
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = REG_SP
+ p.Reg = REG_X11
+ 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
p = obj.Appendp(p, newprog)
p.As = AADDI
p.From.Type = obj.TYPE_CONST
- p.From.Offset = int64(objabi.StackGuard)
+ p.From.Offset = -offset
p.Reg = REG_SP
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_X11
- p = obj.Appendp(p, newprog)
- p.As = ASUB
- p.From.Type = obj.TYPE_REG
- p.From.Reg = REG_X10
- p.Reg = REG_X11
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_X11
-
- p = obj.Appendp(p, newprog)
- p.As = AMOV
- p.From.Type = obj.TYPE_CONST
- p.From.Offset = int64(framesize) + int64(objabi.StackGuard) - objabi.StackSmall
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_X10
-
p = obj.Appendp(p, newprog)
p.As = ABLTU
p.From.Type = obj.TYPE_REG