X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FPowerPC%2FPPCCodeEmitter.cpp;h=418736e21e86f2dee01484d95ffd335c59f54b2a;hb=d254d3111e6a1b2dfc31bbfb3abb7cc589d5800b;hp=a63a7a3a797c81c41a431df063a3533887e7dea5;hpb=99b394db151615414fc3de24e72c199799a05398;p=oota-llvm.git diff --git a/lib/Target/PowerPC/PPCCodeEmitter.cpp b/lib/Target/PowerPC/PPCCodeEmitter.cpp index a63a7a3a797..418736e21e8 100644 --- a/lib/Target/PowerPC/PPCCodeEmitter.cpp +++ b/lib/Target/PowerPC/PPCCodeEmitter.cpp @@ -1,123 +1,77 @@ -//===-- PPC32CodeEmitter.cpp - JIT Code Emitter for PowerPC32 -----*- C++ -*-=// -// +//===-- PPCCodeEmitter.cpp - JIT Code Emitter for PowerPC -----------------===// +// // The LLVM Compiler Infrastructure // -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// //===----------------------------------------------------------------------===// -// +// // This file defines the PowerPC 32-bit CodeEmitter and associated machinery to -// JIT-compile bytecode to native PowerPC. +// JIT-compile bitcode to native PowerPC. // //===----------------------------------------------------------------------===// -#include "PPC32JITInfo.h" -#include "PPC32TargetMachine.h" -#include "PowerPC.h" -#include "llvm/Module.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "PPC.h" +#include "PPCRelocations.h" +#include "PPCTargetMachine.h" +#include "llvm/CodeGen/JITCodeEmitter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/Support/Debug.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetOptions.h" using namespace llvm; namespace { - class JITResolver { - MachineCodeEmitter &MCE; - - // LazyCodeGenMap - Keep track of call sites for functions that are to be - // lazily resolved. - std::map LazyCodeGenMap; - - // LazyResolverMap - Keep track of the lazy resolver created for a - // particular function so that we can reuse them if necessary. - std::map LazyResolverMap; - + class PPCCodeEmitter : public MachineFunctionPass { + TargetMachine &TM; + JITCodeEmitter &MCE; + MachineModuleInfo *MMI; + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + static char ID; + + /// MovePCtoLROffset - When/if we see a MovePCtoLR instruction, we record + /// its address in the function into this pointer. + void *MovePCtoLROffset; public: - JITResolver(MachineCodeEmitter &mce) : MCE(mce) {} - unsigned getLazyResolver(Function *F); - unsigned addFunctionReference(unsigned Address, Function *F); - private: - unsigned emitStubForFunction(Function *F); - static void CompilationCallback(); - unsigned resolveFunctionReference(unsigned RetAddr); - }; - - static JITResolver &getResolver(MachineCodeEmitter &MCE) { - static JITResolver *TheJITResolver = 0; - if (TheJITResolver == 0) - TheJITResolver = new JITResolver(MCE); - return *TheJITResolver; - } -} - -unsigned JITResolver::getLazyResolver(Function *F) { - std::map::iterator I = LazyResolverMap.lower_bound(F); - if (I != LazyResolverMap.end() && I->first == F) return I->second; - - unsigned Stub = emitStubForFunction(F); - LazyResolverMap.insert(I, std::make_pair(F, Stub)); - return Stub; -} - -/// addFunctionReference - This method is called when we need to emit the -/// address of a function that has not yet been emitted, so we don't know the -/// address. Instead, we emit a call to the CompilationCallback method, and -/// keep track of where we are. -/// -unsigned JITResolver::addFunctionReference(unsigned Address, Function *F) { - LazyCodeGenMap[Address] = F; - return (intptr_t)&JITResolver::CompilationCallback; -} + PPCCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) + : MachineFunctionPass(ID), TM(tm), MCE(mce) {} -unsigned JITResolver::resolveFunctionReference(unsigned RetAddr) { - std::map::iterator I = LazyCodeGenMap.find(RetAddr); - assert(I != LazyCodeGenMap.end() && "Not in map!"); - Function *F = I->second; - LazyCodeGenMap.erase(I); - return MCE.forceCompilationOf(F); -} - -/// emitStubForFunction - This method is used by the JIT when it needs to emit -/// the address of a function for a function whose code has not yet been -/// generated. In order to do this, it generates a stub which jumps to the lazy -/// function compiler, which will eventually get fixed to call the function -/// directly. -/// -unsigned JITResolver::emitStubForFunction(Function *F) { - std::cerr << "PPC32CodeEmitter::emitStubForFunction() unimplemented!\n"; - abort(); - return 0; -} - -void JITResolver::CompilationCallback() { - std::cerr << "PPC32CodeEmitter: CompilationCallback() unimplemented!"; - abort(); -} - -namespace { - class PPC32CodeEmitter : public MachineFunctionPass { - TargetMachine &TM; - MachineCodeEmitter &MCE; - - // Tracks which instruction references which BasicBlock - std::vector > > BBRefs; - // Tracks where each BasicBlock starts - std::map BBLocations; + /// getBinaryCodeForInstr - This function, generated by the + /// CodeEmitterGenerator using TableGen, produces the binary encoding for + /// machine instructions. + uint64_t getBinaryCodeForInstr(const MachineInstr &MI) const; + + MachineRelocation GetRelocation(const MachineOperand &MO, + unsigned RelocID) const; + /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr - /// - int64_t getMachineOpValue(MachineInstr &MI, MachineOperand &MO); - - unsigned getAddressOfExternalFunction(Function *F); - - public: - PPC32CodeEmitter(TargetMachine &T, MachineCodeEmitter &M) - : TM(T), MCE(M) {} + unsigned getMachineOpValue(const MachineInstr &MI, + const MachineOperand &MO) const; + + unsigned get_crbitm_encoding(const MachineInstr &MI, unsigned OpNo) const; + unsigned getDirectBrEncoding(const MachineInstr &MI, unsigned OpNo) const; + unsigned getCondBrEncoding(const MachineInstr &MI, unsigned OpNo) const; + unsigned getAbsDirectBrEncoding(const MachineInstr &MI, + unsigned OpNo) const; + unsigned getAbsCondBrEncoding(const MachineInstr &MI, unsigned OpNo) const; + + unsigned getImm16Encoding(const MachineInstr &MI, unsigned OpNo) const; + unsigned getMemRIEncoding(const MachineInstr &MI, unsigned OpNo) const; + unsigned getMemRIXEncoding(const MachineInstr &MI, unsigned OpNo) const; + unsigned getTLSRegEncoding(const MachineInstr &MI, unsigned OpNo) const; + unsigned getTLSCallEncoding(const MachineInstr &MI, unsigned OpNo) const; const char *getPassName() const { return "PowerPC Machine Code Emitter"; } @@ -128,191 +82,209 @@ namespace { /// emitBasicBlock - emits the given MachineBasicBlock to memory /// void emitBasicBlock(MachineBasicBlock &MBB); + }; +} - /// emitWord - write a 32-bit word to memory at the current PC - /// - void emitWord(unsigned w) { MCE.emitWord(w); } - - /// getValueBit - return the particular bit of Val - /// - unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; } +char PPCCodeEmitter::ID = 0; - /// getBinaryCodeForInstr - This function, generated by the - /// CodeEmitterGenerator using TableGen, produces the binary encoding for - /// machine instructions. - /// - unsigned getBinaryCodeForInstr(MachineInstr &MI); - }; +/// createPPCCodeEmitterPass - Return a pass that emits the collected PPC code +/// to the specified MCE object. +FunctionPass *llvm::createPPCJITCodeEmitterPass(PPCTargetMachine &TM, + JITCodeEmitter &JCE) { + return new PPCCodeEmitter(TM, JCE); } -/// addPassesToEmitMachineCode - Add passes to the specified pass manager to get -/// machine code emitted. This uses a MachineCodeEmitter object to handle -/// actually outputting the machine code and resolving things like the address -/// of functions. This method should returns true if machine code emission is -/// not supported. -/// -bool PPC32TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM, - MachineCodeEmitter &MCE) { - // Keep as `true' until this is a functional JIT to allow llvm-gcc to build - return true; - - // Machine code emitter pass for PowerPC - PM.add(new PPC32CodeEmitter(*this, MCE)); - // Delete machine code for this function after emitting it - PM.add(createMachineCodeDeleter()); +bool PPCCodeEmitter::runOnMachineFunction(MachineFunction &MF) { + assert((MF.getTarget().getRelocationModel() != Reloc::Default || + MF.getTarget().getRelocationModel() != Reloc::Static) && + "JIT relocation model must be set to static or default!"); + + MMI = &getAnalysis(); + MCE.setModuleInfo(MMI); + do { + MovePCtoLROffset = 0; + MCE.startFunction(MF); + for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB) + emitBasicBlock(*BB); + } while (MCE.finishFunction(MF)); + return false; } -bool PPC32CodeEmitter::runOnMachineFunction(MachineFunction &MF) { - MCE.startFunction(MF); - MCE.emitConstantPool(MF.getConstantPool()); - for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB) - emitBasicBlock(*BB); - MCE.finishFunction(MF); - - // Resolve branches to BasicBlocks for the entire function - for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) { - long Location = BBLocations[BBRefs[i].first]; - unsigned *Ref = BBRefs[i].second.first; - MachineInstr *MI = BBRefs[i].second.second; - DEBUG(std::cerr << "Fixup @ " << std::hex << Ref << " to 0x" << Location - << " in instr: " << std::dec << *MI); - for (unsigned ii = 0, ee = MI->getNumOperands(); ii != ee; ++ii) { - MachineOperand &op = MI->getOperand(ii); - if (op.isPCRelativeDisp()) { - // the instruction's branch target is made such that it branches to - // PC + (branchTarget * 4), so undo that arithmetic here: - // Location is the target of the branch - // Ref is the location of the instruction, and hence the PC - int64_t branchTarget = (Location - (long)Ref) >> 2; - MI->SetMachineOperandConst(ii, MachineOperand::MO_SignExtendedImmed, - branchTarget); - unsigned fixedInstr = PPC32CodeEmitter::getBinaryCodeForInstr(*MI); - MCE.emitWordAt(fixedInstr, Ref); - break; - } +void PPCCodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) { + MCE.StartMachineBasicBlock(&MBB); + + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I){ + const MachineInstr &MI = *I; + MCE.processDebugLoc(MI.getDebugLoc(), true); + switch (MI.getOpcode()) { + default: + MCE.emitWordBE(getBinaryCodeForInstr(MI)); + break; + case TargetOpcode::PROLOG_LABEL: + case TargetOpcode::EH_LABEL: + MCE.emitLabel(MI.getOperand(0).getMCSymbol()); + break; + case TargetOpcode::IMPLICIT_DEF: + case TargetOpcode::KILL: + break; // pseudo opcode, no side effects + case PPC::MovePCtoLR: + case PPC::MovePCtoLR8: + assert(TM.getRelocationModel() == Reloc::PIC_); + MovePCtoLROffset = (void*)MCE.getCurrentPCValue(); + MCE.emitWordBE(0x48000005); // bl 1 + break; } + MCE.processDebugLoc(MI.getDebugLoc(), false); } - BBRefs.clear(); - BBLocations.clear(); +} - return false; +unsigned PPCCodeEmitter::get_crbitm_encoding(const MachineInstr &MI, + unsigned OpNo) const { + const MachineOperand &MO = MI.getOperand(OpNo); + assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 || + MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) && + (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)); + return 0x80 >> TM.getRegisterInfo()->getEncodingValue(MO.getReg()); } -void PPC32CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) { - BBLocations[MBB.getBasicBlock()] = MCE.getCurrentPCValue(); - for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I){ - MachineInstr &MI = *I; - unsigned Opcode = MI.getOpcode(); - if (Opcode == PPC::IMPLICIT_DEF) - continue; // pseudo opcode, no side effects - else if (Opcode == PPC::MovePCtoLR) { - // This can be simplified: the resulting 32-bit code is 0x48000005 - MachineInstr *MI = BuildMI(PPC::BL, 1).addImm(1); - emitWord(getBinaryCodeForInstr(*MI)); - delete MI; - } else - emitWord(getBinaryCodeForInstr(*I)); +MachineRelocation PPCCodeEmitter::GetRelocation(const MachineOperand &MO, + unsigned RelocID) const { + // If in PIC mode, we need to encode the negated address of the + // 'movepctolr' into the unrelocated field. After relocation, we'll have + // &gv-&movepctolr-4 in the imm field. Once &movepctolr is added to the imm + // field, we get &gv. This doesn't happen for branch relocations, which are + // always implicitly pc relative. + intptr_t Cst = 0; + if (TM.getRelocationModel() == Reloc::PIC_) { + assert(MovePCtoLROffset && "MovePCtoLR not seen yet?"); + Cst = -(intptr_t)MovePCtoLROffset - 4; } + + if (MO.isGlobal()) + return MachineRelocation::getGV(MCE.getCurrentPCOffset(), RelocID, + const_cast(MO.getGlobal()), + Cst, isa(MO.getGlobal())); + if (MO.isSymbol()) + return MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), + RelocID, MO.getSymbolName(), Cst); + if (MO.isCPI()) + return MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), + RelocID, MO.getIndex(), Cst); + + if (MO.isMBB()) + return MachineRelocation::getBB(MCE.getCurrentPCOffset(), + RelocID, MO.getMBB()); + + assert(MO.isJTI()); + return MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), + RelocID, MO.getIndex(), Cst); } -unsigned PPC32CodeEmitter::getAddressOfExternalFunction(Function *F) { - static std::map ExternalFn2Addr; - std::map::iterator Addr = ExternalFn2Addr.find(F); +unsigned PPCCodeEmitter::getDirectBrEncoding(const MachineInstr &MI, + unsigned OpNo) const { + const MachineOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO); + + MCE.addRelocation(GetRelocation(MO, PPC::reloc_pcrel_bx)); + return 0; +} - if (Addr == ExternalFn2Addr.end()) - ExternalFn2Addr[F] = MCE.forceCompilationOf(F); - return ExternalFn2Addr[F]; +unsigned PPCCodeEmitter::getCondBrEncoding(const MachineInstr &MI, + unsigned OpNo) const { + const MachineOperand &MO = MI.getOperand(OpNo); + MCE.addRelocation(GetRelocation(MO, PPC::reloc_pcrel_bcx)); + return 0; } -static unsigned enumRegToMachineReg(unsigned enumReg) { - switch (enumReg) { - case PPC::R0 : case PPC::F0 : return 0; - case PPC::R1 : case PPC::F1 : return 1; - case PPC::R2 : case PPC::F2 : return 2; - case PPC::R3 : case PPC::F3 : return 3; - case PPC::R4 : case PPC::F4 : return 4; - case PPC::R5 : case PPC::F5 : return 5; - case PPC::R6 : case PPC::F6 : return 6; - case PPC::R7 : case PPC::F7 : return 7; - case PPC::R8 : case PPC::F8 : return 8; - case PPC::R9 : case PPC::F9 : return 9; - case PPC::R10: case PPC::F10: return 10; - case PPC::R11: case PPC::F11: return 11; - case PPC::R12: case PPC::F12: return 12; - case PPC::R13: case PPC::F13: return 13; - case PPC::R14: case PPC::F14: return 14; - case PPC::R15: case PPC::F15: return 15; - case PPC::R16: case PPC::F16: return 16; - case PPC::R17: case PPC::F17: return 17; - case PPC::R18: case PPC::F18: return 18; - case PPC::R19: case PPC::F19: return 19; - case PPC::R20: case PPC::F20: return 20; - case PPC::R21: case PPC::F21: return 21; - case PPC::R22: case PPC::F22: return 22; - case PPC::R23: case PPC::F23: return 23; - case PPC::R24: case PPC::F24: return 24; - case PPC::R25: case PPC::F25: return 25; - case PPC::R26: case PPC::F26: return 26; - case PPC::R27: case PPC::F27: return 27; - case PPC::R28: case PPC::F28: return 28; - case PPC::R29: case PPC::F29: return 29; - case PPC::R30: case PPC::F30: return 30; - case PPC::R31: case PPC::F31: return 31; - default: - std::cerr << "Unhandled reg in enumRegToRealReg!\n"; - abort(); - } +unsigned PPCCodeEmitter::getAbsDirectBrEncoding(const MachineInstr &MI, + unsigned OpNo) const { + const MachineOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO); + + llvm_unreachable("Absolute branch relocations unsupported on the old JIT."); } -int64_t PPC32CodeEmitter::getMachineOpValue(MachineInstr &MI, - MachineOperand &MO) { - int64_t rv = 0; // Return value; defaults to 0 for unhandled cases - // or things that get fixed up later by the JIT. - if (MO.isRegister()) { - rv = enumRegToMachineReg(MO.getReg()); - } else if (MO.isImmediate()) { - rv = MO.getImmedValue(); - } else if (MO.isGlobalAddress()) { - //GlobalValue *GV = MO.getGlobal(); - // FIXME: Emit a relocation here. - rv = 0; - } else if (MO.isMachineBasicBlock()) { - const BasicBlock *BB = MO.getMachineBasicBlock()->getBasicBlock(); - unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue(); - BBRefs.push_back(std::make_pair(BB, std::make_pair(CurrPC, &MI))); - } else if (MO.isConstantPoolIndex()) { - unsigned index = MO.getConstantPoolIndex(); - rv = MCE.getConstantPoolEntryAddress(index); - } else if (MO.isFrameIndex()) { - std::cerr << "PPC32CodeEmitter: error: Frame index unhandled!\n"; - abort(); - } else { - std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n"; - abort(); - } +unsigned PPCCodeEmitter::getAbsCondBrEncoding(const MachineInstr &MI, + unsigned OpNo) const { + llvm_unreachable("Absolute branch relocations unsupported on the old JIT."); +} - // Special treatment for global symbols: constants and vars - if (MO.isConstantPoolIndex() || MO.isGlobalAddress()) { - unsigned Opcode = MI.getOpcode(); - int64_t MBBLoc = BBLocations[MI.getParent()->getBasicBlock()]; - if (Opcode == PPC::LOADHiAddr) { - // LoadHiAddr wants hi16(addr - mbb) - rv = (rv - MBBLoc) >> 16; - } else if (Opcode == PPC::LWZ || Opcode == PPC::LA || - Opcode == PPC::LFS || Opcode == PPC::LFD) { - // These load opcodes want lo16(addr - mbb) - rv = (rv - MBBLoc) & 0xffff; - } +unsigned PPCCodeEmitter::getImm16Encoding(const MachineInstr &MI, + unsigned OpNo) const { + const MachineOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO); + + unsigned RelocID; + switch (MO.getTargetFlags() & PPCII::MO_ACCESS_MASK) { + default: llvm_unreachable("Unsupported target operand flags!"); + case PPCII::MO_LO: RelocID = PPC::reloc_absolute_low; break; + case PPCII::MO_HA: RelocID = PPC::reloc_absolute_high; break; } - return rv; + MCE.addRelocation(GetRelocation(MO, RelocID)); + return 0; } -void PPC32JITInfo::replaceMachineCodeForFunction (void *Old, void *New) { - std::cerr << "PPC32JITInfo::replaceMachineCodeForFunction not implemented\n"; - abort(); +unsigned PPCCodeEmitter::getMemRIEncoding(const MachineInstr &MI, + unsigned OpNo) const { + // Encode (imm, reg) as a memri, which has the low 16-bits as the + // displacement and the next 5 bits as the register #. + assert(MI.getOperand(OpNo+1).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1)) << 16; + + const MachineOperand &MO = MI.getOperand(OpNo); + if (MO.isImm()) + return (getMachineOpValue(MI, MO) & 0xFFFF) | RegBits; + + // Add a fixup for the displacement field. + MCE.addRelocation(GetRelocation(MO, PPC::reloc_absolute_low)); + return RegBits; } -#include "PPC32GenCodeEmitter.inc" +unsigned PPCCodeEmitter::getMemRIXEncoding(const MachineInstr &MI, + unsigned OpNo) const { + // Encode (imm, reg) as a memrix, which has the low 14-bits as the + // displacement and the next 5 bits as the register #. + assert(MI.getOperand(OpNo+1).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1)) << 14; + + const MachineOperand &MO = MI.getOperand(OpNo); + if (MO.isImm()) + return ((getMachineOpValue(MI, MO) >> 2) & 0x3FFF) | RegBits; + + MCE.addRelocation(GetRelocation(MO, PPC::reloc_absolute_low_ix)); + return RegBits; +} + + +unsigned PPCCodeEmitter::getTLSRegEncoding(const MachineInstr &MI, + unsigned OpNo) const { + llvm_unreachable("TLS not supported on the old JIT."); + return 0; +} + +unsigned PPCCodeEmitter::getTLSCallEncoding(const MachineInstr &MI, + unsigned OpNo) const { + llvm_unreachable("TLS not supported on the old JIT."); + return 0; +} + +unsigned PPCCodeEmitter::getMachineOpValue(const MachineInstr &MI, + const MachineOperand &MO) const { + + if (MO.isReg()) { + // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand. + // The GPR operand should come through here though. + assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 && + MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) || + MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7); + return TM.getRegisterInfo()->getEncodingValue(MO.getReg()); + } + + assert(MO.isImm() && + "Relocation required in an instruction that we cannot encode!"); + return MO.getImm(); +} +#include "PPCGenCodeEmitter.inc"