cmd/internal/obj/mips: support NOFRAME
This passes toolstash -cmp with one exception: assembly functions that
were declared with a frame size of -4 (or -8) used to record
locals=0xfffffffffffffffc in the object file and now record
locals=0x0. This doesn't affect anything.
Change-Id: I0d15e81770e54222ae329ce4496da06016736771
Reviewed-on: https://go-review.googlesource.com/92041
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/src/cmd/internal/obj/mips/obj0.go b/src/cmd/internal/obj/mips/obj0.go
index ae9d128..477f553 100644
--- a/src/cmd/internal/obj/mips/obj0.go
+++ b/src/cmd/internal/obj/mips/obj0.go
@@ -139,6 +139,19 @@
p := c.cursym.Func.Text
textstksiz := p.To.Offset
+ if textstksiz == -ctxt.FixedFrameSize() {
+ // 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)
@@ -278,15 +291,42 @@
o := p.As
switch o {
case obj.ATEXT:
- autosize = int32(textstksiz + ctxt.FixedFrameSize())
- if (p.Mark&LEAF != 0) && autosize <= int32(ctxt.FixedFrameSize()) {
- autosize = 0
- } else if autosize&4 != 0 && c.ctxt.Arch.Family == sys.MIPS64 {
+ autosize = int32(textstksiz)
+
+ 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 += int32(c.ctxt.FixedFrameSize())
+ }
+
+ if autosize&4 != 0 && c.ctxt.Arch.Family == sys.MIPS64 {
autosize += 4
}
+ if autosize == 0 && c.cursym.Func.Text.Mark&LEAF == 0 {
+ if c.cursym.Func.Text.From.Sym.NoSplit() {
+ if ctxt.Debugvlog {
+ ctxt.Logf("save suppressed in: %s\n", c.cursym.Name)
+ }
+
+ c.cursym.Func.Text.Mark |= LEAF
+ }
+ }
+
p.To.Offset = int64(autosize) - ctxt.FixedFrameSize()
+ if c.cursym.Func.Text.Mark&LEAF != 0 {
+ c.cursym.Set(obj.AttrLeaf, true)
+ if p.From.Sym.NoFrame() {
+ break
+ }
+ }
+
if !p.From.Sym.NoSplit() {
p = c.stacksplit(p, autosize) // emit split check
}
@@ -316,22 +356,9 @@
q.To.Type = obj.TYPE_REG
q.To.Reg = REGSP
q.Spadj = +autosize
- } else if c.cursym.Func.Text.Mark&LEAF == 0 {
- if c.cursym.Func.Text.From.Sym.NoSplit() {
- if ctxt.Debugvlog {
- ctxt.Logf("save suppressed in: %s\n", c.cursym.Name)
- }
-
- c.cursym.Func.Text.Mark |= LEAF
- }
}
- if c.cursym.Func.Text.Mark&LEAF != 0 {
- c.cursym.Set(obj.AttrLeaf, true)
- break
- }
-
- if c.cursym.Func.Text.From.Sym.Wrapper() {
+ if c.cursym.Func.Text.From.Sym.Wrapper() && c.cursym.Func.Text.Mark&LEAF == 0 {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOV g_panic(g), R1
@@ -346,6 +373,9 @@
//
// The NOP is needed to give the jumps somewhere to land.
// It is a liblink NOP, not an mips NOP: it encodes to 0 instruction bytes.
+ //
+ // We don't generate this for leafs because that means the wrapped
+ // function was inlined into the wrapper.
q = obj.Appendp(q, newprog)
@@ -604,11 +634,6 @@
}
func (c *ctxt0) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
- // Leaf function with no frame is effectively NOSPLIT.
- if framesize == 0 {
- return p
- }
-
var mov, add, sub obj.As
if c.ctxt.Arch.Family == sys.MIPS64 {