p := c.cursym.Func.Text
autoffset := int32(p.To.Offset)
- if autoffset < 0 {
+ if autoffset == -4 {
+ // Historical way to mark NOFRAME.
+ p.From.Sym.Set(obj.AttrNoFrame, true)
autoffset = 0
}
+ if autoffset < 0 || autoffset%4 != 0 {
+ c.ctxt.Diag("frame size %d not 0 or a positive multiple of 4", autoffset)
+ }
+ if p.From.Sym.NoFrame() {
+ if autoffset != 0 {
+ c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", autoffset)
+ }
+ }
+
cursym.Func.Locals = autoffset
cursym.Func.Args = p.To.Val.(int32)
o := p.As
switch o {
case obj.ATEXT:
- autosize = int32(p.To.Offset + 4)
- if autosize <= 4 {
- if cursym.Func.Text.Mark&LEAF != 0 {
- p.To.Offset = -4
- autosize = 0
- }
+ autosize = int32(autoffset)
+
+ if p.Mark&LEAF != 0 && autosize == 0 {
+ // A leaf function with no locals has no frame.
+ p.From.Sym.Set(obj.AttrNoFrame, true)
+ }
+
+ if !p.From.Sym.NoFrame() {
+ // If there is a stack frame at all, it includes
+ // space to save the LR.
+ autosize += 4
}
if autosize == 0 && cursym.Func.Text.Mark&LEAF == 0 {
+ // A very few functions that do not return to their caller
+ // are not identified as leaves but still have no frame.
if ctxt.Debugvlog {
ctxt.Logf("save suppressed in: %s\n", cursym.Name)
}
cursym.Func.Text.Mark |= LEAF
}
+ // FP offsets need an updated p.To.Offset.
+ p.To.Offset = int64(autosize) - 4
+
if cursym.Func.Text.Mark&LEAF != 0 {
cursym.Set(obj.AttrLeaf, true)
- if autosize == 0 {
+ if p.From.Sym.NoFrame() {
break
}
}