diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 641e1a1205f..b6a57e53309 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -12,9 +12,10 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "arm-emitter" +#define DEBUG_TYPE "jit" #include "ARM.h" #include "ARMAddressingModes.h" +#include "ARMConstantPoolValue.h" #include "ARMInstrInfo.h" #include "ARMRelocations.h" #include "ARMSubtarget.h" @@ -192,7 +193,7 @@ unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI, else if (MO.isSymbol()) emitExternalSymbolAddress(MO.getSymbolName(), ARM::reloc_arm_relative); else if (MO.isCPI()) - emitConstPoolAddress(MO.getIndex(), ARM::reloc_arm_relative); + emitConstPoolAddress(MO.getIndex(), ARM::reloc_arm_cp_entry); else if (MO.isJTI()) emitJumpTableAddress(MO.getIndex(), ARM::reloc_arm_relative); else if (MO.isMBB()) @@ -226,8 +227,9 @@ void ARMCodeEmitter::emitExternalSymbolAddress(const char *ES, unsigned Reloc) { void ARMCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc, int Disp /* = 0 */, unsigned PCAdj /* = 0 */) { + // Tell JIT emitter we'll resolve the address. MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), - Reloc, CPI, PCAdj)); + Reloc, CPI, PCAdj, true)); } /// emitJumpTableAddress - Arrange for the address of a jump table to @@ -246,7 +248,7 @@ void ARMCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB) { } void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { - DOUT << MI; + DOUT << "JIT: " << "0x" << MCE.getCurrentPCValue() << ":\t" << MI; NumEmitted++; // Keep track of the # of mi's emitted if ((MI.getDesc().TSFlags & ARMII::FormMask) == ARMII::Pseudo) @@ -360,29 +362,47 @@ unsigned ARMCodeEmitter::getAddrMode1SBit(const MachineInstr &MI, } void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) { - unsigned CPID = MI.getOperand(0).getImm(); + unsigned CPI = MI.getOperand(0).getImm(); unsigned CPIndex = MI.getOperand(1).getIndex(); const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIndex]; - //FIXME: Can we get these here? - assert (!MCPE.isMachineConstantPoolEntry()); + // Remember the CONSTPOOL_ENTRY address for later relocation. + JTI->addConstantPoolEntryAddr(CPI, MCE.getCurrentPCValue()); - const Constant *CV = MCPE.Val.ConstVal; - // FIXME: We can get other types here. Need to handle them. - // According to the constant island pass, everything is multiples, - // of 4-bytes in size, though, so that helps. - assert (CV->getType()->isInteger()); - assert (cast(CV->getType())->getBitWidth() == 32); + // Emit constpool island entry. In most cases, the actual values will be + // resolved and relocated after code emission. + if (MCPE.isMachineConstantPoolEntry()) { + ARMConstantPoolValue *ACPV = + static_cast(MCPE.Val.MachineCPVal); - const ConstantInt *CI = dyn_cast(CV); - uint32_t Val = *(uint32_t*)CI->getValue().getRawData(); + DOUT << "\t** ARM constant pool #" << CPI << ", ' @ " + << (void*)MCE.getCurrentPCValue() << *ACPV << '\n'; - DOUT << "Constant pool #" << CPID << ", value '" << Val << "' @ " << - (void*)MCE.getCurrentPCValue() << "\n"; + 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 { + assert(!ACPV->isNonLazyPointer() && "Don't know how to deal this yet!"); + emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute); + } + MCE.emitWordLE(0); + } else { + Constant *CV = MCPE.Val.ConstVal; - if (JTI) - JTI->mapCPIDtoAddress(CPID, MCE.getCurrentPCValue()); - MCE.emitWordLE(Val); + DOUT << "\t** Constant pool #" << CPI << ", ' @ " + << (void*)MCE.getCurrentPCValue() << *CV << '\n'; + + if (GlobalValue *GV = dyn_cast(CV)) { + emitGlobalAddress(GV, ARM::reloc_arm_absolute, false); + MCE.emitWordLE(0); + } else { + abort(); // FIXME: Is this right? + const ConstantInt *CI = dyn_cast(CV); + uint32_t Val = *(uint32_t*)CI->getValue().getRawData(); + MCE.emitWordLE(Val); + } + } } void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { diff --git a/lib/Target/ARM/ARMJITInfo.cpp b/lib/Target/ARM/ARMJITInfo.cpp index 3c50caaf6d0..6a2c253ff11 100644 --- a/lib/Target/ARM/ARMJITInfo.cpp +++ b/lib/Target/ARM/ARMJITInfo.cpp @@ -174,8 +174,14 @@ 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(); - intptr_t ResultPtr = (intptr_t)MR->getResultPointer(); + 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(); switch ((ARM::RelocationType)MR->getRelocationType()) { + case ARM::reloc_arm_cp_entry: case ARM::reloc_arm_relative: { // It is necessary to calculate the correct PC relative value. We // subtract the base addr from the target addr to form a byte offset. @@ -195,6 +201,10 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR, *((unsigned*)RelocPos) |= 0xF << 16; break; } + case ARM::reloc_arm_absolute: { + *((unsigned*)RelocPos) += (unsigned)ResultPtr; + break; + } case ARM::reloc_arm_branch: { // It is necessary to calculate the correct value of signed_immed_24 // field. We subtract the base addr from the target addr to form a diff --git a/lib/Target/ARM/ARMJITInfo.h b/lib/Target/ARM/ARMJITInfo.h index 62b83030106..f16e54205a5 100644 --- a/lib/Target/ARM/ARMJITInfo.h +++ b/lib/Target/ARM/ARMJITInfo.h @@ -22,7 +22,11 @@ namespace llvm { class ARMJITInfo : public TargetJITInfo { ARMTargetMachine &TM; - std::map CPIDtoAddressMap; + + // ConstPoolId2AddrMap - A map from constant pool ids to the corresponding + // CONSTPOOL_ENTRY addresses. + std::map ConstPoolId2AddrMap; + public: explicit ARMJITInfo(ARMTargetMachine &tm) : TM(tm) { useGOT = false; } @@ -52,22 +56,22 @@ namespace llvm { /// pool address resolution is handled by the target. virtual bool hasCustomConstantPool() const { return true; } - /// getCustomConstantPoolEntryAddress - The ARM target puts all constant + /// getConstantPoolEntryAddr - The ARM target puts all constant /// pool entries into constant islands. Resolve the constant pool index /// into the address where the constant is stored. - virtual intptr_t getCustomConstantPoolEntryAddress(unsigned CPID) const - { - std::map::const_iterator elem; - elem = CPIDtoAddressMap.find(CPID); - assert (elem != CPIDtoAddressMap.end()); - return elem->second; - } + virtual intptr_t getConstantPoolEntryAddr(unsigned CPID) const { + std::map::const_iterator I + = ConstPoolId2AddrMap.find(CPID); + assert(I != ConstPoolId2AddrMap.end() && "Missing constpool_entry?"); + return I->second; + } - /// mapCPIDtoAddress - Map a Constant Pool Index (CPID) to the address + /// addConstantPoolEntryAddr - Map a Constant Pool Index (CPID) to the address /// where its associated value is stored. When relocations are processed, /// this value will be used to resolve references to the constant. - void mapCPIDtoAddress(unsigned CPID, intptr_t address) - { CPIDtoAddressMap[CPID] = address; } + void addConstantPoolEntryAddr(unsigned CPID, intptr_t Addr) { + ConstPoolId2AddrMap[CPID] = Addr; + } }; } diff --git a/lib/Target/ARM/ARMRelocations.h b/lib/Target/ARM/ARMRelocations.h index 6963980bc2e..93101a61797 100644 --- a/lib/Target/ARM/ARMRelocations.h +++ b/lib/Target/ARM/ARMRelocations.h @@ -19,8 +19,19 @@ namespace llvm { namespace ARM { enum RelocationType { + // reloc_arm_absolute - Absolute relocation, just add the relocated value + // to the value already in memory. + reloc_arm_absolute, + + // reloc_arm_relative - PC relative relocation, add the relocated value to + // the value already in memory, after we adjust it for where the PC is. reloc_arm_relative, + // reloc_arm_cp_entry - PC relative relocation for constpool_entry's whose + // addresses are kept locally in a map. + reloc_arm_cp_entry, + + // reloc_arm_branch - Branch address relocation. reloc_arm_branch }; }