]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/arm64: support NOFRAME
authorAustin Clements <austin@google.com>
Wed, 24 Jan 2018 22:17:38 +0000 (17:17 -0500)
committerAustin Clements <austin@google.com>
Mon, 12 Feb 2018 21:41:26 +0000 (21:41 +0000)
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: Cherry Zhang <cherryyz@google.com>
src/cmd/internal/obj/arm64/obj7.go

index 71cee60259ab3813e6584b4a3c1f2246645aea3c..71fc523fe030f68bf0c0bb414ba33189f610547a 100644 (file)
@@ -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