From e2ada0413ed352058c330f30b64c4c56877f0b69 Mon Sep 17 00:00:00 2001 From: Misha Brukman Date: Tue, 19 Oct 2004 19:49:42 +0000 Subject: [PATCH] * Add baseline structural JIT code, but disable the JIT to allow llvm-gcc builds - Support added for functions, basic blocks, constant pool, constants, registers, and some basic support for globals, all untested * Turn assert()s into abort()s so that unimplemented functions fail in release llvm-svn: 17143 --- .../lib/Target/SparcV8/SparcV8CodeEmitter.cpp | 183 +++++++++++++++++- 1 file changed, 175 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/SparcV8/SparcV8CodeEmitter.cpp b/llvm/lib/Target/SparcV8/SparcV8CodeEmitter.cpp index e1c1c0690017..2e43c43cbbdf 100644 --- a/llvm/lib/Target/SparcV8/SparcV8CodeEmitter.cpp +++ b/llvm/lib/Target/SparcV8/SparcV8CodeEmitter.cpp @@ -10,10 +10,64 @@ // //===----------------------------------------------------------------------===// +#include "SparcV8.h" #include "SparcV8TargetMachine.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +#include +#include +#include namespace llvm { +namespace { + class SparcV8CodeEmitter : public MachineFunctionPass { + TargetMachine &TM; + MachineCodeEmitter &MCE; + + /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr + /// + int64_t getMachineOpValue(MachineInstr &MI, MachineOperand &MO); + + // Tracks which instruction references which BasicBlock + std::vector > > BBRefs; + // Tracks where each BasicBlock starts + std::map BBLocations; + + public: + SparcV8CodeEmitter(TargetMachine &T, MachineCodeEmitter &M) + : TM(T), MCE(M) {} + + const char *getPassName() const { return "SparcV8 Machine Code Emitter"; } + + /// runOnMachineFunction - emits the given MachineFunction to memory + /// + bool runOnMachineFunction(MachineFunction &MF); + + /// 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; } + + /// getBinaryCodeForInstr - This function, generated by the + /// CodeEmitterGenerator using TableGen, produces the binary encoding for + /// machine instructions. + /// + unsigned getBinaryCodeForInstr(MachineInstr &MI); + }; +} + /// 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 @@ -22,22 +76,135 @@ namespace llvm { /// bool SparcV8TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM, MachineCodeEmitter &MCE) { + // Keep as `true' until this is a functional JIT to allow llvm-gcc to build return true; - // It should go something like this: - // PM.add(new Emitter(MCE)); // Machine code emitter pass for SparcV8 - // Delete machine code for this function after emitting it: - // PM.add(createMachineCodeDeleter()); + + // Machine code emitter pass for SparcV8 + PM.add(new SparcV8CodeEmitter(*this, MCE)); + // Delete machine code for this function after emitting it + PM.add(createMachineCodeDeleter()); + return false; +} + +bool SparcV8CodeEmitter::runOnMachineFunction(MachineFunction &MF) { + MCE.startFunction(MF); + MCE.emitConstantPool(MF.getConstantPool()); + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + emitBasicBlock(*I); + 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 = SparcV8CodeEmitter::getBinaryCodeForInstr(*MI); + MCE.emitWordAt(fixedInstr, Ref); + break; + } + } + } + BBRefs.clear(); + BBLocations.clear(); + + return false; +} + +void SparcV8CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) { + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I) + emitWord(getBinaryCodeForInstr(*I)); +} + +int64_t SparcV8CodeEmitter::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.isPCRelativeDisp()) { + std::cerr << "SparcV8CodeEmitter: PC-relative disp unhandled\n"; + abort(); + } else if (MO.isRegister()) { + rv = MO.getReg(); + } else if (MO.isImmediate()) { + rv = MO.getImmedValue(); + } else if (MO.isGlobalAddress()) { + GlobalValue *GV = MO.getGlobal(); + if (MO.isPCRelative()) { // Global variable reference + if (void *Addr = (void*)(intptr_t)MCE.getGlobalValueAddress(GV)) { + intptr_t CurrPC = MCE.getCurrentPCValue(); + return (int64_t) (((long)Addr - (long)CurrPC) >> 2); + } else { + std::cerr << "Unhandled pc-relative global value: " << GV << "\n"; + abort(); + } + } else { // Function reference + if (!(rv = (intptr_t)MCE.getGlobalValueAddress(GV))) { + if (Function *F = dyn_cast(GV)) { + std::cerr << "SparcV8CodeEmitter error: no lazy fn resolution yet!\n"; + abort(); +#if 0 + // Function has not yet been code generated! + TheJITResolver->addFunctionReference(MCE.getCurrentPCValue(), + cast(GV)); + // Delayed resolution... + return (intptr_t)TheJITResolver->getLazyResolver(cast(GV)); +#endif + } else { + std::cerr << "Unhandled global value: " << GV << "\n"; + abort(); + } + } + } + } 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.isExternalSymbol()) { + } else if (MO.isConstantPoolIndex()) { + unsigned index = MO.getConstantPoolIndex(); + rv = MCE.getConstantPoolEntryAddress(index); + } else if (MO.isFrameIndex()) { + std::cerr << "SparcV8CodeEmitter: error: Frame index unhandled!\n"; + abort(); + } else { + std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n"; + abort(); + } + + // Adjust for special meaning of operands in some instructions + unsigned Opcode = MI.getOpcode(); + if (Opcode == V8::SETHIi && !MO.isRegister() && !MO.isImmediate()) { + rv &= 0x03ff; + } else if (Opcode == V8::ORri &&!MO.isRegister() &&!MO.isImmediate()) { + rv = (rv >> 10) & 0x03fffff; + } + + return rv; } void *SparcV8JITInfo::getJITStubForFunction(Function *F, MachineCodeEmitter &MCE) { - assert (0 && "SparcV8JITInfo::getJITStubForFunction not implemented"); + std::cerr << "SparcV8JITInfo::getJITStubForFunction not implemented!\n"; + abort(); return 0; } -void SparcV8JITInfo::replaceMachineCodeForFunction (void *Old, void *New) { - assert (0 && "SparcV8JITInfo::replaceMachineCodeForFunction not implemented"); +void SparcV8JITInfo::replaceMachineCodeForFunction(void *Old, void *New) { + std::cerr << "SparcV8JITInfo::replaceMachineCodeForFunction not implemented!"; + abort(); } -} // end llvm namespace +#include "SparcV8GenCodeEmitter.inc" +} // end llvm namespace