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.cpp32
1 files changed, 24 insertions, 8 deletions
diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp
index 8e1e35eebba..b7cab75f5a5 100644
--- a/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -68,15 +68,31 @@ 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())
- return X86II::MO_NO_FLAG;
-
- // If this is for a position dependent executable, the static linker can
- // figure it out.
+ // If we're not PIC, it's not very interesting.
if (!isPositionIndependent())
return X86II::MO_NO_FLAG;
+ // For 64-bit, we need to consider the code model.
+ if (is64Bit()) {
+ 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");
+ }
+
// The COFF dynamic linker just patches the executable sections.
if (isTargetCOFF())
return X86II::MO_NO_FLAG;
@@ -98,7 +114,7 @@ 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)
+ if (TM.getCodeModel() == CodeModel::Large && !isPositionIndependent())
return X86II::MO_NO_FLAG;
// Absolute symbols can be referenced directly.
@@ -120,7 +136,7 @@ unsigned char X86Subtarget::classifyGlobalReference(const GlobalValue *GV,
if (isTargetCOFF())
return X86II::MO_DLLIMPORT;
- if (is64Bit())
+ if (is64Bit() && TM.getCodeModel() != CodeModel::Large)
return X86II::MO_GOTPCREL;
if (isTargetDarwin()) {
OpenPOWER on IntegriCloud