Index: lib/Target/TargetMachine.cpp =================================================================== --- lib/Target/TargetMachine.cpp +++ lib/Target/TargetMachine.cpp @@ -134,6 +134,16 @@ if (TT.isOSBinFormatCOFF() || (TT.isOSWindows() && TT.isOSBinFormatMachO())) return true; + // A weak undef symbol might resolve to 0. We have to assume it is + // not local, as we have no control of where in memory we will end + // up. + // FIXME: is this true for all architectures? + // FIXME2: this is false for some relocations. For example, it should be valid + // to produce "call foo" instead of "call foo@plt". It is not clear if that is + // a problem. + if (GV && GV->hasExternalWeakLinkage() && isPositionIndependent()) + return false; + if (GV && (GV->hasLocalLinkage() || !GV->hasDefaultVisibility())) return true; 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 @@ -63,6 +63,20 @@ ret i32 %0 } +; ExternalWeak Linkage +@e = extern_weak global i32, align 4 + +define i32* @my_access_global_d() #0 { +; X32-LABEL: my_access_global_d: +; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %eax +; X32: movl e@GOT(%eax), %eax +; X64-LABEL: my_access_global_d: +; X64: movq e@GOTPCREL(%rip), %rax + +entry: + ret i32* @e +} + ; External Linkage, only declaration, store a value. define i32 @my_access_global_store_d() #0 { Index: test/CodeGen/X86/hidden-vis-3.ll =================================================================== --- test/CodeGen/X86/hidden-vis-3.ll +++ test/CodeGen/X86/hidden-vis-3.ll @@ -10,7 +10,8 @@ ; X32: movl _y, %eax ; X64: _t: -; X64: movl _y(%rip), %eax +; X64: movq _y@GOTPCREL(%rip), %rax +; X64: movl (%rax), %eax %0 = load i32, i32* @x, align 4 ; [#uses=1] %1 = load i32, i32* @y, align 4 ; [#uses=1] 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() { @@ -25,9 +25,9 @@ ret void } ; CHECK: bar3: -; CHECK: callq foo3 +; CHECK: callq foo3@PLT ; I386: bar3: -; I386: calll foo3 +; I386: calll foo3@PLT declare external hidden void @foo4() define void @bar4() { @@ -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() {