diff options
Diffstat (limited to 'src/cmd/internal/obj/x86/obj6.go')
-rw-r--r-- | src/cmd/internal/obj/x86/obj6.go | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go index 75638a0183..9a47ae16ed 100644 --- a/src/cmd/internal/obj/x86/obj6.go +++ b/src/cmd/internal/obj/x86/obj6.go @@ -36,6 +36,7 @@ import ( "fmt" "log" "math" + "strings" ) func CanUse1InsnTLS(ctxt *obj.Link) bool { @@ -509,7 +510,7 @@ func rewriteToPcrel(ctxt *obj.Link, p *obj.Prog) { return } // Any Prog (aside from the above special cases) with an Addr with Name == - // NAME_EXTERN, NAME_STATIC or NAME_GOTREF has a CALL __x86.get_pc_thunk.cx + // NAME_EXTERN, NAME_STATIC or NAME_GOTREF has a CALL __x86.get_pc_thunk.XX // inserted before it. isName := func(a *obj.Addr) bool { if a.Sym == nil || (a.Type != obj.TYPE_MEM && a.Type != obj.TYPE_ADDR) || a.Reg != 0 { @@ -542,12 +543,23 @@ func rewriteToPcrel(ctxt *obj.Link, p *obj.Prog) { if !isName(&p.From) && !isName(&p.To) && (p.From3 == nil || !isName(p.From3)) { return } + var dst int16 = REG_CX + if isName(&p.From) && p.To.Type == obj.TYPE_REG { + switch p.As { + case ALEAL, AMOVL, AMOVWLZX, AMOVBLZX, AMOVWLSX, AMOVBLSX: + dst = p.To.Reg + // Special case: clobber the destination register with + // the PC so we don't have to clobber CX. + // The SSA backend depends on CX not being clobbered across these instructions. + // See cmd/compile/internal/ssa/gen/386.rules (search for Flag_shared). + } + } q := obj.Appendp(ctxt, p) q.RegTo2 = 1 r := obj.Appendp(ctxt, q) r.RegTo2 = 1 q.As = obj.ACALL - q.To.Sym = obj.Linklookup(ctxt, "__x86.get_pc_thunk.cx", 0) + q.To.Sym = obj.Linklookup(ctxt, "__x86.get_pc_thunk."+strings.ToLower(Rconv(int(dst))), 0) q.To.Type = obj.TYPE_MEM q.To.Name = obj.NAME_EXTERN q.To.Sym.Local = true @@ -557,6 +569,15 @@ func rewriteToPcrel(ctxt *obj.Link, p *obj.Prog) { r.From3 = p.From3 r.Reg = p.Reg r.To = p.To + if isName(&p.From) { + r.From.Reg = dst + } + if isName(&p.To) { + r.To.Reg = dst + } + if p.From3 != nil && isName(p.From3) { + r.From3.Reg = dst + } obj.Nopout(p) } |