Commit 75b56a08 authored by Austin Clements's avatar Austin Clements

cmd/internal/obj/arm64: support NOFRAME

In addition, this makes the arm64 prologue code generation much closer
to the pattern used on other platforms.

This passes toolstash -cmp with one exception: assembly functions that
were declared with a frame size of -8 used to record
locals=0xfffffffffffffff8 in the object file and now record
locals=0x0. This doesn't affect anything.

Change-Id: I0d15e81770e54222ae329ce4496da06016736770
Reviewed-on: https://go-review.googlesource.com/92040
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarCherry Zhang <cherryyz@google.com>
parent 99e37e98
...@@ -443,7 +443,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -443,7 +443,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p := c.cursym.Func.Text p := c.cursym.Func.Text
textstksiz := p.To.Offset 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.Args = p.To.Val.(int32)
c.cursym.Func.Locals = int32(textstksiz) c.cursym.Func.Locals = int32(textstksiz)
...@@ -521,14 +533,20 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -521,14 +533,20 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
switch o { switch o {
case obj.ATEXT: case obj.ATEXT:
c.cursym.Func.Text = p c.cursym.Func.Text = p
if textstksiz < 0 { c.autosize = int32(textstksiz)
c.autosize = 0
} else { if p.Mark&LEAF != 0 && c.autosize == 0 {
c.autosize = int32(textstksiz + 8) // 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 if !p.From.Sym.NoFrame() {
} else if c.autosize&(16-1) != 0 { // 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. // The frame includes an LR.
// If the frame size is 8, it's only an LR, // If the frame size is 8, it's only an LR,
// so there's no potential for breaking references to // so there's no potential for breaking references to
...@@ -544,17 +562,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -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) 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 { if c.ctxt.Debugvlog {
c.ctxt.Logf("save suppressed in: %s\n", c.cursym.Func.Text.From.Sym.Name) c.ctxt.Logf("save suppressed in: %s\n", c.cursym.Func.Text.From.Sym.Name)
} }
c.cursym.Func.Text.Mark |= LEAF c.cursym.Func.Text.Mark |= LEAF
} }
if c.cursym.Func.Text.Mark&LEAF != 0 { // FP offsets need an updated p.To.Offset.
c.cursym.Set(obj.AttrLeaf, true) p.To.Offset = int64(c.autosize) - 8
if c.autosize == 0 {
if cursym.Func.Text.Mark&LEAF != 0 {
cursym.Set(obj.AttrLeaf, true)
if p.From.Sym.NoFrame() {
break break
} }
} }
...@@ -563,7 +583,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -563,7 +583,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p = c.stacksplit(p, c.autosize) // emit split check p = c.stacksplit(p, c.autosize) // emit split check
} }
aoffset = c.autosize aoffset := c.autosize
if aoffset > 0xF0 { if aoffset > 0xF0 {
aoffset = 0xF0 aoffset = 0xF0
} }
...@@ -740,7 +760,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -740,7 +760,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
} }
} else { } else {
/* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/ /* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/
aoffset = c.autosize aoffset := c.autosize
if aoffset > 0xF0 { if aoffset > 0xF0 {
aoffset = 0xF0 aoffset = 0xF0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment