diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 53385d945e9..68a36aee162 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -158,7 +158,7 @@ bool ARMCodeEmitter::runOnMachineFunction(MachineFunction &MF) { TD = ((ARMTargetMachine&)MF.getTarget()).getTargetData(); JTI = ((ARMTargetMachine&)MF.getTarget()).getJITInfo(); MCPEs = &MF.getConstantPool()->getConstants(); - JTI->ResizeConstPoolMap(MCPEs->size()); + JTI->Initialize(MCPEs); do { DOUT << "JITTing function '" << MF.getFunction()->getName() << "'\n"; @@ -257,7 +257,7 @@ void ARMCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB) { } void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { - DOUT << "JIT: " << "0x" << MCE.getCurrentPCValue() << ":\t" << MI; + DOUT << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI; NumEmitted++; // Keep track of the # of mi's emitted if ((MI.getDesc().TSFlags & ARMII::FormMask) == ARMII::Pseudo) @@ -286,8 +286,10 @@ void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) { GlobalValue *GV = ACPV->getGV(); if (GV) { assert(!ACPV->isStub() && "Don't know how to deal this yet!"); - emitGlobalAddress(GV, ARM::reloc_arm_absolute, false); - } else { + MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), + ARM::reloc_arm_machine_cp_entry, + GV, CPIndex, false)); + } else { assert(!ACPV->isNonLazyPointer() && "Don't know how to deal this yet!"); emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute); } @@ -320,6 +322,12 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { emitConstPoolInstruction(MI); break; case ARM::PICADD: { + // Remember of the address of the PC label for relocation later. + const MachineOperand &MO2 = MI.getOperand(2); + DOUT << "\t** LPC" << MO2.getImm() << " @ " + << (void*)MCE.getCurrentPCValue() << '\n'; + JTI->addPCLabelAddr(MO2.getImm(), MCE.getCurrentPCValue()); + // PICADD is just an add instruction that implicitly read pc. unsigned Binary = getBinaryCodeForInstr(MI); const TargetInstrDesc &TID = MI.getDesc(); diff --git a/lib/Target/ARM/ARMConstantPoolValue.cpp b/lib/Target/ARM/ARMConstantPoolValue.cpp index 002ebf109f7..c95a6e6b470 100644 --- a/lib/Target/ARM/ARMConstantPoolValue.cpp +++ b/lib/Target/ARM/ARMConstantPoolValue.cpp @@ -93,10 +93,8 @@ void ARMConstantPoolValue::print(raw_ostream &O) const { else if (isStub()) O << "$stub"; if (Modifier) O << "(" << Modifier << ")"; if (PCAdjust != 0) { - O << "-(LPIC" << LabelId << "+" - << (unsigned)PCAdjust; - if (AddCurrentAddress) - O << "-."; + O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust; + if (AddCurrentAddress) O << "-."; O << ")"; } } diff --git a/lib/Target/ARM/ARMJITInfo.cpp b/lib/Target/ARM/ARMJITInfo.cpp index 6a2c253ff11..2f04d0b4e8a 100644 --- a/lib/Target/ARM/ARMJITInfo.cpp +++ b/lib/Target/ARM/ARMJITInfo.cpp @@ -13,6 +13,7 @@ #define DEBUG_TYPE "jit" #include "ARMJITInfo.h" +#include "ARMConstantPoolValue.h" #include "ARMRelocations.h" #include "ARMSubtarget.h" #include "llvm/Function.h" @@ -167,6 +168,25 @@ void *ARMJITInfo::emitFunctionStub(const Function* F, void *Fn, return MCE.finishFunctionStub(F); } +intptr_t ARMJITInfo::resolveRelocationAddr(MachineRelocation *MR) const { + ARM::RelocationType RT = (ARM::RelocationType)MR->getRelocationType(); + if (RT == ARM::reloc_arm_cp_entry) + return getConstantPoolEntryAddr(MR->getConstantPoolIndex()); + else if (RT == ARM::reloc_arm_machine_cp_entry) { + const MachineConstantPoolEntry &MCPE = (*MCPEs)[MR->getConstantVal()]; + assert(MCPE.isMachineConstantPoolEntry() && + "Expecting a machine constant pool entry!"); + ARMConstantPoolValue *ACPV = + static_cast(MCPE.Val.MachineCPVal); + assert((!ACPV->hasModifier() && !ACPV->mustAddCurrentAddress()) && + "Can't handle this machine constant pool entry yet!"); + intptr_t Addr = (intptr_t)(MR->getResultPointer()); + Addr -= getPCLabelAddr(ACPV->getLabelId()) + ACPV->getPCAdjustment(); + return Addr; + } + return (intptr_t)(MR->getResultPointer()); +} + /// relocate - Before the JIT can run a block of code that has been emitted, /// it must rewrite the code to contain the actual addresses of any /// referenced global symbols. @@ -174,12 +194,9 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR, unsigned NumRelocs, unsigned char* GOTBase) { for (unsigned i = 0; i != NumRelocs; ++i, ++MR) { void *RelocPos = (char*)Function + MR->getMachineCodeOffset(); - ARM::RelocationType RT = (ARM::RelocationType)MR->getRelocationType(); // If this is a constpool relocation, get the address of the // constpool_entry instruction. - intptr_t ResultPtr = (RT == ARM::reloc_arm_cp_entry) - ? getConstantPoolEntryAddr(MR->getConstantPoolIndex()) - : (intptr_t)MR->getResultPointer(); + intptr_t ResultPtr = resolveRelocationAddr(MR); switch ((ARM::RelocationType)MR->getRelocationType()) { case ARM::reloc_arm_cp_entry: case ARM::reloc_arm_relative: { @@ -190,18 +207,20 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR, if (ResultPtr >= 0) *((unsigned*)RelocPos) |= 1 << 23; else { - // otherwise, obtain the absolute value and set + // Otherwise, obtain the absolute value and set // bit U(23) to 0. ResultPtr *= -1; *((unsigned*)RelocPos) &= 0xFF7FFFFF; } - // set the immed value calculated + // Set the immed value calculated. *((unsigned*)RelocPos) |= (unsigned)ResultPtr; - // set register Rn to PC + // Set register Rn to PC. *((unsigned*)RelocPos) |= 0xF << 16; break; } + case ARM::reloc_arm_machine_cp_entry: case ARM::reloc_arm_absolute: { + // These addresses have already been resolved. *((unsigned*)RelocPos) += (unsigned)ResultPtr; break; } diff --git a/lib/Target/ARM/ARMJITInfo.h b/lib/Target/ARM/ARMJITInfo.h index cdcd1ad1d64..ba8768aec4b 100644 --- a/lib/Target/ARM/ARMJITInfo.h +++ b/lib/Target/ARM/ARMJITInfo.h @@ -15,6 +15,8 @@ #define ARMJITINFO_H #include "llvm/Target/TargetJITInfo.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" namespace llvm { @@ -23,10 +25,17 @@ namespace llvm { class ARMJITInfo : public TargetJITInfo { ARMTargetMachine &TM; + // MCPEs - List of the constant pool entries for the current machine + // function that's being processed. + const std::vector *MCPEs; + // ConstPoolId2AddrMap - A map from constant pool ids to the corresponding // CONSTPOOL_ENTRY addresses. SmallVector ConstPoolId2AddrMap; + // PCLabelMap - A map from PC labels to addresses. + DenseMap PCLabelMap; + public: explicit ARMJITInfo(ARMTargetMachine &tm) : TM(tm) { useGOT = false; } @@ -51,15 +60,16 @@ namespace llvm { /// referenced global symbols. virtual void relocate(void *Function, MachineRelocation *MR, unsigned NumRelocs, unsigned char* GOTBase); - + /// hasCustomConstantPool - Allows a target to specify that constant /// pool address resolution is handled by the target. virtual bool hasCustomConstantPool() const { return true; } - /// ResizeConstPoolMap - Resize constant pool ids to CONSTPOOL_ENTRY - /// addresses map. - void ResizeConstPoolMap(unsigned Size) { - ConstPoolId2AddrMap.resize(Size); + /// Initialize - Initialize internal stage. Get the list of constant pool + /// Resize constant pool ids to CONSTPOOL_ENTRY addresses map. + void Initialize(const std::vector *mcpes) { + MCPEs = mcpes; + ConstPoolId2AddrMap.resize(MCPEs->size()); } /// getConstantPoolEntryAddr - The ARM target puts all constant @@ -77,6 +87,24 @@ namespace llvm { assert(CPI < ConstPoolId2AddrMap.size()); ConstPoolId2AddrMap[CPI] = Addr; } + + /// getPCLabelAddr - Retrieve the address of the PC label of the specified id. + intptr_t getPCLabelAddr(unsigned Id) const { + DenseMap::const_iterator I = PCLabelMap.find(Id); + assert(I != PCLabelMap.end()); + return I->second; + } + + /// addPCLabelAddr - Remember the address of the specified PC label. + void addPCLabelAddr(unsigned Id, intptr_t Addr) { + PCLabelMap.insert(std::make_pair(Id, Addr)); + } + + private: + /// resolveRelocationAddr - Resolve the resulting address of the relocation + /// if it's not already solved. Constantpool entries must be resolved by + /// ARM target. + intptr_t resolveRelocationAddr(MachineRelocation *MR) const; }; } diff --git a/lib/Target/ARM/ARMRelocations.h b/lib/Target/ARM/ARMRelocations.h index 93101a61797..2c1a98990a2 100644 --- a/lib/Target/ARM/ARMRelocations.h +++ b/lib/Target/ARM/ARMRelocations.h @@ -31,6 +31,10 @@ namespace llvm { // addresses are kept locally in a map. reloc_arm_cp_entry, + // reloc_arm_machine_cp_entry - Relocation of a ARM machine constantpool + // entry. + reloc_arm_machine_cp_entry, + // reloc_arm_branch - Branch address relocation. reloc_arm_branch };