diff options
| author | Keith Randall <khr@golang.org> | 2026-03-06 15:44:41 -0800 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-03-07 06:09:36 -0800 |
| commit | 383000da24e9b32dbe3cae4c48cbb233d7c62253 (patch) | |
| tree | 730a9c9b264260ed6efe2c0aecf35d0d2519b116 /src/cmd/internal/obj | |
| parent | b9545da71c2f5e93355d82a1f9b5ead02f2bc617 (diff) | |
| download | go-383000da24e9b32dbe3cae4c48cbb233d7c62253.tar.xz | |
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>
Diffstat (limited to 'src/cmd/internal/obj')
| -rw-r--r-- | src/cmd/internal/obj/arm/obj5.go | 26 | ||||
| -rw-r--r-- | src/cmd/internal/obj/loong64/obj.go | 12 | ||||
| -rw-r--r-- | src/cmd/internal/obj/mips/obj0.go | 12 | ||||
| -rw-r--r-- | src/cmd/internal/obj/ppc64/obj9.go | 24 | ||||
| -rw-r--r-- | src/cmd/internal/obj/riscv/obj.go | 7 | ||||
| -rw-r--r-- | src/cmd/internal/obj/s390x/objz.go | 11 |
6 files changed, 67 insertions, 25 deletions
diff --git a/src/cmd/internal/obj/arm/obj5.go b/src/cmd/internal/obj/arm/obj5.go index 79f08a41ea..62870731b5 100644 --- a/src/cmd/internal/obj/arm/obj5.go +++ b/src/cmd/internal/obj/arm/obj5.go @@ -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 } diff --git a/src/cmd/internal/obj/loong64/obj.go b/src/cmd/internal/obj/loong64/obj.go index 51a28d130c..fcf10d2307 100644 --- a/src/cmd/internal/obj/loong64/obj.go +++ b/src/cmd/internal/obj/loong64/obj.go @@ -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 diff --git a/src/cmd/internal/obj/mips/obj0.go b/src/cmd/internal/obj/mips/obj0.go index bbed88e9d6..4ade03a778 100644 --- a/src/cmd/internal/obj/mips/obj0.go +++ b/src/cmd/internal/obj/mips/obj0.go @@ -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 diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go index bae2965639..323420fefa 100644 --- a/src/cmd/internal/obj/ppc64/obj9.go +++ b/src/cmd/internal/obj/ppc64/obj9.go @@ -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 diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 24e0a454cd..e9005fe0db 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -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. diff --git a/src/cmd/internal/obj/s390x/objz.go b/src/cmd/internal/obj/s390x/objz.go index 4bfc1f7b2c..d877589573 100644 --- a/src/cmd/internal/obj/s390x/objz.go +++ b/src/cmd/internal/obj/s390x/objz.go @@ -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 |
