mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202628 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			279 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			279 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::PROLOG_LABEL:
 | |
|   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"
 |