diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index dfabfd4124..04f829a7d7 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -3450,6 +3450,10 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { log.Fatalf("bad code") } + if yt.zcase == Zcallduff && ctxt.Flag_dynlink { + ctxt.Diag("directly calling duff when dynamically linking Go") + } + if obj.Framepointer_enabled != 0 && yt.zcase == Zcallduff && p.Mode == 64 { // Maintain BP around call, since duffcopy/duffzero can't do it // (the call jumps into the middle of the function). diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go index 2d30e9ebd4..31475733e3 100644 --- a/src/cmd/internal/obj/x86/obj6.go +++ b/src/cmd/internal/obj/x86/obj6.go @@ -298,6 +298,34 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { } } + if ctxt.Flag_dynlink && (p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO) { + var sym *obj.LSym + if p.As == obj.ADUFFZERO { + sym = obj.Linklookup(ctxt, "runtime.duffzero", 0) + } else { + sym = obj.Linklookup(ctxt, "runtime.duffcopy", 0) + } + offset := p.To.Offset + p.As = AMOVQ + p.From.Type = obj.TYPE_MEM + p.From.Name = obj.NAME_GOTREF + p.From.Sym = sym + p.To.Type = obj.TYPE_REG + p.To.Reg = REG_R15 + p.To.Offset = 0 + p.To.Sym = nil + p1 := obj.Appendp(ctxt, p) + p1.As = AADDQ + p1.From.Type = obj.TYPE_CONST + p1.From.Offset = offset + p1.To.Type = obj.TYPE_REG + p1.To.Reg = REG_R15 + p2 := obj.Appendp(ctxt, p1) + p2.As = obj.ACALL + p2.To.Type = obj.TYPE_REG + p2.To.Reg = REG_R15 + } + if ctxt.Flag_dynlink { if p.As == ALEAQ && p.From.Type == obj.TYPE_MEM && p.From.Name == obj.NAME_EXTERN { p.As = AMOVQ