1
0
mirror of https://github.com/golang/go synced 2024-07-01 07:56:09 +00:00

cmd/internal/obj: fix tail call in non-zero frame leaf function on MIPS and S390X

A "RET f(SB)" wasn't assembled correctly in a leaf function with
non-zero frame size. Follows CL 371034, for MIPS(32/64)(be/le)
and S390X. Other architectures seem to do it right. Add a test.

Change-Id: I41349a7ae9862b924f3a3de2bcb55b782061ce21
Reviewed-on: https://go-review.googlesource.com/c/go/+/371214
Trust: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Cherry Mui 2021-12-13 10:24:07 -05:00
parent 9e85dc5f18
commit 67917c3d78
4 changed files with 27 additions and 6 deletions

View File

@ -466,9 +466,15 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q = c.newprog()
q.As = AJMP
q.Pos = p.Pos
q.To.Type = obj.TYPE_MEM
q.To.Offset = 0
q.To.Reg = REGLINK
if retSym != nil { // retjmp
q.To.Type = obj.TYPE_BRANCH
q.To.Name = obj.NAME_EXTERN
q.To.Sym = retSym
} else {
q.To.Type = obj.TYPE_MEM
q.To.Reg = REGLINK
q.To.Offset = 0
}
q.Mark |= BRANCH
q.Spadj = +autosize

View File

@ -488,8 +488,13 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q = obj.Appendp(p, c.newprog)
q.As = ABR
q.From = obj.Addr{}
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_LR
if retTarget == nil {
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_LR
} else {
q.To.Type = obj.TYPE_BRANCH
q.To.Sym = retTarget
}
q.Mark |= BRANCH
q.Spadj = autosize
break

View File

@ -10,3 +10,7 @@ TEXT ·f(SB), 4, $8-0
TEXT ·leaf(SB), 4, $0-0
RET ·f3(SB)
JMP ·unreachable(SB)
TEXT ·leaf2(SB), 4, $32-0 // nonzero frame size
RET ·f4(SB)
JMP ·unreachable(SB)

View File

@ -6,8 +6,9 @@ package main
func f()
func leaf()
func leaf2()
var f1called, f2called, f3called bool
var f1called, f2called, f3called, f4called bool
func main() {
f()
@ -21,11 +22,16 @@ func main() {
if !f3called {
panic("f3 not called")
}
leaf2()
if !f4called {
panic("f4 not called")
}
}
func f1() { f1called = true }
func f2() { f2called = true }
func f3() { f3called = true }
func f4() { f4called = true }
func unreachable() {
panic("unreachable function called")