Commit e940358f authored by Austin Clements's avatar Austin Clements

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: default avatarCherry Zhang <cherryyz@google.com>
parent 75b56a08
......@@ -139,6 +139,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
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 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
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 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
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 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
//
// 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 preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
}
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 {
......
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