From f86aaa8eb7e4f0aae1dcc862d835458b567d8d3b Mon Sep 17 00:00:00 2001 From: Misha Brukman Date: Mon, 2 Jun 2003 04:12:39 +0000 Subject: [PATCH] Merged in tools/lli/JIT/SparcEmitter.cpp, coupled with the JITResolver taken from lib/Target/X86/X86CodeEmitter.cpp . git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@6530 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SparcV9/SparcV9CodeEmitter.cpp | 267 ++++++++++++++++++++-- lib/Target/SparcV9/SparcV9CodeEmitter.h | 27 ++- 2 files changed, 275 insertions(+), 19 deletions(-) diff --git a/lib/Target/SparcV9/SparcV9CodeEmitter.cpp b/lib/Target/SparcV9/SparcV9CodeEmitter.cpp index 19ac1f9cf0f..6385a278275 100644 --- a/lib/Target/SparcV9/SparcV9CodeEmitter.cpp +++ b/lib/Target/SparcV9/SparcV9CodeEmitter.cpp @@ -3,28 +3,132 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" #include "llvm/PassManager.h" #include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/CodeGen/MachineFunctionInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetData.h" +#include "Support/hash_set" #include "SparcInternals.h" #include "SparcV9CodeEmitter.h" -MachineCodeEmitter * SparcV9CodeEmitter::MCE = 0; -TargetMachine * SparcV9CodeEmitter::TM = 0; - bool UltraSparc::addPassesToEmitMachineCode(PassManager &PM, MachineCodeEmitter &MCE) { //PM.add(new SparcV9CodeEmitter(MCE)); //MachineCodeEmitter *M = MachineCodeEmitter::createDebugMachineCodeEmitter(); - MachineCodeEmitter *M = - MachineCodeEmitter::createFilePrinterMachineCodeEmitter(MCE); + MachineCodeEmitter *M = MachineCodeEmitter::createFilePrinterEmitter(MCE); PM.add(new SparcV9CodeEmitter(this, *M)); PM.add(createMachineCodeDestructionPass()); // Free stuff no longer needed return false; } +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; + 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); + }; + + JITResolver *TheJITResolver; +} + +/// 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; +} + +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); +} + +unsigned JITResolver::getLazyResolver(Function *F) { + std::map::iterator I = LazyResolverMap.lower_bound(F); + if (I != LazyResolverMap.end() && I->first == F) return I->second; + +//std::cerr << "Getting lazy resolver for : " << ((Value*)F)->getName() << "\n"; + + unsigned Stub = emitStubForFunction(F); + LazyResolverMap.insert(I, std::make_pair(F, Stub)); + return Stub; +} + +void JITResolver::CompilationCallback() { + uint64_t *StackPtr = (uint64_t*)__builtin_frame_address(0); + uint64_t RetAddr = (uint64_t)(intptr_t)__builtin_return_address(0); + +#if 0 + std::cerr << "In callback! Addr=0x" << std::hex << RetAddr + << " SP=0x" << (unsigned)StackPtr << std::dec + << ": Resolving call to function: " + << TheVM->getFunctionReferencedName((void*)RetAddr) << "\n"; +#endif + + std::cerr << "Sparc's JIT Resolver not implemented!\n"; + abort(); + +#if 0 + unsigned NewVal = TheJITResolver->resolveFunctionReference((void*)RetAddr); + + // Rewrite the call target... so that we don't fault every time we execute + // the call. + *(unsigned*)RetAddr = NewVal; + + // Change the return address to reexecute the call instruction... + StackPtr[1] -= 4; +#endif +} + +/// 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) { +#if 0 + MCE.startFunctionStub(*F, 6); + MCE.emitByte(0xE8); // Call with 32 bit pc-rel destination... + + unsigned Address = addFunctionReference(MCE.getCurrentPCValue(), F); + MCE.emitWord(Address-MCE.getCurrentPCValue()-4); + + MCE.emitByte(0xCD); // Interrupt - Just a marker identifying the stub! + return (intptr_t)MCE.finishFunctionStub(*F); +#endif + std::cerr << "Sparc's JITResolver::emitStubForFunction() not implemented!\n"; + abort(); +} + + void SparcV9CodeEmitter::emitConstant(unsigned Val, unsigned Size) { // Output the constant in big endian byte order... unsigned byteVal; @@ -90,16 +194,19 @@ int64_t SparcV9CodeEmitter::getMachineOpValue(MachineInstr &MI, fakeReg = TM->getRegInfo().getClassRegNum(fakeReg, regClass); // Find the real register number for use in an instruction realReg = getRealRegNum(fakeReg, regClass); - std::cerr << "Reg[" << fakeReg << "] = " << realReg << "\n"; + std::cerr << "Reg[" << std::dec << fakeReg << "] = " << realReg << "\n"; rv = realReg; } else if (MO.isImmediate()) { rv = MO.getImmedValue(); - } else if (MO.isPCRelativeDisp()) { - std::cerr << "Saving reference to BB (PCRelDisp)\n"; - MCE->saveBBreference((BasicBlock*)MO.getVRegValue(), MI); + } else if (MO.isPCRelativeDisp()) { // this is not always a call!! (fp const) + std::cerr << "Saving reference to func (call - PCRelDisp)\n"; + rv = (int64_t) + (intptr_t)getGlobalAddress(cast(MO.getVRegValue()), + MI,true); } else if (MO.isMachineBasicBlock()) { - std::cerr << "Saving reference to BB (MBB)\n"; - MCE->saveBBreference(MO.getMachineBasicBlock()->getBasicBlock(), MI); + std::cerr << "Saving reference to MBB\n"; + BBRefs.push_back(std::make_pair(MO.getMachineBasicBlock()->getBasicBlock(), + std::make_pair((unsigned*)(intptr_t)MCE->getCurrentPCValue(),&MI))); } else if (MO.isFrameIndex()) { std::cerr << "ERROR: Frame index unhandled.\n"; } else if (MO.isConstantPoolIndex()) { @@ -134,19 +241,98 @@ unsigned SparcV9CodeEmitter::getValueBit(int64_t Val, unsigned bit) { return (Val & 1); } +void* SparcV9CodeEmitter::convertAddress(intptr_t Addr, bool isPCRelative) { + if (isPCRelative) { + return (void*)(Addr - (intptr_t)MCE->getCurrentPCValue()); + } else { + return (void*)Addr; + } +} + + bool SparcV9CodeEmitter::runOnMachineFunction(MachineFunction &MF) { + std::cerr << "Starting function " << MF.getFunction()->getName() + << ", address: " << "0x" << std::hex + << (long)MCE->getCurrentPCValue() << "\n"; + MCE->startFunction(MF); - MCE->emitConstantPool(MF.getConstantPool()); + + // FIXME: the Sparc backend does not use the ConstantPool!! + //MCE->emitConstantPool(MF.getConstantPool()); + + // Instead, the Sparc backend has its own constant pool implementation: + const hash_set &pool = MF.getInfo()->getConstantPoolValues(); + for (hash_set::const_iterator I = pool.begin(), + E = pool.end(); I != E; ++I) + { + const Constant *C = *I; + // For now we just allocate some memory on the heap, this can be + // dramatically improved. + const Type *Ty = ((Value*)C)->getType(); + void *Addr = malloc(TM->getTargetData().getTypeSize(Ty)); + //FIXME + //TheVM.InitializeMemory(C, Addr); + std::cerr << "Adding ConstantMap[" << C << "]=" << std::dec << Addr << "\n"; + ConstantMap[C] = Addr; + } + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) emitBasicBlock(*I); MCE->finishFunction(MF); + + std::cerr << "Finishing function " << MF.getFunction()->getName() << "\n"; + ConstantMap.clear(); + 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; + std::cerr << "Fixup @" << std::hex << Ref << " to " << Location + << " in instr: " << std::dec << *MI << "\n"; + } + + // 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; + std::cerr << "attempting to resolve BB: " << i << "\n"; + 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 + (br target * 4), so undo that arithmetic here: + // Location is the target of the branch + // Ref is the location of the instruction, and hence the PC + unsigned branchTarget = (Location - (long)Ref) >> 2; + // Save the flags. + bool loBits32=false, hiBits32=false, loBits64=false, hiBits64=false; + if (op.opLoBits32()) { loBits32=true; } + if (op.opHiBits32()) { hiBits32=true; } + if (op.opLoBits64()) { loBits64=true; } + if (op.opHiBits64()) { hiBits64=true; } + MI->SetMachineOperandConst(ii, MachineOperand::MO_SignExtendedImmed, + branchTarget); + if (loBits32) { MI->setOperandLo32(ii); } + else if (hiBits32) { MI->setOperandHi32(ii); } + else if (loBits64) { MI->setOperandLo64(ii); } + else if (hiBits64) { MI->setOperandHi64(ii); } + std::cerr << "Rewrote BB ref: "; + unsigned fixedInstr = SparcV9CodeEmitter::getBinaryCodeForInstr(*MI); + *Ref = fixedInstr; + break; + } + } + } + BBRefs.clear(); + BBLocations.clear(); + return false; } void SparcV9CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) { currBB = MBB.getBasicBlock(); - MCE->startBasicBlock(MBB); + BBLocations[currBB] = MCE->getCurrentPCValue(); for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I) emitInstruction(**I); } @@ -155,4 +341,59 @@ void SparcV9CodeEmitter::emitInstruction(MachineInstr &MI) { emitConstant(getBinaryCodeForInstr(MI), 4); } +void* SparcV9CodeEmitter::getGlobalAddress(GlobalValue *V, MachineInstr &MI, + bool isPCRelative) +{ + if (isPCRelative) { // must be a call, this is a major hack! + // Try looking up the function to see if it is already compiled! + if (void *Addr = (void*)(intptr_t)MCE->getGlobalValueAddress(V)) { + intptr_t CurByte = MCE->getCurrentPCValue(); + // The real target of the call is Addr = PC + (target * 4) + // CurByte is the PC, Addr we just received + return (void*) (((long)Addr - (long)CurByte) >> 2); + } else { + if (Function *F = dyn_cast(V)) { + // Function has not yet been code generated! + TheJITResolver->addFunctionReference(MCE->getCurrentPCValue(), + cast(V)); + // Delayed resolution... + return (void*)TheJITResolver->getLazyResolver(cast(V)); + + } else if (Constant *C = ConstantPointerRef::get(V)) { + if (ConstantMap.find(C) != ConstantMap.end()) { + return ConstantMap[C]; + } else { + std::cerr << "Constant: 0x" << std::hex << &*C << std::dec + << ", " << *V << " not found in ConstantMap!\n"; + abort(); + } + +#if 0 + } else if (const GlobalVariable *G = dyn_cast(V)) { + if (G->isConstant()) { + const Constant* C = G->getInitializer(); + if (ConstantMap.find(C) != ConstantMap.end()) { + return ConstantMap[C]; + } else { + std::cerr << "Constant: " << *G << " not found in ConstantMap!\n"; + abort(); + } + } else { + std::cerr << "Variable: " << *G << " address not found!\n"; + abort(); + } +#endif + } else { + std::cerr << "Unhandled global: " << *V << "\n"; + abort(); + } + } + } else { + return convertAddress((intptr_t)MCE->getGlobalValueAddress(V), + isPCRelative); + } +} + + #include "SparcV9CodeEmitter.inc" + diff --git a/lib/Target/SparcV9/SparcV9CodeEmitter.h b/lib/Target/SparcV9/SparcV9CodeEmitter.h index 125dedb1e0e..6680a9c7fc9 100644 --- a/lib/Target/SparcV9/SparcV9CodeEmitter.h +++ b/lib/Target/SparcV9/SparcV9CodeEmitter.h @@ -9,14 +9,25 @@ #include "llvm/BasicBlock.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" #include "llvm/Target/TargetMachine.h" +class GlobalValue; +class MachineInstr; +class MachineOperand; + class SparcV9CodeEmitter : public MachineFunctionPass { - static MachineCodeEmitter *MCE; - static TargetMachine *TM; + MachineCodeEmitter *MCE; + TargetMachine *TM; BasicBlock *currBB; + // Tracks which instruction references which BasicBlock + std::vector > > BBRefs; + // Tracks where each BasicBlock starts + std::map BBLocations; + // Tracks locations of Constants which are laid out in memory (e.g. FP) + std::map ConstantMap; + public: SparcV9CodeEmitter(TargetMachine *tm, MachineCodeEmitter &M) { MCE = &M; @@ -27,17 +38,21 @@ public: /// Function generated by the CodeEmitterGenerator using TableGen /// - static unsigned getBinaryCodeForInstr(MachineInstr &MI); + unsigned getBinaryCodeForInstr(MachineInstr &MI); private: - static int64_t getMachineOpValue(MachineInstr &MI, MachineOperand &MO); - static unsigned getValueBit(int64_t Val, unsigned bit); + int64_t getMachineOpValue(MachineInstr &MI, MachineOperand &MO); + unsigned getValueBit(int64_t Val, unsigned bit); void emitConstant(unsigned Val, unsigned Size); void emitBasicBlock(MachineBasicBlock &MBB); void emitInstruction(MachineInstr &MI); + void* convertAddress(intptr_t Addr, bool isPCRelative); + void* getGlobalAddress(GlobalValue *V, MachineInstr &MI, + bool isPCRelative); + }; #endif -- 2.34.1