Get PIC jump table working.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58869 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng
2008-11-07 22:30:53 +00:00
parent 366cf29ca5
commit 437c1738ef
2 changed files with 54 additions and 51 deletions

View File

@@ -96,6 +96,7 @@ namespace {
const TargetInstrDesc &TID) const; const TargetInstrDesc &TID) const;
void emitDataProcessingInstruction(const MachineInstr &MI, void emitDataProcessingInstruction(const MachineInstr &MI,
unsigned ImplicitRd = 0,
unsigned ImplicitRn = 0); unsigned ImplicitRn = 0);
void emitLoadStoreInstruction(const MachineInstr &MI, void emitLoadStoreInstruction(const MachineInstr &MI,
@@ -115,7 +116,7 @@ namespace {
void emitBranchInstruction(const MachineInstr &MI); void emitBranchInstruction(const MachineInstr &MI);
void emitInlineJumpTable(unsigned JTIndex, intptr_t JTBase); void emitInlineJumpTable(unsigned JTIndex);
void emitMiscBranchInstruction(const MachineInstr &MI); void emitMiscBranchInstruction(const MachineInstr &MI);
@@ -137,16 +138,14 @@ namespace {
unsigned getShiftOp(unsigned Imm) const ; unsigned getShiftOp(unsigned Imm) const ;
/// Routines that handle operands which add machine relocations which are /// Routines that handle operands which add machine relocations which are
/// fixed up by the JIT fixup stage. /// fixed up by the relocation stage.
void emitGlobalAddress(GlobalValue *GV, unsigned Reloc, void emitGlobalAddress(GlobalValue *GV, unsigned Reloc,
bool NeedStub); bool NeedStub, unsigned CPIdx = 0);
void emitExternalSymbolAddress(const char *ES, unsigned Reloc); void emitExternalSymbolAddress(const char *ES, unsigned Reloc);
void emitConstPoolAddress(unsigned CPI, unsigned Reloc, void emitConstPoolAddress(unsigned CPI, unsigned Reloc);
int Disp = 0, unsigned PCAdj = 0 ); void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc);
void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc, void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc,
unsigned PCAdj = 0); intptr_t JTBase = 0);
void emitGlobalConstant(const Constant *CV);
void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc);
}; };
char ARMCodeEmitter::ID = 0; char ARMCodeEmitter::ID = 0;
} }
@@ -227,9 +226,10 @@ unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI,
/// emitGlobalAddress - Emit the specified address to the code stream. /// emitGlobalAddress - Emit the specified address to the code stream.
/// ///
void ARMCodeEmitter::emitGlobalAddress(GlobalValue *GV, void ARMCodeEmitter::emitGlobalAddress(GlobalValue *GV,
unsigned Reloc, bool NeedStub) { unsigned Reloc, bool NeedStub,
unsigned CPIdx) {
MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(),
Reloc, GV, 0, NeedStub)); Reloc, GV, CPIdx, NeedStub));
} }
/// emitExternalSymbolAddress - Arrange for the address of an external symbol to /// emitExternalSymbolAddress - Arrange for the address of an external symbol to
@@ -243,28 +243,25 @@ void ARMCodeEmitter::emitExternalSymbolAddress(const char *ES, unsigned Reloc) {
/// emitConstPoolAddress - Arrange for the address of an constant pool /// emitConstPoolAddress - Arrange for the address of an constant pool
/// to be emitted to the current location in the function, and allow it to be PC /// to be emitted to the current location in the function, and allow it to be PC
/// relative. /// relative.
void ARMCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc, void ARMCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc) {
int Disp /* = 0 */,
unsigned PCAdj /* = 0 */) {
// Tell JIT emitter we'll resolve the address. // Tell JIT emitter we'll resolve the address.
MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
Reloc, CPI, PCAdj, true)); Reloc, CPI, 0, true));
} }
/// emitJumpTableAddress - Arrange for the address of a jump table to /// emitJumpTableAddress - Arrange for the address of a jump table to
/// be emitted to the current location in the function, and allow it to be PC /// be emitted to the current location in the function, and allow it to be PC
/// relative. /// relative.
void ARMCodeEmitter::emitJumpTableAddress(unsigned JTIndex, unsigned Reloc, void ARMCodeEmitter::emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) {
unsigned PCAdj /* = 0 */) {
MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
Reloc, JTIndex, PCAdj, true)); Reloc, JTIndex, 0, true));
} }
/// emitMachineBasicBlock - Emit the specified address basic block. /// emitMachineBasicBlock - Emit the specified address basic block.
void ARMCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB, void ARMCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB,
unsigned Reloc) { unsigned Reloc, intptr_t JTBase) {
MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(),
Reloc, BB)); Reloc, BB, JTBase));
} }
void ARMCodeEmitter::emitWordLE(unsigned Binary) { void ARMCodeEmitter::emitWordLE(unsigned Binary) {
@@ -321,8 +318,8 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
} }
void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) { void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) {
unsigned CPI = MI.getOperand(0).getImm(); unsigned CPI = MI.getOperand(0).getImm(); // CP instruction index.
unsigned CPIndex = MI.getOperand(1).getIndex(); unsigned CPIndex = MI.getOperand(1).getIndex(); // Actual cp entry index.
const MachineConstantPoolEntry &MCPE = (*MCPEs)[CPIndex]; const MachineConstantPoolEntry &MCPE = (*MCPEs)[CPIndex];
// Remember the CONSTPOOL_ENTRY address for later relocation. // Remember the CONSTPOOL_ENTRY address for later relocation.
@@ -335,14 +332,12 @@ void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) {
static_cast<ARMConstantPoolValue*>(MCPE.Val.MachineCPVal); static_cast<ARMConstantPoolValue*>(MCPE.Val.MachineCPVal);
DOUT << " ** ARM constant pool #" << CPI << " @ " DOUT << " ** ARM constant pool #" << CPI << " @ "
<< (void*)MCE.getCurrentPCValue() << " " << *ACPV << "\n"; << (void*)MCE.getCurrentPCValue() << " " << *ACPV << '\n';
GlobalValue *GV = ACPV->getGV(); GlobalValue *GV = ACPV->getGV();
if (GV) { if (GV) {
assert(!ACPV->isStub() && "Don't know how to deal this yet!"); assert(!ACPV->isStub() && "Don't know how to deal this yet!");
MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), emitGlobalAddress(GV, ARM::reloc_arm_machine_cp_entry, false, CPIndex);
ARM::reloc_arm_machine_cp_entry,
GV, CPIndex, false));
} else { } else {
assert(!ACPV->isNonLazyPointer() && "Don't know how to deal this yet!"); assert(!ACPV->isNonLazyPointer() && "Don't know how to deal this yet!");
emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute); emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute);
@@ -352,7 +347,7 @@ void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) {
Constant *CV = MCPE.Val.ConstVal; Constant *CV = MCPE.Val.ConstVal;
DOUT << " ** Constant pool #" << CPI << " @ " DOUT << " ** Constant pool #" << CPI << " @ "
<< (void*)MCE.getCurrentPCValue() << " " << *CV << "\n"; << (void*)MCE.getCurrentPCValue() << " " << *CV << '\n';
if (GlobalValue *GV = dyn_cast<GlobalValue>(CV)) { if (GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
emitGlobalAddress(GV, ARM::reloc_arm_absolute, false); emitGlobalAddress(GV, ARM::reloc_arm_absolute, false);
@@ -454,7 +449,7 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) {
// Remember of the address of the PC label for relocation later. // Remember of the address of the PC label for relocation later.
addPCLabel(MI.getOperand(2).getImm()); addPCLabel(MI.getOperand(2).getImm());
// PICADD is just an add instruction that implicitly read pc. // PICADD is just an add instruction that implicitly read pc.
emitDataProcessingInstruction(MI, ARM::PC); emitDataProcessingInstruction(MI, 0, ARM::PC);
break; break;
} }
case ARM::PICLDR: case ARM::PICLDR:
@@ -568,6 +563,7 @@ unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI,
} }
void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI,
unsigned ImplicitRd,
unsigned ImplicitRn) { unsigned ImplicitRn) {
const TargetInstrDesc &TID = MI.getDesc(); const TargetInstrDesc &TID = MI.getDesc();
@@ -583,10 +579,12 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI,
// Encode register def if there is one. // Encode register def if there is one.
unsigned NumDefs = TID.getNumDefs(); unsigned NumDefs = TID.getNumDefs();
unsigned OpIdx = 0; unsigned OpIdx = 0;
if (NumDefs) { if (NumDefs)
Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRdShift; Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift;
++OpIdx; else if (ImplicitRd)
} // Special handling for implicit use (e.g. PC).
Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRd)
<< ARMII::RegRdShift);
// If this is a two-address operand, skip it. e.g. MOVCCr operand 1. // If this is a two-address operand, skip it. e.g. MOVCCr operand 1.
if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
@@ -904,17 +902,18 @@ void ARMCodeEmitter::emitBranchInstruction(const MachineInstr &MI) {
emitWordLE(Binary); emitWordLE(Binary);
} }
void ARMCodeEmitter::emitInlineJumpTable(unsigned JTIndex, intptr_t JTBase) { void ARMCodeEmitter::emitInlineJumpTable(unsigned JTIndex) {
// Remember the base address of the inline jump table. // Remember the base address of the inline jump table.
JTI->addJumpTableBaseAddr(JTIndex, MCE.getCurrentPCValue()); intptr_t JTBase = MCE.getCurrentPCValue();
JTI->addJumpTableBaseAddr(JTIndex, JTBase);
DOUT << " ** Jump Table #" << JTIndex << " @ " << (void*)JTBase << '\n';
// Now emit the jump table entries. // Now emit the jump table entries.
const std::vector<MachineBasicBlock*> &MBBs = (*MJTEs)[JTIndex].MBBs; const std::vector<MachineBasicBlock*> &MBBs = (*MJTEs)[JTIndex].MBBs;
for (unsigned i = 0, e = MBBs.size(); i != e; ++i) { for (unsigned i = 0, e = MBBs.size(); i != e; ++i) {
if (IsPIC) if (IsPIC)
// DestBB address - JT base. // DestBB address - JT base.
MCE.addRelocation(MachineRelocation::getBB(JTBase, ARM::reloc_arm_pic_jt, emitMachineBasicBlock(MBBs[i], ARM::reloc_arm_pic_jt, JTBase);
MBBs[i]));
else else
// Absolute DestBB address. // Absolute DestBB address.
emitMachineBasicBlock(MBBs[i], ARM::reloc_arm_absolute); emitMachineBasicBlock(MBBs[i], ARM::reloc_arm_absolute);
@@ -924,17 +923,23 @@ void ARMCodeEmitter::emitInlineJumpTable(unsigned JTIndex, intptr_t JTBase) {
void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) { void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) {
const TargetInstrDesc &TID = MI.getDesc(); const TargetInstrDesc &TID = MI.getDesc();
if (TID.Opcode == ARM::BX ||
TID.Opcode == ARM::BR_JTr ||
TID.Opcode == ARM::BR_JTadd)
abort(); // FIXME
if (TID.Opcode == ARM::BR_JTm) { // Handle jump tables.
if (TID.Opcode == ARM::BR_JTr || TID.Opcode == ARM::BR_JTadd) {
// First emit a ldr pc, [] instruction.
emitDataProcessingInstruction(MI, ARM::PC);
// Then emit the inline jump table.
unsigned JTIndex = (TID.Opcode == ARM::BR_JTr)
? MI.getOperand(1).getIndex() : MI.getOperand(2).getIndex();
emitInlineJumpTable(JTIndex);
return;
} else if (TID.Opcode == ARM::BR_JTm) {
// First emit a ldr pc, [] instruction. // First emit a ldr pc, [] instruction.
emitLoadStoreInstruction(MI, ARM::PC); emitLoadStoreInstruction(MI, ARM::PC);
// Then emit the inline jump table. // Then emit the inline jump table.
emitInlineJumpTable(MI.getOperand(3).getIndex(), MCE.getCurrentPCOffset()); emitInlineJumpTable(MI.getOperand(3).getIndex());
return; return;
} }

View File

@@ -170,9 +170,14 @@ void *ARMJITInfo::emitFunctionStub(const Function* F, void *Fn,
intptr_t ARMJITInfo::resolveRelocDestAddr(MachineRelocation *MR) const { intptr_t ARMJITInfo::resolveRelocDestAddr(MachineRelocation *MR) const {
ARM::RelocationType RT = (ARM::RelocationType)MR->getRelocationType(); ARM::RelocationType RT = (ARM::RelocationType)MR->getRelocationType();
if (RT == ARM::reloc_arm_jt_base) if (RT == ARM::reloc_arm_pic_jt)
// Destination address - jump table base.
return (intptr_t)(MR->getResultPointer()) - MR->getConstantVal();
else if (RT == ARM::reloc_arm_jt_base)
// Jump table base address.
return getJumpTableBaseAddr(MR->getJumpTableIndex()); return getJumpTableBaseAddr(MR->getJumpTableIndex());
else if (RT == ARM::reloc_arm_cp_entry) else if (RT == ARM::reloc_arm_cp_entry)
// Constant pool entry address.
return getConstantPoolEntryAddr(MR->getConstantPoolIndex()); return getConstantPoolEntryAddr(MR->getConstantPoolIndex());
else if (RT == ARM::reloc_arm_machine_cp_entry) { else if (RT == ARM::reloc_arm_machine_cp_entry) {
const MachineConstantPoolEntry &MCPE = (*MCPEs)[MR->getConstantVal()]; const MachineConstantPoolEntry &MCPE = (*MCPEs)[MR->getConstantVal()];
@@ -196,8 +201,6 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR,
unsigned NumRelocs, unsigned char* GOTBase) { unsigned NumRelocs, unsigned char* GOTBase) {
for (unsigned i = 0; i != NumRelocs; ++i, ++MR) { for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
void *RelocPos = (char*)Function + MR->getMachineCodeOffset(); void *RelocPos = (char*)Function + MR->getMachineCodeOffset();
// If this is a constpool relocation, get the address of the
// constpool_entry instruction.
intptr_t ResultPtr = resolveRelocDestAddr(MR); intptr_t ResultPtr = resolveRelocDestAddr(MR);
switch ((ARM::RelocationType)MR->getRelocationType()) { switch ((ARM::RelocationType)MR->getRelocationType()) {
case ARM::reloc_arm_cp_entry: case ARM::reloc_arm_cp_entry:
@@ -220,6 +223,7 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR,
*((unsigned*)RelocPos) |= 0xF << 16; *((unsigned*)RelocPos) |= 0xF << 16;
break; break;
} }
case ARM::reloc_arm_pic_jt:
case ARM::reloc_arm_machine_cp_entry: case ARM::reloc_arm_machine_cp_entry:
case ARM::reloc_arm_absolute: { case ARM::reloc_arm_absolute: {
// These addresses have already been resolved. // These addresses have already been resolved.
@@ -244,12 +248,6 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR,
*((unsigned*)RelocPos) |= ResultPtr; *((unsigned*)RelocPos) |= ResultPtr;
break; break;
} }
case ARM::reloc_arm_pic_jt: {
// PIC JT entry is destination - JT base.
ResultPtr = ResultPtr - (intptr_t)RelocPos;
*((unsigned*)RelocPos) |= ResultPtr;
break;
}
} }
} }
} }