mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-19 13:38:56 +00:00
Jump table JIT support. Work in progress.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58836 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
47c01a0099
commit
4df60f5491
@ -28,10 +28,14 @@
|
|||||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||||
#include "llvm/CodeGen/MachineInstr.h"
|
#include "llvm/CodeGen/MachineInstr.h"
|
||||||
|
#include "llvm/CodeGen/MachineJumpTableInfo.h"
|
||||||
#include "llvm/CodeGen/Passes.h"
|
#include "llvm/CodeGen/Passes.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#include <iomanip>
|
||||||
|
#endif
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
STATISTIC(NumEmitted, "Number of machine instructions emitted");
|
STATISTIC(NumEmitted, "Number of machine instructions emitted");
|
||||||
@ -44,16 +48,20 @@ namespace {
|
|||||||
TargetMachine &TM;
|
TargetMachine &TM;
|
||||||
MachineCodeEmitter &MCE;
|
MachineCodeEmitter &MCE;
|
||||||
const std::vector<MachineConstantPoolEntry> *MCPEs;
|
const std::vector<MachineConstantPoolEntry> *MCPEs;
|
||||||
|
const std::vector<MachineJumpTableEntry> *MJTEs;
|
||||||
|
bool IsPIC;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static char ID;
|
static char ID;
|
||||||
explicit ARMCodeEmitter(TargetMachine &tm, MachineCodeEmitter &mce)
|
explicit ARMCodeEmitter(TargetMachine &tm, MachineCodeEmitter &mce)
|
||||||
: MachineFunctionPass(&ID), JTI(0), II(0), TD(0), TM(tm),
|
: 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,
|
ARMCodeEmitter(TargetMachine &tm, MachineCodeEmitter &mce,
|
||||||
const ARMInstrInfo &ii, const TargetData &td)
|
const ARMInstrInfo &ii, const TargetData &td)
|
||||||
: MachineFunctionPass(&ID), JTI(0), II(&ii), TD(&td), TM(tm),
|
: 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);
|
bool runOnMachineFunction(MachineFunction &MF);
|
||||||
|
|
||||||
@ -71,6 +79,8 @@ namespace {
|
|||||||
|
|
||||||
void emitMOVi2piecesInstruction(const MachineInstr &MI);
|
void emitMOVi2piecesInstruction(const MachineInstr &MI);
|
||||||
|
|
||||||
|
void emitLEApcrelJTInstruction(const MachineInstr &MI);
|
||||||
|
|
||||||
void addPCLabel(unsigned LabelID);
|
void addPCLabel(unsigned LabelID);
|
||||||
|
|
||||||
void emitPseudoInstruction(const MachineInstr &MI);
|
void emitPseudoInstruction(const MachineInstr &MI);
|
||||||
@ -89,6 +99,7 @@ namespace {
|
|||||||
unsigned ImplicitRn = 0);
|
unsigned ImplicitRn = 0);
|
||||||
|
|
||||||
void emitLoadStoreInstruction(const MachineInstr &MI,
|
void emitLoadStoreInstruction(const MachineInstr &MI,
|
||||||
|
unsigned ImplicitRd = 0,
|
||||||
unsigned ImplicitRn = 0);
|
unsigned ImplicitRn = 0);
|
||||||
|
|
||||||
void emitMiscLoadStoreInstruction(const MachineInstr &MI,
|
void emitMiscLoadStoreInstruction(const MachineInstr &MI,
|
||||||
@ -104,6 +115,8 @@ namespace {
|
|||||||
|
|
||||||
void emitBranchInstruction(const MachineInstr &MI);
|
void emitBranchInstruction(const MachineInstr &MI);
|
||||||
|
|
||||||
|
void emitInlineJumpTable(unsigned JTIndex, intptr_t JTBase);
|
||||||
|
|
||||||
void emitMiscBranchInstruction(const MachineInstr &MI);
|
void emitMiscBranchInstruction(const MachineInstr &MI);
|
||||||
|
|
||||||
/// getBinaryCodeForInstr - This function, generated by the
|
/// getBinaryCodeForInstr - This function, generated by the
|
||||||
@ -133,7 +146,7 @@ namespace {
|
|||||||
void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc,
|
void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc,
|
||||||
unsigned PCAdj = 0);
|
unsigned PCAdj = 0);
|
||||||
void emitGlobalConstant(const Constant *CV);
|
void emitGlobalConstant(const Constant *CV);
|
||||||
void emitMachineBasicBlock(MachineBasicBlock *BB);
|
void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc);
|
||||||
};
|
};
|
||||||
char ARMCodeEmitter::ID = 0;
|
char ARMCodeEmitter::ID = 0;
|
||||||
}
|
}
|
||||||
@ -153,7 +166,9 @@ bool ARMCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
TD = ((ARMTargetMachine&)MF.getTarget()).getTargetData();
|
TD = ((ARMTargetMachine&)MF.getTarget()).getTargetData();
|
||||||
JTI = ((ARMTargetMachine&)MF.getTarget()).getJITInfo();
|
JTI = ((ARMTargetMachine&)MF.getTarget()).getJITInfo();
|
||||||
MCPEs = &MF.getConstantPool()->getConstants();
|
MCPEs = &MF.getConstantPool()->getConstants();
|
||||||
JTI->Initialize(MCPEs);
|
MJTEs = &MF.getJumpTableInfo()->getJumpTables();
|
||||||
|
IsPIC = TM.getRelocationModel() == Reloc::PIC_;
|
||||||
|
JTI->Initialize(MF);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
DOUT << "JITTing function '" << MF.getFunction()->getName() << "'\n";
|
DOUT << "JITTing function '" << MF.getFunction()->getName() << "'\n";
|
||||||
@ -201,7 +216,7 @@ unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI,
|
|||||||
else if (MO.isJTI())
|
else if (MO.isJTI())
|
||||||
emitJumpTableAddress(MO.getIndex(), ARM::reloc_arm_relative);
|
emitJumpTableAddress(MO.getIndex(), ARM::reloc_arm_relative);
|
||||||
else if (MO.isMBB())
|
else if (MO.isMBB())
|
||||||
emitMachineBasicBlock(MO.getMBB());
|
emitMachineBasicBlock(MO.getMBB(), ARM::reloc_arm_branch);
|
||||||
else {
|
else {
|
||||||
cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
|
cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
|
||||||
abort();
|
abort();
|
||||||
@ -242,17 +257,21 @@ void ARMCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc,
|
|||||||
void ARMCodeEmitter::emitJumpTableAddress(unsigned JTIndex, unsigned Reloc,
|
void ARMCodeEmitter::emitJumpTableAddress(unsigned JTIndex, unsigned Reloc,
|
||||||
unsigned PCAdj /* = 0 */) {
|
unsigned PCAdj /* = 0 */) {
|
||||||
MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
|
MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
|
||||||
Reloc, JTIndex, PCAdj));
|
Reloc, JTIndex, PCAdj, 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) {
|
||||||
MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(),
|
MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(),
|
||||||
ARM::reloc_arm_branch, BB));
|
Reloc, BB));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMCodeEmitter::emitWordLE(unsigned Binary) {
|
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);
|
MCE.emitWordLE(Binary);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,6 +408,34 @@ void ARMCodeEmitter::emitMOVi2piecesInstruction(const MachineInstr &MI) {
|
|||||||
emitWordLE(Binary);
|
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) {
|
void ARMCodeEmitter::addPCLabel(unsigned LabelID) {
|
||||||
DOUT << " ** LPC" << LabelID << " @ "
|
DOUT << " ** LPC" << LabelID << " @ "
|
||||||
<< (void*)MCE.getCurrentPCValue() << '\n';
|
<< (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.
|
// Remember of the address of the PC label for relocation later.
|
||||||
addPCLabel(MI.getOperand(2).getImm());
|
addPCLabel(MI.getOperand(2).getImm());
|
||||||
// These are just load / store instructions that implicitly read pc.
|
// These are just load / store instructions that implicitly read pc.
|
||||||
emitLoadStoreInstruction(MI, ARM::PC);
|
emitLoadStoreInstruction(MI, 0, ARM::PC);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ARM::PICLDRH:
|
case ARM::PICLDRH:
|
||||||
@ -434,6 +481,10 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) {
|
|||||||
// Two instructions to materialize a constant.
|
// Two instructions to materialize a constant.
|
||||||
emitMOVi2piecesInstruction(MI);
|
emitMOVi2piecesInstruction(MI);
|
||||||
break;
|
break;
|
||||||
|
case ARM::LEApcrelJT:
|
||||||
|
// Materialize jumptable address.
|
||||||
|
emitLEApcrelJTInstruction(MI);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,7 +620,7 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Encode so_imm.
|
// 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 |= 1 << ARMII::I_BitShift;
|
||||||
Binary |= getMachineSoImmOpValue(MO.getImm());
|
Binary |= getMachineSoImmOpValue(MO.getImm());
|
||||||
|
|
||||||
@ -577,6 +628,7 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
|
void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
|
||||||
|
unsigned ImplicitRd,
|
||||||
unsigned ImplicitRn) {
|
unsigned ImplicitRn) {
|
||||||
// Part of binary is determined by TableGn.
|
// Part of binary is determined by TableGn.
|
||||||
unsigned Binary = getBinaryCodeForInstr(MI);
|
unsigned Binary = getBinaryCodeForInstr(MI);
|
||||||
@ -585,18 +637,21 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
|
|||||||
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
|
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
|
||||||
|
|
||||||
// Set first operand
|
// 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
|
// Set second operand
|
||||||
unsigned OpIdx = 1;
|
|
||||||
if (ImplicitRn)
|
if (ImplicitRn)
|
||||||
// Special handling for implicit use (e.g. PC).
|
// Special handling for implicit use (e.g. PC).
|
||||||
Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRn)
|
Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRn)
|
||||||
<< ARMII::RegRnShift);
|
<< ARMII::RegRnShift);
|
||||||
else {
|
else
|
||||||
Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRnShift;
|
Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift;
|
||||||
++OpIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MachineOperand &MO2 = MI.getOperand(OpIdx);
|
const MachineOperand &MO2 = MI.getOperand(OpIdx);
|
||||||
unsigned AM2Opc = (ImplicitRn == ARM::PC)
|
unsigned AM2Opc = (ImplicitRn == ARM::PC)
|
||||||
@ -646,10 +701,8 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI,
|
|||||||
// Special handling for implicit use (e.g. PC).
|
// Special handling for implicit use (e.g. PC).
|
||||||
Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRn)
|
Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRn)
|
||||||
<< ARMII::RegRnShift);
|
<< ARMII::RegRnShift);
|
||||||
else {
|
else
|
||||||
Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRnShift;
|
Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift;
|
||||||
++OpIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MachineOperand &MO2 = MI.getOperand(OpIdx);
|
const MachineOperand &MO2 = MI.getOperand(OpIdx);
|
||||||
unsigned AM3Opc = (ImplicitRn == ARM::PC)
|
unsigned AM3Opc = (ImplicitRn == ARM::PC)
|
||||||
@ -851,14 +904,40 @@ void ARMCodeEmitter::emitBranchInstruction(const MachineInstr &MI) {
|
|||||||
emitWordLE(Binary);
|
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) {
|
void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) {
|
||||||
const TargetInstrDesc &TID = MI.getDesc();
|
const TargetInstrDesc &TID = MI.getDesc();
|
||||||
if (TID.Opcode == ARM::BX ||
|
if (TID.Opcode == ARM::BX ||
|
||||||
TID.Opcode == ARM::BR_JTr ||
|
TID.Opcode == ARM::BR_JTr ||
|
||||||
TID.Opcode == ARM::BR_JTm ||
|
|
||||||
TID.Opcode == ARM::BR_JTadd)
|
TID.Opcode == ARM::BR_JTadd)
|
||||||
abort(); // FIXME
|
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.
|
// Part of binary is determined by TableGn.
|
||||||
unsigned Binary = getBinaryCodeForInstr(MI);
|
unsigned Binary = getBinaryCodeForInstr(MI);
|
||||||
|
|
||||||
|
@ -151,33 +151,9 @@ class ABXIx2<dag oops, dag iops, string asm, list<dag> pattern>
|
|||||||
"", pattern>;
|
"", pattern>;
|
||||||
|
|
||||||
// BR_JT instructions
|
// BR_JT instructions
|
||||||
// == mov pc
|
class JTI<dag oops, dag iops, string asm, list<dag> pattern>
|
||||||
class JTI<bits<4> opcod, dag oops, dag iops, string asm, list<dag> pattern>
|
|
||||||
: XI<oops, iops, AddrModeNone, SizeSpecial, IndexModeNone, BrMiscFrm,
|
: XI<oops, iops, AddrModeNone, SizeSpecial, IndexModeNone, BrMiscFrm,
|
||||||
asm, "", pattern> {
|
asm, "", pattern>;
|
||||||
let Inst{20} = 0; // S Bit
|
|
||||||
let Inst{24-21} = opcod;
|
|
||||||
let Inst{27-26} = {0,0};
|
|
||||||
}
|
|
||||||
// == add pc
|
|
||||||
class JTI1<bits<4> opcod, dag oops, dag iops, string asm, list<dag> pattern>
|
|
||||||
: XI<oops, iops, AddrMode1, SizeSpecial, IndexModeNone, BrMiscFrm,
|
|
||||||
asm, "", pattern> {
|
|
||||||
let Inst{20} = 0; // S bit
|
|
||||||
let Inst{24-21} = opcod;
|
|
||||||
let Inst{27-26} = {0,0};
|
|
||||||
}
|
|
||||||
// == ldr pc
|
|
||||||
class JTI2<bits<4> opcod, dag oops, dag iops, string asm, list<dag> pattern>
|
|
||||||
: XI<oops, iops, AddrMode2, SizeSpecial, IndexModeNone, BrMiscFrm,
|
|
||||||
asm, "", pattern> {
|
|
||||||
let Inst{20} = 1; // L bit
|
|
||||||
let Inst{21} = 0; // W bit
|
|
||||||
let Inst{22} = 0; // B bit
|
|
||||||
let Inst{24} = 1; // P bit
|
|
||||||
let Inst{27-26} = {0,1};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// addrmode1 instructions
|
// addrmode1 instructions
|
||||||
class AI1<bits<4> opcod, dag oops, dag iops, Format f, string opc,
|
class AI1<bits<4> opcod, dag oops, dag iops, Format f, string opc,
|
||||||
|
@ -572,23 +572,35 @@ let isBranch = 1, isTerminator = 1 in {
|
|||||||
[(br bb:$target)]>;
|
[(br bb:$target)]>;
|
||||||
|
|
||||||
let isNotDuplicable = 1, isIndirectBranch = 1 in {
|
let isNotDuplicable = 1, isIndirectBranch = 1 in {
|
||||||
def BR_JTr : JTI<0b1101, (outs),
|
def BR_JTr : JTI<(outs), (ins GPR:$target, jtblock_operand:$jt, i32imm:$id),
|
||||||
(ins GPR:$target, jtblock_operand:$jt, i32imm:$id),
|
|
||||||
"mov pc, $target \n$jt",
|
"mov pc, $target \n$jt",
|
||||||
[(ARMbrjt GPR:$target, tjumptable:$jt, imm:$id)]>;
|
[(ARMbrjt GPR:$target, tjumptable:$jt, imm:$id)]> {
|
||||||
def BR_JTm : JTI2<0, (outs),
|
let Inst{20} = 0; // S Bit
|
||||||
(ins addrmode2:$target, jtblock_operand:$jt, i32imm:$id),
|
let Inst{24-21} = 0b1101;
|
||||||
"ldr pc, $target \n$jt",
|
let Inst{27-26} = {0,0};
|
||||||
[(ARMbrjt (i32 (load addrmode2:$target)), tjumptable:$jt,
|
|
||||||
imm:$id)]>;
|
|
||||||
def BR_JTadd : JTI1<0b0100, (outs),
|
|
||||||
(ins GPR:$target, GPR:$idx, jtblock_operand:$jt,
|
|
||||||
i32imm:$id),
|
|
||||||
"add pc, $target, $idx \n$jt",
|
|
||||||
[(ARMbrjt (add GPR:$target, GPR:$idx), tjumptable:$jt,
|
|
||||||
imm:$id)]>;
|
|
||||||
}
|
}
|
||||||
|
def BR_JTm : JTI<(outs),
|
||||||
|
(ins addrmode2:$target, jtblock_operand:$jt, i32imm:$id),
|
||||||
|
"ldr pc, $target \n$jt",
|
||||||
|
[(ARMbrjt (i32 (load addrmode2:$target)), tjumptable:$jt,
|
||||||
|
imm:$id)]> {
|
||||||
|
let Inst{20} = 1; // L bit
|
||||||
|
let Inst{21} = 0; // W bit
|
||||||
|
let Inst{22} = 0; // B bit
|
||||||
|
let Inst{24} = 1; // P bit
|
||||||
|
let Inst{27-26} = {0,1};
|
||||||
}
|
}
|
||||||
|
def BR_JTadd : JTI<(outs),
|
||||||
|
(ins GPR:$target, GPR:$idx, jtblock_operand:$jt, i32imm:$id),
|
||||||
|
"add pc, $target, $idx \n$jt",
|
||||||
|
[(ARMbrjt (add GPR:$target, GPR:$idx), tjumptable:$jt,
|
||||||
|
imm:$id)]> {
|
||||||
|
let Inst{20} = 0; // S bit
|
||||||
|
let Inst{24-21} = 0b0100;
|
||||||
|
let Inst{27-26} = {0,0};
|
||||||
|
}
|
||||||
|
} // isNotDuplicable = 1, isIndirectBranch = 1
|
||||||
|
} // isBarrier = 1
|
||||||
|
|
||||||
// FIXME: should be able to write a pattern for ARMBrcond, but can't use
|
// FIXME: should be able to write a pattern for ARMBrcond, but can't use
|
||||||
// a two-value operand where a dag node expects two operands. :(
|
// a two-value operand where a dag node expects two operands. :(
|
||||||
|
@ -168,9 +168,11 @@ void *ARMJITInfo::emitFunctionStub(const Function* F, void *Fn,
|
|||||||
return MCE.finishFunctionStub(F);
|
return MCE.finishFunctionStub(F);
|
||||||
}
|
}
|
||||||
|
|
||||||
intptr_t ARMJITInfo::resolveRelocationAddr(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_cp_entry)
|
if (RT == ARM::reloc_arm_jt_base)
|
||||||
|
return getJumpTableBaseAddr(MR->getJumpTableIndex());
|
||||||
|
else if (RT == ARM::reloc_arm_cp_entry)
|
||||||
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,7 +198,7 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR,
|
|||||||
void *RelocPos = (char*)Function + MR->getMachineCodeOffset();
|
void *RelocPos = (char*)Function + MR->getMachineCodeOffset();
|
||||||
// If this is a constpool relocation, get the address of the
|
// If this is a constpool relocation, get the address of the
|
||||||
// constpool_entry instruction.
|
// constpool_entry instruction.
|
||||||
intptr_t ResultPtr = resolveRelocationAddr(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:
|
||||||
case ARM::reloc_arm_relative: {
|
case ARM::reloc_arm_relative: {
|
||||||
@ -221,7 +223,7 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR,
|
|||||||
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.
|
||||||
*((unsigned*)RelocPos) += (unsigned)ResultPtr;
|
*((unsigned*)RelocPos) |= (unsigned)ResultPtr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ARM::reloc_arm_branch: {
|
case ARM::reloc_arm_branch: {
|
||||||
@ -230,12 +232,24 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR,
|
|||||||
// byte offset, which must be inside the range -33554432 and +33554428.
|
// byte offset, which must be inside the range -33554432 and +33554428.
|
||||||
// Then, we set the signed_immed_24 field of the instruction to bits
|
// Then, we set the signed_immed_24 field of the instruction to bits
|
||||||
// [25:2] of the byte offset. More details ARM-ARM p. A4-11.
|
// [25:2] of the byte offset. More details ARM-ARM p. A4-11.
|
||||||
ResultPtr = ResultPtr-(intptr_t)RelocPos-8;
|
ResultPtr = ResultPtr - (intptr_t)RelocPos - 8;
|
||||||
ResultPtr = (ResultPtr & 0x03FFFFFC) >> 2;
|
ResultPtr = (ResultPtr & 0x03FFFFFC) >> 2;
|
||||||
assert(ResultPtr >= -33554432 && ResultPtr <= 33554428);
|
assert(ResultPtr >= -33554432 && ResultPtr <= 33554428);
|
||||||
*((unsigned*)RelocPos) |= ResultPtr;
|
*((unsigned*)RelocPos) |= ResultPtr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ARM::reloc_arm_jt_base: {
|
||||||
|
// JT base - (instruction addr + 8)
|
||||||
|
ResultPtr = ResultPtr - (intptr_t)RelocPos - 8;
|
||||||
|
*((unsigned*)RelocPos) |= ResultPtr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ARM::reloc_arm_pic_jt: {
|
||||||
|
// PIC JT entry is destination - JT base.
|
||||||
|
ResultPtr = ResultPtr - (intptr_t)RelocPos;
|
||||||
|
*((unsigned*)RelocPos) |= ResultPtr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
#include "llvm/Target/TargetJITInfo.h"
|
#include "llvm/Target/TargetJITInfo.h"
|
||||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||||
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
|
#include "llvm/CodeGen/MachineJumpTableInfo.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
|
||||||
@ -31,7 +33,11 @@ namespace llvm {
|
|||||||
|
|
||||||
// ConstPoolId2AddrMap - A map from constant pool ids to the corresponding
|
// ConstPoolId2AddrMap - A map from constant pool ids to the corresponding
|
||||||
// CONSTPOOL_ENTRY addresses.
|
// CONSTPOOL_ENTRY addresses.
|
||||||
SmallVector<intptr_t, 32> ConstPoolId2AddrMap;
|
SmallVector<intptr_t, 16> ConstPoolId2AddrMap;
|
||||||
|
|
||||||
|
// JumpTableId2AddrMap - A map from inline jumptable ids to the
|
||||||
|
// corresponding inline jump table bases.
|
||||||
|
SmallVector<intptr_t, 16> JumpTableId2AddrMap;
|
||||||
|
|
||||||
// PCLabelMap - A map from PC labels to addresses.
|
// PCLabelMap - A map from PC labels to addresses.
|
||||||
DenseMap<unsigned, intptr_t> PCLabelMap;
|
DenseMap<unsigned, intptr_t> PCLabelMap;
|
||||||
@ -65,6 +71,10 @@ namespace llvm {
|
|||||||
/// pool address resolution is handled by the target.
|
/// pool address resolution is handled by the target.
|
||||||
virtual bool hasCustomConstantPool() const { return true; }
|
virtual bool hasCustomConstantPool() const { return true; }
|
||||||
|
|
||||||
|
/// hasCustomJumpTables - Allows a target to specify that jumptables
|
||||||
|
/// are emitted by the target.
|
||||||
|
virtual bool hasCustomJumpTables() const { return true; }
|
||||||
|
|
||||||
/// allocateSeparateGVMemory - If true, globals should be placed in
|
/// allocateSeparateGVMemory - If true, globals should be placed in
|
||||||
/// separately allocated heap memory rather than in the same
|
/// separately allocated heap memory rather than in the same
|
||||||
/// code memory allocated by MachineCodeEmitter.
|
/// code memory allocated by MachineCodeEmitter.
|
||||||
@ -78,20 +88,21 @@ namespace llvm {
|
|||||||
|
|
||||||
/// Initialize - Initialize internal stage. Get the list of constant pool
|
/// Initialize - Initialize internal stage. Get the list of constant pool
|
||||||
/// Resize constant pool ids to CONSTPOOL_ENTRY addresses map.
|
/// Resize constant pool ids to CONSTPOOL_ENTRY addresses map.
|
||||||
void Initialize(const std::vector<MachineConstantPoolEntry> *mcpes) {
|
void Initialize(const MachineFunction &MF) {
|
||||||
MCPEs = mcpes;
|
MCPEs = &MF.getConstantPool()->getConstants();
|
||||||
ConstPoolId2AddrMap.resize(MCPEs->size());
|
ConstPoolId2AddrMap.resize(MCPEs->size());
|
||||||
|
JumpTableId2AddrMap.resize(MF.getJumpTableInfo()->getJumpTables().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getConstantPoolEntryAddr - The ARM target puts all constant
|
/// getConstantPoolEntryAddr - The ARM target puts all constant
|
||||||
/// pool entries into constant islands. Resolve the constant pool index
|
/// pool entries into constant islands. This returns the address of the
|
||||||
/// into the address where the constant is stored.
|
/// constant pool entry of the specified index.
|
||||||
intptr_t getConstantPoolEntryAddr(unsigned CPI) const {
|
intptr_t getConstantPoolEntryAddr(unsigned CPI) const {
|
||||||
assert(CPI < ConstPoolId2AddrMap.size());
|
assert(CPI < ConstPoolId2AddrMap.size());
|
||||||
return ConstPoolId2AddrMap[CPI];
|
return ConstPoolId2AddrMap[CPI];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// addConstantPoolEntryAddr - Map a Constant Pool Index (CPI) to the address
|
/// addConstantPoolEntryAddr - Map a Constant Pool Index to the address
|
||||||
/// where its associated value is stored. When relocations are processed,
|
/// where its associated value is stored. When relocations are processed,
|
||||||
/// this value will be used to resolve references to the constant.
|
/// this value will be used to resolve references to the constant.
|
||||||
void addConstantPoolEntryAddr(unsigned CPI, intptr_t Addr) {
|
void addConstantPoolEntryAddr(unsigned CPI, intptr_t Addr) {
|
||||||
@ -99,6 +110,23 @@ namespace llvm {
|
|||||||
ConstPoolId2AddrMap[CPI] = Addr;
|
ConstPoolId2AddrMap[CPI] = Addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getJumpTableBaseAddr - The ARM target inline all jump tables within
|
||||||
|
/// text section of the function. This returns the address of the base of
|
||||||
|
/// the jump table of the specified index.
|
||||||
|
intptr_t getJumpTableBaseAddr(unsigned JTI) const {
|
||||||
|
assert(JTI < JumpTableId2AddrMap.size());
|
||||||
|
return JumpTableId2AddrMap[JTI];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// addJumpTableBaseAddr - Map a jump table index to the address where
|
||||||
|
/// the corresponding inline jump table is emitted. When relocations are
|
||||||
|
/// processed, this value will be used to resolve references to the
|
||||||
|
/// jump table.
|
||||||
|
void addJumpTableBaseAddr(unsigned JTI, intptr_t Addr) {
|
||||||
|
assert(JTI < JumpTableId2AddrMap.size());
|
||||||
|
JumpTableId2AddrMap[JTI] = Addr;
|
||||||
|
}
|
||||||
|
|
||||||
/// getPCLabelAddr - Retrieve the address of the PC label of the specified id.
|
/// getPCLabelAddr - Retrieve the address of the PC label of the specified id.
|
||||||
intptr_t getPCLabelAddr(unsigned Id) const {
|
intptr_t getPCLabelAddr(unsigned Id) const {
|
||||||
DenseMap<unsigned, intptr_t>::const_iterator I = PCLabelMap.find(Id);
|
DenseMap<unsigned, intptr_t>::const_iterator I = PCLabelMap.find(Id);
|
||||||
@ -112,10 +140,10 @@ namespace llvm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// resolveRelocationAddr - Resolve the resulting address of the relocation
|
/// resolveRelocDestAddr - Resolve the resulting address of the relocation
|
||||||
/// if it's not already solved. Constantpool entries must be resolved by
|
/// if it's not already solved. Constantpool entries must be resolved by
|
||||||
/// ARM target.
|
/// ARM target.
|
||||||
intptr_t resolveRelocationAddr(MachineRelocation *MR) const;
|
intptr_t resolveRelocDestAddr(MachineRelocation *MR) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,13 @@ namespace llvm {
|
|||||||
// entry.
|
// entry.
|
||||||
reloc_arm_machine_cp_entry,
|
reloc_arm_machine_cp_entry,
|
||||||
|
|
||||||
|
// reloc_arm_jt_base - PC relative relocation for jump tables whose
|
||||||
|
// addresses are kept locally in a map.
|
||||||
|
reloc_arm_jt_base,
|
||||||
|
|
||||||
|
// reloc_arm_pic_jt - PIC jump table entry relocation: dest bb - jt base.
|
||||||
|
reloc_arm_pic_jt,
|
||||||
|
|
||||||
// reloc_arm_branch - Branch address relocation.
|
// reloc_arm_branch - Branch address relocation.
|
||||||
reloc_arm_branch
|
reloc_arm_branch
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user