diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index 71cee60259..71fc523fe0 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -443,7 +443,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { p := c.cursym.Func.Text textstksiz := p.To.Offset - aoffset := int32(textstksiz) + if textstksiz == -8 { + // Historical way to mark NOFRAME. + p.From.Sym.Set(obj.AttrNoFrame, true) + textstksiz = 0 + } + if textstksiz < 0 { + c.ctxt.Diag("negative frame size %d - did you mean NOFRAME?", textstksiz) + } + if p.From.Sym.NoFrame() { + if textstksiz != 0 { + c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz) + } + } c.cursym.Func.Args = p.To.Val.(int32) c.cursym.Func.Locals = int32(textstksiz) @@ -521,14 +533,20 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { switch o { case obj.ATEXT: c.cursym.Func.Text = p - if textstksiz < 0 { - c.autosize = 0 - } else { - c.autosize = int32(textstksiz + 8) + c.autosize = int32(textstksiz) + + if p.Mark&LEAF != 0 && c.autosize == 0 { + // A leaf function with no locals has no frame. + p.From.Sym.Set(obj.AttrNoFrame, true) } - if (c.cursym.Func.Text.Mark&LEAF != 0) && c.autosize <= 8 { - c.autosize = 0 - } else if c.autosize&(16-1) != 0 { + + if !p.From.Sym.NoFrame() { + // If there is a stack frame at all, it includes + // space to save the LR. + c.autosize += 8 + } + + if c.autosize != 0 && c.autosize&(16-1) != 0 { // The frame includes an LR. // If the frame size is 8, it's only an LR, // so there's no potential for breaking references to @@ -544,17 +562,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { c.ctxt.Diag("%v: unaligned frame size %d - must be 8 mod 16 (or 0)", p, c.autosize-8) } } - p.To.Offset = int64(c.autosize) - 8 - if c.autosize == 0 && !(c.cursym.Func.Text.Mark&LEAF != 0) { + if c.autosize == 0 && c.cursym.Func.Text.Mark&LEAF == 0 { if c.ctxt.Debugvlog { c.ctxt.Logf("save suppressed in: %s\n", c.cursym.Func.Text.From.Sym.Name) } c.cursym.Func.Text.Mark |= LEAF } - if c.cursym.Func.Text.Mark&LEAF != 0 { - c.cursym.Set(obj.AttrLeaf, true) - if c.autosize == 0 { + // FP offsets need an updated p.To.Offset. + p.To.Offset = int64(c.autosize) - 8 + + if cursym.Func.Text.Mark&LEAF != 0 { + cursym.Set(obj.AttrLeaf, true) + if p.From.Sym.NoFrame() { break } } @@ -563,7 +583,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { p = c.stacksplit(p, c.autosize) // emit split check } - aoffset = c.autosize + aoffset := c.autosize if aoffset > 0xF0 { aoffset = 0xF0 } @@ -740,7 +760,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } } else { /* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/ - aoffset = c.autosize + aoffset := c.autosize if aoffset > 0xF0 { aoffset = 0xF0