PPCCodeEmitter.cpp revision 205218
1//===-- PPCCodeEmitter.cpp - JIT Code Emitter for PowerPC32 -------*- C++ -*-=// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines the PowerPC 32-bit CodeEmitter and associated machinery to 11// JIT-compile bitcode to native PowerPC. 12// 13//===----------------------------------------------------------------------===// 14 15#include "PPCTargetMachine.h" 16#include "PPCRelocations.h" 17#include "PPC.h" 18#include "llvm/Module.h" 19#include "llvm/PassManager.h" 20#include "llvm/CodeGen/JITCodeEmitter.h" 21#include "llvm/CodeGen/MachineFunctionPass.h" 22#include "llvm/CodeGen/MachineInstrBuilder.h" 23#include "llvm/CodeGen/MachineModuleInfo.h" 24#include "llvm/Support/ErrorHandling.h" 25#include "llvm/Support/raw_ostream.h" 26#include "llvm/Target/TargetOptions.h" 27using namespace llvm; 28 29namespace { 30 class PPCCodeEmitter : public MachineFunctionPass { 31 TargetMachine &TM; 32 JITCodeEmitter &MCE; 33 MachineModuleInfo *MMI; 34 35 void getAnalysisUsage(AnalysisUsage &AU) const { 36 AU.addRequired<MachineModuleInfo>(); 37 MachineFunctionPass::getAnalysisUsage(AU); 38 } 39 40 static char ID; 41 42 /// MovePCtoLROffset - When/if we see a MovePCtoLR instruction, we record 43 /// its address in the function into this pointer. 44 void *MovePCtoLROffset; 45 public: 46 47 PPCCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) 48 : MachineFunctionPass(&ID), TM(tm), MCE(mce) {} 49 50 /// getBinaryCodeForInstr - This function, generated by the 51 /// CodeEmitterGenerator using TableGen, produces the binary encoding for 52 /// machine instructions. 53 54 unsigned getBinaryCodeForInstr(const MachineInstr &MI); 55 56 /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr 57 58 unsigned getMachineOpValue(const MachineInstr &MI, 59 const MachineOperand &MO); 60 61 const char *getPassName() const { return "PowerPC Machine Code Emitter"; } 62 63 /// runOnMachineFunction - emits the given MachineFunction to memory 64 /// 65 bool runOnMachineFunction(MachineFunction &MF); 66 67 /// emitBasicBlock - emits the given MachineBasicBlock to memory 68 /// 69 void emitBasicBlock(MachineBasicBlock &MBB); 70 71 /// getValueBit - return the particular bit of Val 72 /// 73 unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; } 74 }; 75} 76 77char PPCCodeEmitter::ID = 0; 78 79/// createPPCCodeEmitterPass - Return a pass that emits the collected PPC code 80/// to the specified MCE object. 81FunctionPass *llvm::createPPCJITCodeEmitterPass(PPCTargetMachine &TM, 82 JITCodeEmitter &JCE) { 83 return new PPCCodeEmitter(TM, JCE); 84} 85 86bool PPCCodeEmitter::runOnMachineFunction(MachineFunction &MF) { 87 assert((MF.getTarget().getRelocationModel() != Reloc::Default || 88 MF.getTarget().getRelocationModel() != Reloc::Static) && 89 "JIT relocation model must be set to static or default!"); 90 91 MMI = &getAnalysis<MachineModuleInfo>(); 92 MCE.setModuleInfo(MMI); 93 do { 94 MovePCtoLROffset = 0; 95 MCE.startFunction(MF); 96 for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB) 97 emitBasicBlock(*BB); 98 } while (MCE.finishFunction(MF)); 99 100 return false; 101} 102 103void PPCCodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) { 104 MCE.StartMachineBasicBlock(&MBB); 105 106 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I){ 107 const MachineInstr &MI = *I; 108 MCE.processDebugLoc(MI.getDebugLoc(), true); 109 switch (MI.getOpcode()) { 110 default: 111 MCE.emitWordBE(getBinaryCodeForInstr(MI)); 112 break; 113 case TargetOpcode::DBG_LABEL: 114 case TargetOpcode::EH_LABEL: 115 MCE.emitLabel(MI.getOperand(0).getMCSymbol()); 116 break; 117 case TargetOpcode::IMPLICIT_DEF: 118 case TargetOpcode::KILL: 119 break; // pseudo opcode, no side effects 120 case PPC::MovePCtoLR: 121 case PPC::MovePCtoLR8: 122 assert(TM.getRelocationModel() == Reloc::PIC_); 123 MovePCtoLROffset = (void*)MCE.getCurrentPCValue(); 124 MCE.emitWordBE(0x48000005); // bl 1 125 break; 126 } 127 MCE.processDebugLoc(MI.getDebugLoc(), false); 128 } 129} 130 131unsigned PPCCodeEmitter::getMachineOpValue(const MachineInstr &MI, 132 const MachineOperand &MO) { 133 134 unsigned rv = 0; // Return value; defaults to 0 for unhandled cases 135 // or things that get fixed up later by the JIT. 136 if (MO.isReg()) { 137 rv = PPCRegisterInfo::getRegisterNumbering(MO.getReg()); 138 139 // Special encoding for MTCRF and MFOCRF, which uses a bit mask for the 140 // register, not the register number directly. 141 if ((MI.getOpcode() == PPC::MTCRF || MI.getOpcode() == PPC::MFOCRF) && 142 (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)) { 143 rv = 0x80 >> rv; 144 } 145 } else if (MO.isImm()) { 146 rv = MO.getImm(); 147 } else if (MO.isGlobal() || MO.isSymbol() || 148 MO.isCPI() || MO.isJTI()) { 149 unsigned Reloc = 0; 150 if (MI.getOpcode() == PPC::BL_Darwin || MI.getOpcode() == PPC::BL8_Darwin || 151 MI.getOpcode() == PPC::BL_SVR4 || MI.getOpcode() == PPC::BL8_ELF || 152 MI.getOpcode() == PPC::TAILB || MI.getOpcode() == PPC::TAILB8) 153 Reloc = PPC::reloc_pcrel_bx; 154 else { 155 if (TM.getRelocationModel() == Reloc::PIC_) { 156 assert(MovePCtoLROffset && "MovePCtoLR not seen yet?"); 157 } 158 switch (MI.getOpcode()) { 159 default: MI.dump(); llvm_unreachable("Unknown instruction for relocation!"); 160 case PPC::LIS: 161 case PPC::LIS8: 162 case PPC::ADDIS: 163 case PPC::ADDIS8: 164 Reloc = PPC::reloc_absolute_high; // Pointer to symbol 165 break; 166 case PPC::LI: 167 case PPC::LI8: 168 case PPC::LA: 169 // Loads. 170 case PPC::LBZ: 171 case PPC::LBZ8: 172 case PPC::LHA: 173 case PPC::LHA8: 174 case PPC::LHZ: 175 case PPC::LHZ8: 176 case PPC::LWZ: 177 case PPC::LWZ8: 178 case PPC::LFS: 179 case PPC::LFD: 180 181 // Stores. 182 case PPC::STB: 183 case PPC::STB8: 184 case PPC::STH: 185 case PPC::STH8: 186 case PPC::STW: 187 case PPC::STW8: 188 case PPC::STFS: 189 case PPC::STFD: 190 Reloc = PPC::reloc_absolute_low; 191 break; 192 193 case PPC::LWA: 194 case PPC::LD: 195 case PPC::STD: 196 case PPC::STD_32: 197 Reloc = PPC::reloc_absolute_low_ix; 198 break; 199 } 200 } 201 202 MachineRelocation R; 203 if (MO.isGlobal()) { 204 R = MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, 205 MO.getGlobal(), 0, 206 isa<Function>(MO.getGlobal())); 207 } else if (MO.isSymbol()) { 208 R = MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), 209 Reloc, MO.getSymbolName(), 0); 210 } else if (MO.isCPI()) { 211 R = MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), 212 Reloc, MO.getIndex(), 0); 213 } else { 214 assert(MO.isJTI()); 215 R = MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), 216 Reloc, MO.getIndex(), 0); 217 } 218 219 // If in PIC mode, we need to encode the negated address of the 220 // 'movepctolr' into the unrelocated field. After relocation, we'll have 221 // &gv-&movepctolr-4 in the imm field. Once &movepctolr is added to the imm 222 // field, we get &gv. This doesn't happen for branch relocations, which are 223 // always implicitly pc relative. 224 if (TM.getRelocationModel() == Reloc::PIC_ && Reloc != PPC::reloc_pcrel_bx){ 225 assert(MovePCtoLROffset && "MovePCtoLR not seen yet?"); 226 R.setConstantVal(-(intptr_t)MovePCtoLROffset - 4); 227 } 228 MCE.addRelocation(R); 229 230 } else if (MO.isMBB()) { 231 unsigned Reloc = 0; 232 unsigned Opcode = MI.getOpcode(); 233 if (Opcode == PPC::B || Opcode == PPC::BL_Darwin || 234 Opcode == PPC::BLA_Darwin|| Opcode == PPC::BL_SVR4 || 235 Opcode == PPC::BLA_SVR4) 236 Reloc = PPC::reloc_pcrel_bx; 237 else // BCC instruction 238 Reloc = PPC::reloc_pcrel_bcx; 239 240 MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), 241 Reloc, MO.getMBB())); 242 } else { 243#ifndef NDEBUG 244 errs() << "ERROR: Unknown type of MachineOperand: " << MO << "\n"; 245#endif 246 llvm_unreachable(0); 247 } 248 249 return rv; 250} 251 252#include "PPCGenCodeEmitter.inc" 253