summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/X86Subtarget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/X86/X86Subtarget.cpp')
-rw-r--r--llvm/lib/Target/X86/X86Subtarget.cpp44
1 files changed, 36 insertions, 8 deletions
diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp
index 8e1e35eebba..7e84323dda4 100644
--- a/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -68,14 +68,36 @@ X86Subtarget::classifyGlobalReference(const GlobalValue *GV) const {
unsigned char
X86Subtarget::classifyLocalReference(const GlobalValue *GV) const {
- // 64 bits can use %rip addressing for anything local.
- if (is64Bit())
+ // If we're not PIC, it's not very interesting.
+ if (!isPositionIndependent())
return X86II::MO_NO_FLAG;
- // If this is for a position dependent executable, the static linker can
- // figure it out.
- if (!isPositionIndependent())
+ if (is64Bit()) {
+ // 64-bit ELF PIC local references may use GOTOFF relocations.
+ if (isTargetELF()) {
+ switch (TM.getCodeModel()) {
+ // 64-bit small code model is simple: All rip-relative.
+ case CodeModel::Small:
+ case CodeModel::Kernel:
+ return X86II::MO_NO_FLAG;
+
+ // The large PIC code model uses GOTOFF.
+ case CodeModel::Large:
+ return X86II::MO_GOTOFF;
+
+ // Medium is a hybrid: RIP-rel for code, GOTOFF for DSO local data.
+ case CodeModel::Medium:
+ if (isa<Function>(GV))
+ return X86II::MO_NO_FLAG; // All code is RIP-relative
+ return X86II::MO_GOTOFF; // Local symbols use GOTOFF.
+ }
+ llvm_unreachable("invalid code model");
+ }
+
+ // Otherwise, this is either a RIP-relative reference or a 64-bit movabsq,
+ // both of which use MO_NO_FLAG.
return X86II::MO_NO_FLAG;
+ }
// The COFF dynamic linker just patches the executable sections.
if (isTargetCOFF())
@@ -97,8 +119,8 @@ X86Subtarget::classifyLocalReference(const GlobalValue *GV) const {
unsigned char X86Subtarget::classifyGlobalReference(const GlobalValue *GV,
const Module &M) const {
- // Large model never uses stubs.
- if (TM.getCodeModel() == CodeModel::Large)
+ // The static large model never uses stubs.
+ if (TM.getCodeModel() == CodeModel::Large && !isPositionIndependent())
return X86II::MO_NO_FLAG;
// Absolute symbols can be referenced directly.
@@ -120,8 +142,14 @@ unsigned char X86Subtarget::classifyGlobalReference(const GlobalValue *GV,
if (isTargetCOFF())
return X86II::MO_DLLIMPORT;
- if (is64Bit())
+ if (is64Bit()) {
+ // ELF supports a large, truly PIC code model with non-PC relative GOT
+ // references. Other object file formats do not. Use the no-flag, 64-bit
+ // reference for them.
+ if (TM.getCodeModel() == CodeModel::Large)
+ return isTargetELF() ? X86II::MO_GOT : X86II::MO_NO_FLAG;
return X86II::MO_GOTPCREL;
+ }
if (isTargetDarwin()) {
if (!isPositionIndependent())
OpenPOWER on IntegriCloud