//===-- 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. // //===---------------------------------------------------------------------===// #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; #define DEBUG_TYPE "jit" 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 *MCPEs; bool IsPIC; void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired (); MachineFunctionPass::getAnalysisUsage(AU); } static char ID; public: SparcCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) : MachineFunctionPass(ID), JTI(nullptr), II(nullptr), TD(nullptr), TM(tm), MCE(mce), MCPEs(nullptr), 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( const_cast(MF.getTarget())); JTI = Target.getJITInfo(); II = Target.getInstrInfo(); TD = Target.getDataLayout(); Subtarget = &TM.getSubtarget (); MCPEs = &MF.getConstantPool()->getConstants(); JTI->Initialize(MF, IsPIC); MCE.setModuleInfo(&getAnalysis ()); 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(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(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"