mirror of
https://github.com/golang/go.git
synced 2026-04-02 17:30:01 +09:00
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:
committed by
Gopher Robot
parent
b9545da71c
commit
383000da24
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user