diff options
-rw-r--r-- | lib/Target/PowerPC/PPCCodeEmitter.cpp | 52 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCISelLowering.cpp | 3 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCSubtarget.cpp | 38 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCSubtarget.h | 18 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCTargetMachine.cpp | 5 |
5 files changed, 83 insertions, 33 deletions
diff --git a/lib/Target/PowerPC/PPCCodeEmitter.cpp b/lib/Target/PowerPC/PPCCodeEmitter.cpp index 3857c6a3ed..cabe308ce9 100644 --- a/lib/Target/PowerPC/PPCCodeEmitter.cpp +++ b/lib/Target/PowerPC/PPCCodeEmitter.cpp @@ -136,15 +136,9 @@ int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) { if (MI.getOpcode() == PPC::BL || MI.getOpcode() == PPC::BL8) Reloc = PPC::reloc_pcrel_bx; else { - // If in PIC mode, we need to encode the negated address of the - // 'movepctolr' into the unrelocated field. After relocation, we'll have - // &gv-&movepctolr in the imm field. Once &movepctolr is added to the imm - // field, we get &gv. if (TM.getRelocationModel() == Reloc::PIC_) { assert(MovePCtoLROffset && "MovePCtoLR not seen yet?"); - rv = -(intptr_t)MovePCtoLROffset - 4; } - switch (MI.getOpcode()) { default: MI.dump(); assert(0 && "Unknown instruction for relocation!"); case PPC::LIS: @@ -152,7 +146,6 @@ int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) { case PPC::ADDIS: case PPC::ADDIS8: Reloc = PPC::reloc_absolute_high; // Pointer to symbol - rv >>= 16; break; case PPC::LI: case PPC::LI8: @@ -173,7 +166,6 @@ int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) { case PPC::STFS: case PPC::STFD: Reloc = PPC::reloc_absolute_low; - rv &= 0xFFFF; break; case PPC::LWA: @@ -181,25 +173,37 @@ int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) { case PPC::STD: case PPC::STD_32: Reloc = PPC::reloc_absolute_low_ix; - rv &= 0xFFFF; - rv >>= 2; break; } } - if (MO.isGlobalAddress()) - MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), - Reloc, MO.getGlobal(), 0)); - else if (MO.isExternalSymbol()) - MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), - Reloc, MO.getSymbolName(), 0)); - else if (MO.isConstantPoolIndex()) - MCE.addRelocation(MachineRelocation::getConstPool( - MCE.getCurrentPCOffset(), - Reloc, MO.getConstantPoolIndex(), 0)); - else // isJumpTableIndex - MCE.addRelocation(MachineRelocation::getJumpTable( - MCE.getCurrentPCOffset(), - Reloc, MO.getJumpTableIndex(), 0)); + + MachineRelocation R; + if (MO.isGlobalAddress()) { + R = MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, + MO.getGlobal(), 0); + } else if (MO.isExternalSymbol()) { + R = MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), + Reloc, MO.getSymbolName(), 0); + } else if (MO.isConstantPoolIndex()) { + R = MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), + Reloc, MO.getConstantPoolIndex(), 0); + } else { + assert(MO.isJumpTableIndex()); + R = MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), + Reloc, MO.getJumpTableIndex(), 0); + } + + // If in PIC mode, we need to encode the negated address of the + // 'movepctolr' into the unrelocated field. After relocation, we'll have + // &gv-&movepctolr-4 in the imm field. Once &movepctolr is added to the imm + // field, we get &gv. This doesn't happen for branch relocations, which are + // always implicitly pc relative. + if (TM.getRelocationModel() == Reloc::PIC_ && Reloc != PPC::reloc_pcrel_bx){ + assert(MovePCtoLROffset && "MovePCtoLR not seen yet?"); + R.setConstantVal(-(intptr_t)MovePCtoLROffset - 4); + } + MCE.addRelocation(R); + } else if (MO.isMachineBasicBlock()) { unsigned Reloc = 0; unsigned Opcode = MI.getOpcode(); diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index af202e2743..08dae42476 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1015,8 +1015,7 @@ static SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) { Lo = DAG.getNode(ISD::ADD, PtrVT, Hi, Lo); - if (!GV->hasWeakLinkage() && !GV->hasLinkOnceLinkage() && - (!GV->isExternal() || GV->hasNotBeenReadFromBytecode())) + if (!TM.getSubtarget<PPCSubtarget>().hasLazyResolverStub(GV)) return Lo; // If the global is weak or external, we have to go through the lazy diff --git a/lib/Target/PowerPC/PPCSubtarget.cpp b/lib/Target/PowerPC/PPCSubtarget.cpp index 5c18e65665..eca16c4a38 100644 --- a/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/lib/Target/PowerPC/PPCSubtarget.cpp @@ -14,6 +14,7 @@ #include "PPCSubtarget.h" #include "PPC.h" #include "llvm/Module.h" +#include "llvm/Target/TargetMachine.h" #include "PPCGenSubtarget.inc" using namespace llvm; @@ -55,9 +56,10 @@ static const char *GetCurrentPowerPCCPU() { #endif -PPCSubtarget::PPCSubtarget(const Module &M, const std::string &FS, bool is64Bit) - : StackAlignment(16) - , InstrItins() +PPCSubtarget::PPCSubtarget(const TargetMachine &tm, const Module &M, + const std::string &FS, bool is64Bit) + : TM(tm) + , StackAlignment(16) , IsGigaProcessor(false) , Has64BitSupport(false) , Use64BitRegs(false) @@ -65,7 +67,8 @@ PPCSubtarget::PPCSubtarget(const Module &M, const std::string &FS, bool is64Bit) , HasAltivec(false) , HasFSQRT(false) , HasSTFIWX(false) - , IsDarwin(false) { + , IsDarwin(false) + , HasLazyResolverStubs(false) { // Determine default and user specified characteristics std::string CPU = "generic"; @@ -105,4 +108,31 @@ PPCSubtarget::PPCSubtarget(const Module &M, const std::string &FS, bool is64Bit) IsDarwin = true; #endif } + + // Set up darwin-specific properties. + if (IsDarwin) { + HasLazyResolverStubs = true; + } +} + +/// SetJITMode - This is called to inform the subtarget info that we are +/// producing code for the JIT. +void PPCSubtarget::SetJITMode() { + // JIT mode doesn't want lazy resolver stubs, it knows exactly where + // everything is. This matters for PPC64, which codegens in PIC mode without + // stubs. + HasLazyResolverStubs = false; +} + + +/// hasLazyResolverStub - Return true if accesses to the specified global have +/// to go through a dyld lazy resolution stub. This means that an extra load +/// is required to get the address of the global. +bool PPCSubtarget::hasLazyResolverStub(const GlobalValue *GV) const { + // We never hae stubs if HasLazyResolverStubs=false or if in static mode. + if (!HasLazyResolverStubs || TM.getRelocationModel() == Reloc::Static) + return false; + + return GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || + (GV->isExternal() && !GV->hasNotBeenReadFromBytecode()); } diff --git a/lib/Target/PowerPC/PPCSubtarget.h b/lib/Target/PowerPC/PPCSubtarget.h index 1cce24d2f6..e8ad25f3eb 100644 --- a/lib/Target/PowerPC/PPCSubtarget.h +++ b/lib/Target/PowerPC/PPCSubtarget.h @@ -21,9 +21,13 @@ namespace llvm { class Module; - +class GlobalValue; +class TargetMachine; + class PPCSubtarget : public TargetSubtarget { protected: + const TargetMachine &TM; + /// stackAlignment - The minimum alignment known to hold of the stack frame on /// entry to the function and which must be maintained by every function. unsigned StackAlignment; @@ -40,15 +44,21 @@ protected: bool HasFSQRT; bool HasSTFIWX; bool IsDarwin; + bool HasLazyResolverStubs; public: /// This constructor initializes the data members to match that /// of the specified module. /// - PPCSubtarget(const Module &M, const std::string &FS, bool is64Bit); + PPCSubtarget(const TargetMachine &TM, const Module &M, + const std::string &FS, bool is64Bit); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); + + /// SetJITMode - This is called to inform the subtarget info that we are + /// producing code for the JIT. + void SetJITMode(); /// getStackAlignment - Returns the minimum alignment known to hold of the /// stack frame on entry to the function and which must be maintained by every @@ -78,6 +88,10 @@ public: /// has64BitSupport() returns true. bool use64BitRegs() const { return Use64BitRegs; } + /// hasLazyResolverStub - Return true if accesses to the specified global have + /// to go through a dyld lazy resolution stub. This means that an extra load + /// is required to get the address of the global. + bool hasLazyResolverStub(const GlobalValue *GV) const; // Specific obvious features. bool hasFSQRT() const { return HasFSQRT; } diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index 9dcbc04870..8cf85d186f 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -81,7 +81,7 @@ unsigned PPC64TargetMachine::getModuleMatchQuality(const Module &M) { PPCTargetMachine::PPCTargetMachine(const Module &M, const std::string &FS, bool is64Bit) - : Subtarget(M, FS, is64Bit), + : Subtarget(*this, M, FS, is64Bit), DataLayout(Subtarget.getTargetDataString()), InstrInfo(*this), FrameInfo(*this, is64Bit), JITInfo(*this, is64Bit), TLInfo(*this), InstrItins(Subtarget.getInstrItineraryData()) { @@ -146,6 +146,9 @@ bool PPCTargetMachine::addCodeEmitter(FunctionPassManager &PM, bool Fast, setRelocationModel(Reloc::Static); } + // Inform the subtarget that we are in JIT mode. FIXME: does this break macho + // writing? + Subtarget.SetJITMode(); // Machine code emitter pass for PowerPC. PM.add(createPPCCodeEmitterPass(*this, MCE)); |