cmd/internal/obj: fix indirect tail call code

The assembler isn't handling this correctly for most architectures.
Of course, the two I tried first, arm64 and amd64, worked, so I assumed
other archs could handle it also. Apparently not.

Should fix dashboard failures introduced by CL 751465.

Change-Id: I9fc4f123d11acf3d10cc9806abfb93ec077509a7
Reviewed-on: https://go-review.googlesource.com/c/go/+/752560
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
Keith Randall
2026-03-06 15:44:41 -08:00
committed by Gopher Robot
parent b9545da71c
commit 383000da24
6 changed files with 67 additions and 25 deletions

View File

@@ -352,16 +352,25 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
case obj.ARET:
nocache(p)
retSym, retReg := p.To.Sym, p.To.Reg
if retReg == obj.REG_NONE {
retReg = REGLINK
}
p.To.Sym = nil
p.To.Name = obj.NAME_NONE
p.To.Reg = obj.REG_NONE
if cursym.Func().Text.Mark&LEAF != 0 {
if autosize == 0 {
p.As = AB
p.From = obj.Addr{}
if p.To.Sym != nil { // retjmp
if retSym != nil { // retjmp
p.To.Type = obj.TYPE_BRANCH
} else {
p.To.Type = obj.TYPE_MEM
p.To.Offset = 0
p.To.Reg = REGLINK
p.To.Reg = retReg
}
break
@@ -380,14 +389,17 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
// this ARET, they come from a branch
// with the same stackframe, so no spadj.
if p.To.Sym != nil { // retjmp
if retSym != nil || retReg != REGLINK { // retjmp
p.To.Reg = REGLINK
q2 = obj.Appendp(p, newprog)
q2.As = AB
q2.To.Type = obj.TYPE_BRANCH
q2.To.Sym = p.To.Sym
p.To.Sym = nil
p.To.Name = obj.NAME_NONE
if retSym != nil {
q2.To.Type = obj.TYPE_BRANCH
q2.To.Sym = retSym
} else {
q2.To.Type = obj.TYPE_MEM
q2.To.Reg = retReg
}
p = q2
}

View File

@@ -359,9 +359,13 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
break
}
retSym := p.To.Sym
retSym, retReg := p.To.Sym, p.To.Reg
if retReg == obj.REG_NONE {
retReg = REGLINK
}
p.To.Name = obj.NAME_NONE // clear fields as we may modify p to other instruction
p.To.Sym = nil
p.To.Reg = obj.REG_NONE
if c.cursym.Func().Text.Mark&LEAF != 0 {
if autosize == 0 {
@@ -373,7 +377,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p.To.Sym = retSym
} else {
p.To.Type = obj.TYPE_MEM
p.To.Reg = REGLINK
p.To.Reg = retReg
p.To.Offset = 0
}
p.Mark |= BRANCH
@@ -397,7 +401,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
} else {
q.To.Type = obj.TYPE_MEM
q.To.Offset = 0
q.To.Reg = REGLINK
q.To.Reg = retReg
}
q.Mark |= BRANCH
q.Spadj = +autosize
@@ -438,7 +442,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
} else {
q1.To.Type = obj.TYPE_MEM
q1.To.Offset = 0
q1.To.Reg = REGLINK
q1.To.Reg = retReg
}
q1.Mark |= BRANCH
q1.Spadj = +autosize

View File

@@ -364,9 +364,13 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
break
}
retSym := p.To.Sym
retSym, retReg := p.To.Sym, p.To.Reg
if retReg == obj.REG_NONE {
retReg = REGLINK
}
p.To.Name = obj.NAME_NONE // clear fields as we may modify p to other instruction
p.To.Sym = nil
p.To.Reg = obj.REG_NONE
if c.cursym.Func().Text.Mark&LEAF != 0 {
if autosize == 0 {
@@ -378,7 +382,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p.To.Sym = retSym
} else {
p.To.Type = obj.TYPE_MEM
p.To.Reg = REGLINK
p.To.Reg = retReg
p.To.Offset = 0
}
p.Mark |= BRANCH
@@ -401,7 +405,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q.To.Sym = retSym
} else {
q.To.Type = obj.TYPE_MEM
q.To.Reg = REGLINK
q.To.Reg = retReg
q.To.Offset = 0
}
q.Mark |= BRANCH
@@ -443,7 +447,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
} else {
q1.To.Type = obj.TYPE_MEM
q1.To.Offset = 0
q1.To.Reg = REGLINK
q1.To.Reg = retReg
}
q1.Mark |= BRANCH
q1.Spadj = +autosize

View File

@@ -965,7 +965,23 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
break
}
retTarget := p.To.Sym
retTarget, retReg := p.To.Sym, p.To.Reg
if retReg == obj.REG_NONE {
retReg = REG_LR
} else {
// Move target address into REG_CTR.
// (Indirect branches can only go to REG_LR or REG_CTR.)
x := newprog()
*x = *p
p.As = AMOVD
p.From.Type = obj.TYPE_REG
p.From.Reg = retReg
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_CTR
retReg = REG_CTR
p.Link = x
p = x
}
if c.cursym.Func().Text.Mark&LEAF != 0 {
if autosize == 0 {
@@ -973,7 +989,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p.From = obj.Addr{}
if retTarget == nil {
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_LR
p.To.Reg = retReg
} else {
p.To.Type = obj.TYPE_BRANCH
p.To.Sym = retTarget
@@ -994,7 +1010,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q.Pos = p.Pos
if retTarget == nil {
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_LR
q.To.Reg = retReg
} else {
q.To.Type = obj.TYPE_BRANCH
q.To.Sym = retTarget
@@ -1063,7 +1079,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q1.Pos = p.Pos
if retTarget == nil {
q1.To.Type = obj.TYPE_REG
q1.To.Reg = REG_LR
q1.To.Reg = retReg
} else {
q1.To.Type = obj.TYPE_BRANCH
q1.To.Sym = retTarget

View File

@@ -596,7 +596,10 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
case obj.ARET:
// Replace RET with epilogue.
retJMP := p.To.Sym
retJMP, retReg := p.To.Sym, p.To.Reg
if retReg == obj.REG_NONE {
retReg = REG_LR
}
if stacksize != 0 {
// Restore LR.
@@ -621,7 +624,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p.As = AJALR
p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
p.Reg = obj.REG_NONE
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: retReg}
}
// "Add back" the stack removed in the previous instruction.

View File

@@ -385,7 +385,10 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
}
case obj.ARET:
retTarget := p.To.Sym
retTarget, retReg := p.To.Sym, p.To.Reg
if retReg == obj.REG_NONE {
retReg = REG_LR
}
if c.cursym.Func().Text.Mark&LEAF != 0 {
if autosize == 0 {
@@ -393,7 +396,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p.From = obj.Addr{}
if retTarget == nil {
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_LR
p.To.Reg = retReg
} else {
p.To.Type = obj.TYPE_BRANCH
p.To.Sym = retTarget
@@ -414,7 +417,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q.From = obj.Addr{}
if retTarget == nil {
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_LR
q.To.Reg = retReg
} else {
q.To.Type = obj.TYPE_BRANCH
q.To.Sym = retTarget
@@ -450,7 +453,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q.From = obj.Addr{}
if retTarget == nil {
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_LR
q.To.Reg = retReg
} else {
q.To.Type = obj.TYPE_BRANCH
q.To.Sym = retTarget