diff options
Diffstat (limited to 'llvm/lib/Target/X86/X86InstrInfo.cpp')
-rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.cpp | 56 |
1 files changed, 42 insertions, 14 deletions
diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index cfa25731c40..604cad3abc6 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -11333,7 +11333,9 @@ isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const { /// TODO: Eliminate this and move the code to X86MachineFunctionInfo. /// unsigned X86InstrInfo::getGlobalBaseReg(MachineFunction *MF) const { - assert(!Subtarget.is64Bit() && + assert((!Subtarget.is64Bit() || + MF->getTarget().getCodeModel() == CodeModel::Medium || + MF->getTarget().getCodeModel() == CodeModel::Large) && "X86-64 PIC uses RIP relative addressing"); X86MachineFunctionInfo *X86FI = MF->getInfo<X86MachineFunctionInfo>(); @@ -11344,7 +11346,8 @@ unsigned X86InstrInfo::getGlobalBaseReg(MachineFunction *MF) const { // Create the register. The code to initialize it is inserted // later, by the CGBR pass (below). MachineRegisterInfo &RegInfo = MF->getRegInfo(); - GlobalBaseReg = RegInfo.createVirtualRegister(&X86::GR32_NOSPRegClass); + GlobalBaseReg = RegInfo.createVirtualRegister( + Subtarget.is64Bit() ? &X86::GR64_NOSPRegClass : &X86::GR32_NOSPRegClass); X86FI->setGlobalBaseReg(GlobalBaseReg); return GlobalBaseReg; } @@ -12720,7 +12723,8 @@ namespace { // Don't do anything if this is 64-bit as 64-bit PIC // uses RIP relative addressing. - if (STI.is64Bit()) + if (STI.is64Bit() && (TM->getCodeModel() == CodeModel::Small || + TM->getCodeModel() == CodeModel::Kernel)) return false; // Only emit a global base reg in PIC mode. @@ -12747,17 +12751,41 @@ namespace { else PC = GlobalBaseReg; - // Operand of MovePCtoStack is completely ignored by asm printer. It's - // only used in JIT code emission as displacement to pc. - BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOVPC32r), PC).addImm(0); - - // If we're using vanilla 'GOT' PIC style, we should use relative addressing - // not to pc, but to _GLOBAL_OFFSET_TABLE_ external. - if (STI.isPICStyleGOT()) { - // Generate addl $__GLOBAL_OFFSET_TABLE_ + [.-piclabel], %some_register - BuildMI(FirstMBB, MBBI, DL, TII->get(X86::ADD32ri), GlobalBaseReg) - .addReg(PC).addExternalSymbol("_GLOBAL_OFFSET_TABLE_", - X86II::MO_GOT_ABSOLUTE_ADDRESS); + if (STI.is64Bit()) { + if (TM->getCodeModel() == CodeModel::Medium) { + BuildMI(FirstMBB, MBBI, DL, TII->get(X86::LEA64r), PC) + .addReg(X86::RIP) + .addImm(0) + .addReg(0) + .addExternalSymbol("_GLOBAL_OFFSET_TABLE_") + .addReg(0); + } else if (TM->getCodeModel() == CodeModel::Large) { + // Loading the GOT in the large code model requires math with labels, + // so we use a pseudo instruction and expand it during MC emission. + // FIXME: Are we using the right register state for a scratch register + // that doesn't conflict with the destination? + unsigned Scratch = RegInfo.createVirtualRegister(&X86::GR64RegClass); + BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOVGOT64r), PC) + .addReg(Scratch, RegState::Undef | RegState::Define) + .addExternalSymbol("_GLOBAL_OFFSET_TABLE_"); + } else { + llvm_unreachable("unexpected code model"); + } + } else { + // Operand of MovePCtoStack is completely ignored by asm printer. It's + // only used in JIT code emission as displacement to pc. + BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOVPC32r), PC).addImm(0); + + // If we're using vanilla 'GOT' PIC style, we should use relative + // addressing not to pc, but to _GLOBAL_OFFSET_TABLE_ external. + if (STI.isPICStyleGOT()) { + // Generate addl $__GLOBAL_OFFSET_TABLE_ + [.-piclabel], + // %some_register + BuildMI(FirstMBB, MBBI, DL, TII->get(X86::ADD32ri), GlobalBaseReg) + .addReg(PC) + .addExternalSymbol("_GLOBAL_OFFSET_TABLE_", + X86II::MO_GOT_ABSOLUTE_ADDRESS); + } } return true; |