Index: lib/Target/TargetMachine.cpp =================================================================== --- lib/Target/TargetMachine.cpp +++ lib/Target/TargetMachine.cpp @@ -128,6 +128,15 @@ if (TT.isOSBinFormatCOFF() || (TT.isOSWindows() && TT.isOSBinFormatMachO())) return true; + // Most PIC code sequences that assume that a symbol is local cannot + // produce a 0 if it turns out the symbol is undefined. While this + // is ABI and relocation depended, it seems worth it to handle it + // here. + // FIXME: this is probably not ELF specific. + if (GV && isPositionIndependent() && TT.isOSBinFormatELF() && + GV->hasExternalWeakLinkage()) + return false; + if (GV && (GV->hasLocalLinkage() || !GV->hasDefaultVisibility())) return true; @@ -148,9 +157,8 @@ return true; bool IsTLS = GV && GV->isThreadLocal(); - bool IsAccessViaCopyRelocs = Options.MCOptions.MCPIECopyRelocations && GV && - isa(GV) && - !GV->hasExternalWeakLinkage(); + bool IsAccessViaCopyRelocs = + Options.MCOptions.MCPIECopyRelocations && GV && isa(GV); Triple::ArchType Arch = TT.getArch(); bool IsPPC = Arch == Triple::ppc || Arch == Triple::ppc64 || Arch == Triple::ppc64le; Index: lib/Target/X86/X86Subtarget.cpp =================================================================== --- lib/Target/X86/X86Subtarget.cpp +++ lib/Target/X86/X86Subtarget.cpp @@ -99,22 +99,6 @@ return X86II::MO_GOTOFF; } -static bool shouldAssumeGlobalReferenceLocal(const X86Subtarget *ST, - const TargetMachine &TM, - const Module &M, - const GlobalValue *GV) { - if (!TM.shouldAssumeDSOLocal(M, GV)) - return false; - // A weak reference can end up being 0. If the code can be more that 4g away - // from zero and we are using the small code model we have to treat it as non - // local. - if (GV && GV->hasExternalWeakLinkage() && - TM.getCodeModel() == CodeModel::Small && TM.isPositionIndependent() && - ST->is64Bit() && ST->isTargetELF()) - return false; - return true; -} - unsigned char X86Subtarget::classifyGlobalReference(const GlobalValue *GV, const Module &M) const { // Large model never uses stubs. @@ -134,7 +118,7 @@ } } - if (shouldAssumeGlobalReferenceLocal(this, TM, M, GV)) + if (TM.shouldAssumeDSOLocal(M, GV)) return classifyLocalReference(GV); if (isTargetCOFF()) Index: test/CodeGen/X86/global-access-pie-copyrelocs.ll =================================================================== --- test/CodeGen/X86/global-access-pie-copyrelocs.ll +++ test/CodeGen/X86/global-access-pie-copyrelocs.ll @@ -77,6 +77,19 @@ ret i32* @e } +; ExternalWeak hidden Linkage +@he = extern_weak hidden global i32, align 4 + +define i32* @my_access_global_he() #0 { +; X32-LABEL: my_access_global_he: +; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %eax +; X32: movl he@GOT(%eax), %eax +; X64-LABEL: my_access_global_he: +; X64: movq he@GOTPCREL(%rip), %rax + ret i32* @he +} + + ; External Linkage, only declaration, store a value. define i32 @my_access_global_store_d() #0 { Index: test/CodeGen/X86/weak-undef.ll =================================================================== --- test/CodeGen/X86/weak-undef.ll +++ test/CodeGen/X86/weak-undef.ll @@ -8,7 +8,7 @@ ; CHECK: bar1: ; CHECK: movq foo1@GOTPCREL(%rip), %rax ; I386: bar1: -; I386: leal foo1@GOTOFF(%eax), %eax +; I386: movl foo1@GOT(%eax), %eax @foo2 = external hidden global i32, align 4 define i32* @bar2() { @@ -46,7 +46,7 @@ ; CHECK: bar5: ; CHECK: movq foo5@GOTPCREL(%rip), %rax ; I386: bar5: -; I386: leal foo5@GOTOFF(%eax), %eax +; I386: movl foo5@GOT(%eax), %eax declare external hidden i32 @foo6() define i32()* @bar6() {