LLVM API Documentation

PPCCodeEmitter.cpp

Go to the documentation of this file.
00001 //===-- PPCCodeEmitter.cpp - JIT Code Emitter for PowerPC32 -------*- C++ -*-=//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines the PowerPC 32-bit CodeEmitter and associated machinery to
00011 // JIT-compile bitcode to native PowerPC.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "PPCTargetMachine.h"
00016 #include "PPCRelocations.h"
00017 #include "PPC.h"
00018 #include "llvm/Module.h"
00019 #include "llvm/PassManager.h"
00020 #include "llvm/CodeGen/MachineCodeEmitter.h"
00021 #include "llvm/CodeGen/MachineFunctionPass.h"
00022 #include "llvm/CodeGen/MachineInstrBuilder.h"
00023 #include "llvm/CodeGen/MachineModuleInfo.h"
00024 #include "llvm/CodeGen/Passes.h"
00025 #include "llvm/Support/Debug.h"                   
00026 #include "llvm/Support/Compiler.h"
00027 #include "llvm/Target/TargetOptions.h"
00028 using namespace llvm;
00029 
00030 namespace {
00031   class VISIBILITY_HIDDEN PPCCodeEmitter : public MachineFunctionPass {
00032     TargetMachine &TM;
00033     MachineCodeEmitter &MCE;
00034 
00035     /// MovePCtoLROffset - When/if we see a MovePCtoLR instruction, we record
00036     /// its address in the function into this pointer.
00037     void *MovePCtoLROffset;
00038     
00039     /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr
00040     ///
00041     unsigned getMachineOpValue(const MachineInstr &MI, const MachineOperand &MO);
00042     
00043     void getAnalysisUsage(AnalysisUsage &AU) const {
00044       AU.addRequired<MachineModuleInfo>();
00045       MachineFunctionPass::getAnalysisUsage(AU);
00046     }
00047 
00048   public:
00049     static char ID;
00050     PPCCodeEmitter(TargetMachine &T, MachineCodeEmitter &M)
00051       : MachineFunctionPass(&ID), TM(T), MCE(M) {}
00052 
00053     const char *getPassName() const { return "PowerPC Machine Code Emitter"; }
00054 
00055     /// runOnMachineFunction - emits the given MachineFunction to memory
00056     ///
00057     bool runOnMachineFunction(MachineFunction &MF);
00058 
00059     /// emitBasicBlock - emits the given MachineBasicBlock to memory
00060     ///
00061     void emitBasicBlock(MachineBasicBlock &MBB);
00062 
00063     /// getValueBit - return the particular bit of Val
00064     ///
00065     unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; }
00066 
00067     /// getBinaryCodeForInstr - This function, generated by the
00068     /// CodeEmitterGenerator using TableGen, produces the binary encoding for
00069     /// machine instructions.
00070     ///
00071     unsigned getBinaryCodeForInstr(const MachineInstr &MI);
00072   };
00073   char PPCCodeEmitter::ID = 0;
00074 }
00075 
00076 /// createPPCCodeEmitterPass - Return a pass that emits the collected PPC code
00077 /// to the specified MCE object.
00078 FunctionPass *llvm::createPPCCodeEmitterPass(PPCTargetMachine &TM,
00079                                              MachineCodeEmitter &MCE) {
00080   return new PPCCodeEmitter(TM, MCE);
00081 }
00082 
00083 bool PPCCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
00084   assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
00085           MF.getTarget().getRelocationModel() != Reloc::Static) &&
00086          "JIT relocation model must be set to static or default!");
00087 
00088   MCE.setModuleInfo(&getAnalysis<MachineModuleInfo>());
00089   do {
00090     MovePCtoLROffset = 0;
00091     MCE.startFunction(MF);
00092     for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
00093       emitBasicBlock(*BB);
00094   } while (MCE.finishFunction(MF));
00095 
00096   return false;
00097 }
00098 
00099 void PPCCodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) {
00100   MCE.StartMachineBasicBlock(&MBB);
00101   
00102   for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I){
00103     const MachineInstr &MI = *I;
00104     switch (MI.getOpcode()) {
00105     default:
00106       MCE.emitWordBE(getBinaryCodeForInstr(MI));
00107       break;
00108     case TargetInstrInfo::DBG_LABEL:
00109     case TargetInstrInfo::EH_LABEL:
00110       MCE.emitLabel(MI.getOperand(0).getImm());
00111       break;
00112     case TargetInstrInfo::IMPLICIT_DEF:
00113       break; // pseudo opcode, no side effects
00114     case PPC::MovePCtoLR:
00115     case PPC::MovePCtoLR8:
00116       assert(TM.getRelocationModel() == Reloc::PIC_);
00117       MovePCtoLROffset = (void*)MCE.getCurrentPCValue();
00118       MCE.emitWordBE(0x48000005);   // bl 1
00119       break;
00120     }
00121   }
00122 }
00123 
00124 unsigned PPCCodeEmitter::getMachineOpValue(const MachineInstr &MI,
00125                                            const MachineOperand &MO) {
00126 
00127   unsigned rv = 0; // Return value; defaults to 0 for unhandled cases
00128                    // or things that get fixed up later by the JIT.
00129   if (MO.isReg()) {
00130     rv = PPCRegisterInfo::getRegisterNumbering(MO.getReg());
00131 
00132     // Special encoding for MTCRF and MFOCRF, which uses a bit mask for the
00133     // register, not the register number directly.
00134     if ((MI.getOpcode() == PPC::MTCRF || MI.getOpcode() == PPC::MFOCRF) &&
00135         (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)) {
00136       rv = 0x80 >> rv;
00137     }
00138   } else if (MO.isImm()) {
00139     rv = MO.getImm();
00140   } else if (MO.isGlobal() || MO.isSymbol() ||
00141              MO.isCPI() || MO.isJTI()) {
00142     unsigned Reloc = 0;
00143     if (MI.getOpcode() == PPC::BL_Macho || MI.getOpcode() == PPC::BL8_Macho ||
00144         MI.getOpcode() == PPC::BL_ELF || MI.getOpcode() == PPC::BL8_ELF ||
00145         MI.getOpcode() == PPC::TAILB || MI.getOpcode() == PPC::TAILB8)
00146       Reloc = PPC::reloc_pcrel_bx;
00147     else {
00148       if (TM.getRelocationModel() == Reloc::PIC_) {
00149         assert(MovePCtoLROffset && "MovePCtoLR not seen yet?");
00150       }
00151       switch (MI.getOpcode()) {
00152       default: MI.dump(); assert(0 && "Unknown instruction for relocation!");
00153       case PPC::LIS:
00154       case PPC::LIS8:
00155       case PPC::ADDIS:
00156       case PPC::ADDIS8:
00157         Reloc = PPC::reloc_absolute_high;       // Pointer to symbol
00158         break;
00159       case PPC::LI:
00160       case PPC::LI8:
00161       case PPC::LA:
00162       // Loads.
00163       case PPC::LBZ:
00164       case PPC::LBZ8:
00165       case PPC::LHA:
00166       case PPC::LHA8:
00167       case PPC::LHZ:
00168       case PPC::LHZ8:
00169       case PPC::LWZ:
00170       case PPC::LWZ8:
00171       case PPC::LFS:
00172       case PPC::LFD:
00173       
00174       // Stores.
00175       case PPC::STB:
00176       case PPC::STB8:
00177       case PPC::STH:
00178       case PPC::STH8:
00179       case PPC::STW:
00180       case PPC::STW8:
00181       case PPC::STFS:
00182       case PPC::STFD:
00183         Reloc = PPC::reloc_absolute_low;
00184         break;
00185 
00186       case PPC::LWA:
00187       case PPC::LD:
00188       case PPC::STD:
00189       case PPC::STD_32:
00190         Reloc = PPC::reloc_absolute_low_ix;
00191         break;
00192       }
00193     }
00194     
00195     MachineRelocation R;
00196     if (MO.isGlobal()) {
00197       R = MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
00198                                    MO.getGlobal(), 0,
00199                                    isa<Function>(MO.getGlobal()));
00200     } else if (MO.isSymbol()) {
00201       R = MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
00202                                        Reloc, MO.getSymbolName(), 0);
00203     } else if (MO.isCPI()) {
00204       R = MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
00205                                           Reloc, MO.getIndex(), 0);
00206     } else {
00207       assert(MO.isJTI());
00208       R = MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
00209                                           Reloc, MO.getIndex(), 0);
00210     }
00211     
00212     // If in PIC mode, we need to encode the negated address of the
00213     // 'movepctolr' into the unrelocated field.  After relocation, we'll have
00214     // &gv-&movepctolr-4 in the imm field.  Once &movepctolr is added to the imm
00215     // field, we get &gv.  This doesn't happen for branch relocations, which are
00216     // always implicitly pc relative.
00217     if (TM.getRelocationModel() == Reloc::PIC_ && Reloc != PPC::reloc_pcrel_bx){
00218       assert(MovePCtoLROffset && "MovePCtoLR not seen yet?");
00219       R.setConstantVal(-(intptr_t)MovePCtoLROffset - 4);
00220     }
00221     MCE.addRelocation(R);
00222     
00223   } else if (MO.isMBB()) {
00224     unsigned Reloc = 0;
00225     unsigned Opcode = MI.getOpcode();
00226     if (Opcode == PPC::B || Opcode == PPC::BL_Macho ||
00227         Opcode == PPC::BLA_Macho || Opcode == PPC::BL_ELF || 
00228         Opcode == PPC::BLA_ELF)
00229       Reloc = PPC::reloc_pcrel_bx;
00230     else // BCC instruction
00231       Reloc = PPC::reloc_pcrel_bcx;
00232     MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(),
00233                                                Reloc, MO.getMBB()));
00234   } else {
00235     cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
00236     abort();
00237   }
00238 
00239   return rv;
00240 }
00241 
00242 #include "PPCGenCodeEmitter.inc"
00243