aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/ARM/ARMCodeEmitter.cpp
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2008-11-07 09:06:08 +0000
committerEvan Cheng <evan.cheng@apple.com>2008-11-07 09:06:08 +0000
commit0f63ae111d5a509911fc61246c1acc62f8c58f18 (patch)
tree97057d1e9ba1b772dde79b066801707d949da016 /lib/Target/ARM/ARMCodeEmitter.cpp
parent68e5fc36910ad653796741fd6b9ca036c975f1b2 (diff)
downloadexternal_llvm-0f63ae111d5a509911fc61246c1acc62f8c58f18.zip
external_llvm-0f63ae111d5a509911fc61246c1acc62f8c58f18.tar.gz
external_llvm-0f63ae111d5a509911fc61246c1acc62f8c58f18.tar.bz2
Jump table JIT support. Work in progress.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58836 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/ARMCodeEmitter.cpp')
-rw-r--r--lib/Target/ARM/ARMCodeEmitter.cpp125
1 files changed, 102 insertions, 23 deletions
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index f786df9..0267276 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -28,10 +28,14 @@
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
+#ifndef NDEBUG
+#include <iomanip>
+#endif
using namespace llvm;
STATISTIC(NumEmitted, "Number of machine instructions emitted");
@@ -44,16 +48,20 @@ namespace {
TargetMachine &TM;
MachineCodeEmitter &MCE;
const std::vector<MachineConstantPoolEntry> *MCPEs;
-
+ const std::vector<MachineJumpTableEntry> *MJTEs;
+ bool IsPIC;
+
public:
static char ID;
explicit ARMCodeEmitter(TargetMachine &tm, MachineCodeEmitter &mce)
: MachineFunctionPass(&ID), JTI(0), II(0), TD(0), TM(tm),
- MCE(mce), MCPEs(0) {}
+ MCE(mce), MCPEs(0), MJTEs(0),
+ IsPIC(TM.getRelocationModel() == Reloc::PIC_) {}
ARMCodeEmitter(TargetMachine &tm, MachineCodeEmitter &mce,
const ARMInstrInfo &ii, const TargetData &td)
: MachineFunctionPass(&ID), JTI(0), II(&ii), TD(&td), TM(tm),
- MCE(mce), MCPEs(0) {}
+ MCE(mce), MCPEs(0), MJTEs(0),
+ IsPIC(TM.getRelocationModel() == Reloc::PIC_) {}
bool runOnMachineFunction(MachineFunction &MF);
@@ -71,6 +79,8 @@ namespace {
void emitMOVi2piecesInstruction(const MachineInstr &MI);
+ void emitLEApcrelJTInstruction(const MachineInstr &MI);
+
void addPCLabel(unsigned LabelID);
void emitPseudoInstruction(const MachineInstr &MI);
@@ -89,6 +99,7 @@ namespace {
unsigned ImplicitRn = 0);
void emitLoadStoreInstruction(const MachineInstr &MI,
+ unsigned ImplicitRd = 0,
unsigned ImplicitRn = 0);
void emitMiscLoadStoreInstruction(const MachineInstr &MI,
@@ -104,6 +115,8 @@ namespace {
void emitBranchInstruction(const MachineInstr &MI);
+ void emitInlineJumpTable(unsigned JTIndex, intptr_t JTBase);
+
void emitMiscBranchInstruction(const MachineInstr &MI);
/// getBinaryCodeForInstr - This function, generated by the
@@ -133,7 +146,7 @@ namespace {
void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc,
unsigned PCAdj = 0);
void emitGlobalConstant(const Constant *CV);
- void emitMachineBasicBlock(MachineBasicBlock *BB);
+ void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc);
};
char ARMCodeEmitter::ID = 0;
}
@@ -153,7 +166,9 @@ bool ARMCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
TD = ((ARMTargetMachine&)MF.getTarget()).getTargetData();
JTI = ((ARMTargetMachine&)MF.getTarget()).getJITInfo();
MCPEs = &MF.getConstantPool()->getConstants();
- JTI->Initialize(MCPEs);
+ MJTEs = &MF.getJumpTableInfo()->getJumpTables();
+ IsPIC = TM.getRelocationModel() == Reloc::PIC_;
+ JTI->Initialize(MF);
do {
DOUT << "JITTing function '" << MF.getFunction()->getName() << "'\n";
@@ -201,7 +216,7 @@ unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI,
else if (MO.isJTI())
emitJumpTableAddress(MO.getIndex(), ARM::reloc_arm_relative);
else if (MO.isMBB())
- emitMachineBasicBlock(MO.getMBB());
+ emitMachineBasicBlock(MO.getMBB(), ARM::reloc_arm_branch);
else {
cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
abort();
@@ -242,17 +257,21 @@ void ARMCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc,
void ARMCodeEmitter::emitJumpTableAddress(unsigned JTIndex, unsigned Reloc,
unsigned PCAdj /* = 0 */) {
MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
- Reloc, JTIndex, PCAdj));
+ Reloc, JTIndex, PCAdj, true));
}
/// emitMachineBasicBlock - Emit the specified address basic block.
-void ARMCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB) {
+void ARMCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB,
+ unsigned Reloc) {
MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(),
- ARM::reloc_arm_branch, BB));
+ Reloc, BB));
}
void ARMCodeEmitter::emitWordLE(unsigned Binary) {
- DOUT << " " << (void*)Binary << "\n";
+#ifndef NDEBUG
+ DOUT << " 0x" << std::hex << std::setw(8) << std::setfill('0')
+ << Binary << std::dec << "\n";
+#endif
MCE.emitWordLE(Binary);
}
@@ -389,6 +408,34 @@ void ARMCodeEmitter::emitMOVi2piecesInstruction(const MachineInstr &MI) {
emitWordLE(Binary);
}
+void ARMCodeEmitter::emitLEApcrelJTInstruction(const MachineInstr &MI) {
+ // It's basically add r, pc, (LJTI - $+8)
+
+ const TargetInstrDesc &TID = MI.getDesc();
+
+ // Emit the 'add' instruction.
+ unsigned Binary = 0x4 << 21; // add: Insts{24-31} = 0b0100
+
+ // Set the conditional execution predicate
+ Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+
+ // Encode S bit if MI modifies CPSR.
+ Binary |= getAddrModeSBit(MI, TID);
+
+ // Encode Rd.
+ Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift;
+
+ // Encode Rn which is PC.
+ Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::PC) << ARMII::RegRnShift;
+
+ // Encode the displacement.
+ // Set bit I(25) to identify this is the immediate form of <shifter_op>.
+ Binary |= 1 << ARMII::I_BitShift;
+ emitJumpTableAddress(MI.getOperand(1).getIndex(), ARM::reloc_arm_jt_base);
+
+ emitWordLE(Binary);
+}
+
void ARMCodeEmitter::addPCLabel(unsigned LabelID) {
DOUT << " ** LPC" << LabelID << " @ "
<< (void*)MCE.getCurrentPCValue() << '\n';
@@ -417,7 +464,7 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) {
// Remember of the address of the PC label for relocation later.
addPCLabel(MI.getOperand(2).getImm());
// These are just load / store instructions that implicitly read pc.
- emitLoadStoreInstruction(MI, ARM::PC);
+ emitLoadStoreInstruction(MI, 0, ARM::PC);
break;
}
case ARM::PICLDRH:
@@ -434,6 +481,10 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) {
// Two instructions to materialize a constant.
emitMOVi2piecesInstruction(MI);
break;
+ case ARM::LEApcrelJT:
+ // Materialize jumptable address.
+ emitLEApcrelJTInstruction(MI);
+ break;
}
}
@@ -569,7 +620,7 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI,
}
// Encode so_imm.
- // Set bit I(25) to identify this is the immediate form of <shifter_op>
+ // Set bit I(25) to identify this is the immediate form of <shifter_op>.
Binary |= 1 << ARMII::I_BitShift;
Binary |= getMachineSoImmOpValue(MO.getImm());
@@ -577,6 +628,7 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI,
}
void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
+ unsigned ImplicitRd,
unsigned ImplicitRn) {
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
@@ -585,18 +637,21 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
// Set first operand
- Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift;
+ unsigned OpIdx = 0;
+ if (ImplicitRd)
+ // Special handling for implicit use (e.g. PC).
+ Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRd)
+ << ARMII::RegRdShift);
+ else
+ Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift;
// Set second operand
- unsigned OpIdx = 1;
if (ImplicitRn)
// Special handling for implicit use (e.g. PC).
Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRn)
<< ARMII::RegRnShift);
- else {
- Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRnShift;
- ++OpIdx;
- }
+ else
+ Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift;
const MachineOperand &MO2 = MI.getOperand(OpIdx);
unsigned AM2Opc = (ImplicitRn == ARM::PC)
@@ -646,10 +701,8 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI,
// Special handling for implicit use (e.g. PC).
Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRn)
<< ARMII::RegRnShift);
- else {
- Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRnShift;
- ++OpIdx;
- }
+ else
+ Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift;
const MachineOperand &MO2 = MI.getOperand(OpIdx);
unsigned AM3Opc = (ImplicitRn == ARM::PC)
@@ -851,14 +904,40 @@ void ARMCodeEmitter::emitBranchInstruction(const MachineInstr &MI) {
emitWordLE(Binary);
}
+void ARMCodeEmitter::emitInlineJumpTable(unsigned JTIndex, intptr_t JTBase) {
+ // Remember the base address of the inline jump table.
+ JTI->addJumpTableBaseAddr(JTIndex, MCE.getCurrentPCValue());
+
+ // Now emit the jump table entries.
+ const std::vector<MachineBasicBlock*> &MBBs = (*MJTEs)[JTIndex].MBBs;
+ for (unsigned i = 0, e = MBBs.size(); i != e; ++i) {
+ if (IsPIC)
+ // DestBB address - JT base.
+ MCE.addRelocation(MachineRelocation::getBB(JTBase, ARM::reloc_arm_pic_jt,
+ MBBs[i]));
+ else
+ // Absolute DestBB address.
+ emitMachineBasicBlock(MBBs[i], ARM::reloc_arm_absolute);
+ emitWordLE(0);
+ }
+}
+
void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) {
const TargetInstrDesc &TID = MI.getDesc();
if (TID.Opcode == ARM::BX ||
TID.Opcode == ARM::BR_JTr ||
- TID.Opcode == ARM::BR_JTm ||
TID.Opcode == ARM::BR_JTadd)
abort(); // FIXME
+ if (TID.Opcode == ARM::BR_JTm) {
+ // First emit a ldr pc, [] instruction.
+ emitLoadStoreInstruction(MI, ARM::PC);
+
+ // Then emit the inline jump table.
+ emitInlineJumpTable(MI.getOperand(3).getIndex(), MCE.getCurrentPCOffset());
+ return;
+ }
+
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);