mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
7d7d99622f
The old system was fairly convoluted: * A temporary label was created. * A single PROLOG_LABEL was created with it. * A few MCCFIInstructions were created with the same label. The semantics were that the cfi instructions were mapped to the PROLOG_LABEL via the temporary label. The output position was that of the PROLOG_LABEL. The temporary label itself was used only for doing the mapping. The new CFI_INSTRUCTION has a 1:1 mapping to MCCFIInstructions and points to one by holding an index into the CFI instructions of this function. I did consider removing MMI.getFrameInstructions completelly and having CFI_INSTRUCTION own a MCCFIInstruction, but MCCFIInstructions have non trivial constructors and destructors and are somewhat big, so the this setup is probably better. The net result is that we don't create temporary labels that are never used. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203204 91177308-0d34-0410-b5e6-96231b3b80d8
280 lines
9.5 KiB
C++
280 lines
9.5 KiB
C++
//===-- Sparc/SparcCodeEmitter.cpp - Convert Sparc Code to Machine Code ---===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===---------------------------------------------------------------------===//
|
|
//
|
|
// This file contains the pass that transforms the Sparc machine instructions
|
|
// into relocatable machine code.
|
|
//
|
|
//===---------------------------------------------------------------------===//
|
|
|
|
#define DEBUG_TYPE "jit"
|
|
#include "Sparc.h"
|
|
#include "MCTargetDesc/SparcMCExpr.h"
|
|
#include "SparcRelocations.h"
|
|
#include "SparcTargetMachine.h"
|
|
#include "llvm/ADT/Statistic.h"
|
|
#include "llvm/CodeGen/JITCodeEmitter.h"
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
using namespace llvm;
|
|
|
|
STATISTIC(NumEmitted, "Number of machine instructions emitted");
|
|
|
|
namespace {
|
|
|
|
class SparcCodeEmitter : public MachineFunctionPass {
|
|
SparcJITInfo *JTI;
|
|
const SparcInstrInfo *II;
|
|
const DataLayout *TD;
|
|
const SparcSubtarget *Subtarget;
|
|
TargetMachine &TM;
|
|
JITCodeEmitter &MCE;
|
|
const std::vector<MachineConstantPoolEntry> *MCPEs;
|
|
bool IsPIC;
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const {
|
|
AU.addRequired<MachineModuleInfo> ();
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
}
|
|
|
|
static char ID;
|
|
|
|
public:
|
|
SparcCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce)
|
|
: MachineFunctionPass(ID), JTI(0), II(0), TD(0),
|
|
TM(tm), MCE(mce), MCPEs(0),
|
|
IsPIC(TM.getRelocationModel() == Reloc::PIC_) {}
|
|
|
|
bool runOnMachineFunction(MachineFunction &MF);
|
|
|
|
virtual const char *getPassName() const {
|
|
return "Sparc Machine Code Emitter";
|
|
}
|
|
|
|
/// getBinaryCodeForInstr - This function, generated by the
|
|
/// CodeEmitterGenerator using TableGen, produces the binary encoding for
|
|
/// machine instructions.
|
|
uint64_t getBinaryCodeForInstr(const MachineInstr &MI) const;
|
|
|
|
void emitInstruction(MachineBasicBlock::instr_iterator MI,
|
|
MachineBasicBlock &MBB);
|
|
|
|
private:
|
|
/// getMachineOpValue - Return binary encoding of operand. If the machine
|
|
/// operand requires relocation, record the relocation and return zero.
|
|
unsigned getMachineOpValue(const MachineInstr &MI,
|
|
const MachineOperand &MO) const;
|
|
|
|
unsigned getCallTargetOpValue(const MachineInstr &MI,
|
|
unsigned) const;
|
|
unsigned getBranchTargetOpValue(const MachineInstr &MI,
|
|
unsigned) const;
|
|
unsigned getBranchPredTargetOpValue(const MachineInstr &MI,
|
|
unsigned) const;
|
|
unsigned getBranchOnRegTargetOpValue(const MachineInstr &MI,
|
|
unsigned) const;
|
|
|
|
void emitWord(unsigned Word);
|
|
|
|
unsigned getRelocation(const MachineInstr &MI,
|
|
const MachineOperand &MO) const;
|
|
|
|
void emitGlobalAddress(const GlobalValue *GV, unsigned Reloc) const;
|
|
void emitExternalSymbolAddress(const char *ES, unsigned Reloc) const;
|
|
void emitConstPoolAddress(unsigned CPI, unsigned Reloc) const;
|
|
void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc) const;
|
|
};
|
|
} // end anonymous namespace.
|
|
|
|
char SparcCodeEmitter::ID = 0;
|
|
|
|
bool SparcCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
|
|
SparcTargetMachine &Target = static_cast<SparcTargetMachine &>(
|
|
const_cast<TargetMachine &>(MF.getTarget()));
|
|
|
|
JTI = Target.getJITInfo();
|
|
II = Target.getInstrInfo();
|
|
TD = Target.getDataLayout();
|
|
Subtarget = &TM.getSubtarget<SparcSubtarget> ();
|
|
MCPEs = &MF.getConstantPool()->getConstants();
|
|
JTI->Initialize(MF, IsPIC);
|
|
MCE.setModuleInfo(&getAnalysis<MachineModuleInfo> ());
|
|
|
|
do {
|
|
DEBUG(errs() << "JITTing function '"
|
|
<< MF.getName() << "'\n");
|
|
MCE.startFunction(MF);
|
|
|
|
for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
|
|
MBB != E; ++MBB){
|
|
MCE.StartMachineBasicBlock(MBB);
|
|
for (MachineBasicBlock::instr_iterator I = MBB->instr_begin(),
|
|
E = MBB->instr_end(); I != E;)
|
|
emitInstruction(*I++, *MBB);
|
|
}
|
|
} while (MCE.finishFunction(MF));
|
|
|
|
return false;
|
|
}
|
|
|
|
void SparcCodeEmitter::emitInstruction(MachineBasicBlock::instr_iterator MI,
|
|
MachineBasicBlock &MBB) {
|
|
DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << *MI);
|
|
|
|
MCE.processDebugLoc(MI->getDebugLoc(), true);
|
|
|
|
++NumEmitted;
|
|
|
|
switch (MI->getOpcode()) {
|
|
default: {
|
|
emitWord(getBinaryCodeForInstr(*MI));
|
|
break;
|
|
}
|
|
case TargetOpcode::INLINEASM: {
|
|
// We allow inline assembler nodes with empty bodies - they can
|
|
// implicitly define registers, which is ok for JIT.
|
|
if (MI->getOperand(0).getSymbolName()[0]) {
|
|
report_fatal_error("JIT does not support inline asm!");
|
|
}
|
|
break;
|
|
}
|
|
case TargetOpcode::CFI_INSTRUCTION:
|
|
break;
|
|
case TargetOpcode::EH_LABEL: {
|
|
MCE.emitLabel(MI->getOperand(0).getMCSymbol());
|
|
break;
|
|
}
|
|
case TargetOpcode::IMPLICIT_DEF:
|
|
case TargetOpcode::KILL: {
|
|
// Do nothing.
|
|
break;
|
|
}
|
|
case SP::GETPCX: {
|
|
report_fatal_error("JIT does not support pseudo instruction GETPCX yet!");
|
|
break;
|
|
}
|
|
}
|
|
|
|
MCE.processDebugLoc(MI->getDebugLoc(), false);
|
|
}
|
|
|
|
void SparcCodeEmitter::emitWord(unsigned Word) {
|
|
DEBUG(errs() << " 0x";
|
|
errs().write_hex(Word) << "\n");
|
|
MCE.emitWordBE(Word);
|
|
}
|
|
|
|
/// getMachineOpValue - Return binary encoding of operand. If the machine
|
|
/// operand requires relocation, record the relocation and return zero.
|
|
unsigned SparcCodeEmitter::getMachineOpValue(const MachineInstr &MI,
|
|
const MachineOperand &MO) const {
|
|
if (MO.isReg())
|
|
return TM.getRegisterInfo()->getEncodingValue(MO.getReg());
|
|
else if (MO.isImm())
|
|
return static_cast<unsigned>(MO.getImm());
|
|
else if (MO.isGlobal())
|
|
emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO));
|
|
else if (MO.isSymbol())
|
|
emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO));
|
|
else if (MO.isCPI())
|
|
emitConstPoolAddress(MO.getIndex(), getRelocation(MI, MO));
|
|
else if (MO.isMBB())
|
|
emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO));
|
|
else
|
|
llvm_unreachable("Unable to encode MachineOperand!");
|
|
return 0;
|
|
}
|
|
unsigned SparcCodeEmitter::getCallTargetOpValue(const MachineInstr &MI,
|
|
unsigned opIdx) const {
|
|
const MachineOperand MO = MI.getOperand(opIdx);
|
|
return getMachineOpValue(MI, MO);
|
|
}
|
|
|
|
unsigned SparcCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI,
|
|
unsigned opIdx) const {
|
|
const MachineOperand MO = MI.getOperand(opIdx);
|
|
return getMachineOpValue(MI, MO);
|
|
}
|
|
|
|
unsigned SparcCodeEmitter::getBranchPredTargetOpValue(const MachineInstr &MI,
|
|
unsigned opIdx) const {
|
|
const MachineOperand MO = MI.getOperand(opIdx);
|
|
return getMachineOpValue(MI, MO);
|
|
}
|
|
|
|
unsigned SparcCodeEmitter::getBranchOnRegTargetOpValue(const MachineInstr &MI,
|
|
unsigned opIdx) const {
|
|
const MachineOperand MO = MI.getOperand(opIdx);
|
|
return getMachineOpValue(MI, MO);
|
|
}
|
|
|
|
unsigned SparcCodeEmitter::getRelocation(const MachineInstr &MI,
|
|
const MachineOperand &MO) const {
|
|
|
|
unsigned TF = MO.getTargetFlags();
|
|
switch (TF) {
|
|
default:
|
|
case SparcMCExpr::VK_Sparc_None: break;
|
|
case SparcMCExpr::VK_Sparc_LO: return SP::reloc_sparc_lo;
|
|
case SparcMCExpr::VK_Sparc_HI: return SP::reloc_sparc_hi;
|
|
case SparcMCExpr::VK_Sparc_H44: return SP::reloc_sparc_h44;
|
|
case SparcMCExpr::VK_Sparc_M44: return SP::reloc_sparc_m44;
|
|
case SparcMCExpr::VK_Sparc_L44: return SP::reloc_sparc_l44;
|
|
case SparcMCExpr::VK_Sparc_HH: return SP::reloc_sparc_hh;
|
|
case SparcMCExpr::VK_Sparc_HM: return SP::reloc_sparc_hm;
|
|
}
|
|
|
|
unsigned Opc = MI.getOpcode();
|
|
switch (Opc) {
|
|
default: break;
|
|
case SP::CALL: return SP::reloc_sparc_pc30;
|
|
case SP::BA:
|
|
case SP::BCOND:
|
|
case SP::FBCOND: return SP::reloc_sparc_pc22;
|
|
case SP::BPXCC: return SP::reloc_sparc_pc19;
|
|
}
|
|
llvm_unreachable("unknown reloc!");
|
|
}
|
|
|
|
void SparcCodeEmitter::emitGlobalAddress(const GlobalValue *GV,
|
|
unsigned Reloc) const {
|
|
MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
|
|
const_cast<GlobalValue *>(GV), 0,
|
|
true));
|
|
}
|
|
|
|
void SparcCodeEmitter::
|
|
emitExternalSymbolAddress(const char *ES, unsigned Reloc) const {
|
|
MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
|
|
Reloc, ES, 0, 0));
|
|
}
|
|
|
|
void SparcCodeEmitter::
|
|
emitConstPoolAddress(unsigned CPI, unsigned Reloc) const {
|
|
MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
|
|
Reloc, CPI, 0, false));
|
|
}
|
|
|
|
void SparcCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB,
|
|
unsigned Reloc) const {
|
|
MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(),
|
|
Reloc, BB));
|
|
}
|
|
|
|
|
|
/// createSparcJITCodeEmitterPass - Return a pass that emits the collected Sparc
|
|
/// code to the specified MCE object.
|
|
FunctionPass *llvm::createSparcJITCodeEmitterPass(SparcTargetMachine &TM,
|
|
JITCodeEmitter &JCE) {
|
|
return new SparcCodeEmitter(TM, JCE);
|
|
}
|
|
|
|
#include "SparcGenCodeEmitter.inc"
|