From: Rafael Espindola Date: Fri, 11 Aug 2017 20:49:27 +0000 (+0000) Subject: Fix access to undefined weak symbols in pic code X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8026017fd0d296783f952c2ed942a8b8153e273e;p=llvm Fix access to undefined weak symbols in pic code When the access to a weak symbol is not a call, the access has to be able to produce the value 0 at runtime. We were sometimes producing code sequences where that was not possible if the code was leaded more than 4g away from 0. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310756 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index 493084f795f..1b02b88c187 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -99,6 +99,22 @@ X86Subtarget::classifyLocalReference(const GlobalValue *GV) const { 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. @@ -118,7 +134,7 @@ unsigned char X86Subtarget::classifyGlobalReference(const GlobalValue *GV, } } - if (TM.shouldAssumeDSOLocal(M, GV)) + if (shouldAssumeGlobalReferenceLocal(this, TM, M, GV)) return classifyLocalReference(GV); if (isTargetCOFF()) diff --git a/test/CodeGen/X86/weak-undef.ll b/test/CodeGen/X86/weak-undef.ll new file mode 100644 index 00000000000..7a71d980aaf --- /dev/null +++ b/test/CodeGen/X86/weak-undef.ll @@ -0,0 +1,58 @@ +; RUN: llc < %s -relocation-model=pic -mtriple=x86_64-pc-linux | FileCheck %s +; RUN: llc < %s -relocation-model=pic -mtriple=i386-pc-linux | FileCheck --check-prefix=I386 %s + +@foo1 = extern_weak hidden global i32, align 4 +define i32* @bar1() { + ret i32* @foo1 +} +; CHECK: bar1: +; CHECK: movq foo1@GOTPCREL(%rip), %rax +; I386: bar1: +; I386: leal foo1@GOTOFF(%eax), %eax + +@foo2 = external hidden global i32, align 4 +define i32* @bar2() { + ret i32* @foo2 +} +; CHECK: bar2: +; CHECK: leaq foo2(%rip), %rax +; I386: bar2: +; I386: leal foo2@GOTOFF(%eax), %eax + +declare extern_weak hidden void @foo3() +define void @bar3() { + call void @foo3() + ret void +} +; CHECK: bar3: +; CHECK: callq foo3 +; I386: bar3: +; I386: calll foo3 + +declare external hidden void @foo4() +define void @bar4() { + call void @foo4() + ret void +} +; CHECK: bar4: +; CHECK: callq foo4 +; I386: bar4: +; I386: calll foo4 + +declare extern_weak hidden i32 @foo5() +define i32()* @bar5() { + ret i32()* @foo5 +} +; CHECK: bar5: +; CHECK: movq foo5@GOTPCREL(%rip), %rax +; I386: bar5: +; I386: leal foo5@GOTOFF(%eax), %eax + +declare external hidden i32 @foo6() +define i32()* @bar6() { + ret i32()* @foo6 +} +; CHECK: bar6: +; CHECK: leaq foo6(%rip), %rax +; I386: bar6: +; I386: leal foo6@GOTOFF(%eax), %eax