Commit 3c85e1b1 authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle

cmd/internal/obj/x86: factor rewriting to use GOT into separate function

I was prodded into doing this in review comments for the ARM version, and it's
going to make shared libs for 386 easier.

Change-Id: Id12de801b1425b8c6b5736fe91b418fc123a4e40
Reviewed-on: https://go-review.googlesource.com/17012Reviewed-by: default avatarDavid Crawshaw <crawshaw@golang.org>
parent 6bf794a3
...@@ -2090,8 +2090,11 @@ func oclass(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int { ...@@ -2090,8 +2090,11 @@ func oclass(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int {
case obj.TYPE_ADDR: case obj.TYPE_ADDR:
switch a.Name { switch a.Name {
case obj.NAME_GOTREF:
ctxt.Diag("unexpected TYPE_ADDR with NAME_GOTREF")
return Yxxx
case obj.NAME_EXTERN, case obj.NAME_EXTERN,
obj.NAME_GOTREF,
obj.NAME_STATIC: obj.NAME_STATIC:
if a.Sym != nil && isextern(a.Sym) || p.Mode == 32 { if a.Sym != nil && isextern(a.Sym) || p.Mode == 32 {
return Yi32 return Yi32
......
...@@ -308,7 +308,19 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { ...@@ -308,7 +308,19 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
} }
} }
if ctxt.Flag_dynlink && (p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO) { if ctxt.Flag_dynlink {
rewriteToUseGot(ctxt, p)
}
}
// Rewrite p, if necessary, to access global data via the global offset table.
func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
// ADUFFxxx $offset
// becomes
// MOVQ runtime.duffxxx@GOT, R15
// ADDQ $offset, R15
// CALL R15
var sym *obj.LSym var sym *obj.LSym
if p.As == obj.ADUFFZERO { if p.As == obj.ADUFFZERO {
sym = obj.Linklookup(ctxt, "runtime.duffzero", 0) sym = obj.Linklookup(ctxt, "runtime.duffzero", 0)
...@@ -336,12 +348,17 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { ...@@ -336,12 +348,17 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
p2.To.Reg = REG_R15 p2.To.Reg = REG_R15
} }
if ctxt.Flag_dynlink { // We only care about global data: NAME_EXTERN means a global
// symbol in the Go sense, and p.Sym.Local is true for a few
// internally defined symbols.
if p.As == ALEAQ && p.From.Type == obj.TYPE_MEM && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local { if p.As == ALEAQ && p.From.Type == obj.TYPE_MEM && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
// LEAQ sym, Rx becomes MOVQ $sym, Rx which will be rewritten below
p.As = AMOVQ p.As = AMOVQ
p.From.Type = obj.TYPE_ADDR p.From.Type = obj.TYPE_ADDR
} }
if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local { if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
// MOVQ $sym, Rx becomes MOVQ sym@GOT, Rx
// MOVQ $sym+<off>, Rx becomes MOVQ sym@GOT, Rx; ADDQ <off>, Rx
if p.As != AMOVQ { if p.As != AMOVQ {
ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p) ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
} }
...@@ -363,6 +380,9 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { ...@@ -363,6 +380,9 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
ctxt.Diag("don't know how to handle %v with -dynlink", p) ctxt.Diag("don't know how to handle %v with -dynlink", p)
} }
var source *obj.Addr var source *obj.Addr
// MOVx sym, Ry becomes MOVW sym@GOT, R15; MOVx (R15), Ry
// MOVx Ry, sym becomes MOVW sym@GOT, R15; MOVx Ry, (R15)
// An addition may be inserted between the two MOVs if there is an offset.
if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local { if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local { if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p) ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
...@@ -403,13 +423,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { ...@@ -403,13 +423,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
} else { } else {
return return
} }
l := p.Link obj.Nopout(p)
l2 := p2.Link
*p = *p1
*p1 = *p2
p.Link = l
p1.Link = l2
}
} }
func nacladdr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) { func nacladdr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
......
...@@ -24,13 +24,13 @@ LEAQ name+10(SB), AX -> MOVQ name@GOT(SB), AX; ADDQ $10, AX ...@@ -24,13 +24,13 @@ LEAQ name+10(SB), AX -> MOVQ name@GOT(SB), AX; ADDQ $10, AX
MOVQ $name(SB), AX -> MOVQ name@GOT(SB), AX MOVQ $name(SB), AX -> MOVQ name@GOT(SB), AX
MOVQ $name+10(SB), AX -> MOVQ name@GOT(SB), AX; ADDQ $10, AX MOVQ $name+10(SB), AX -> MOVQ name@GOT(SB), AX; ADDQ $10, AX
MOVQ name(SB), AX -> MOVQ name@GOT(SB), R15; MOVQ (R15), AX MOVQ name(SB), AX -> NOP; MOVQ name@GOT(SB), R15; MOVQ (R15), AX
MOVQ name+10(SB), AX -> MOVQ name@GOT(SB), R15; MOVQ 10(R15), AX MOVQ name+10(SB), AX -> NOP; MOVQ name@GOT(SB), R15; MOVQ 10(R15), AX
CMPQ name(SB), $0 -> MOVQ name@GOT(SB), R15; CMPQ (R15), $0 CMPQ name(SB), $0 -> NOP; MOVQ name@GOT(SB), R15; CMPQ (R15), $0
MOVQ $1, name(SB) -> MOVQ name@GOT(SB), R15; MOVQ $1, (R15) MOVQ $1, name(SB) -> NOP; MOVQ name@GOT(SB), R15; MOVQ $1, (R15)
MOVQ $1, name+10(SB) -> MOVQ name@GOT(SB), R15; MOVQ $1, 10(R15) MOVQ $1, name+10(SB) -> NOP; MOVQ name@GOT(SB), R15; MOVQ $1, 10(R15)
` `
type ParsedTestData struct { type ParsedTestData struct {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment