diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-02-16 09:30:23 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-02-16 09:30:23 +0000 |
commit | f25ddd991a5601d0101602c4c263a58c7af4b8a2 (patch) | |
tree | 4cfca640904d1896e25032757a61f8959c066919 /lib/ExecutionEngine/JIT/JITEmitter.cpp | |
parent | 3fd58f91dd318518f7daa4ba64c0aaf31799d89b (diff) | |
download | FreeBSD-src-f25ddd991a5601d0101602c4c263a58c7af4b8a2.zip FreeBSD-src-f25ddd991a5601d0101602c4c263a58c7af4b8a2.tar.gz |
Update LLVM to r96341.
Diffstat (limited to 'lib/ExecutionEngine/JIT/JITEmitter.cpp')
-rw-r--r-- | lib/ExecutionEngine/JIT/JITEmitter.cpp | 189 |
1 files changed, 119 insertions, 70 deletions
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index 4dc119d..57c4375 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -37,6 +37,7 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MutexGuard.h" #include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" @@ -57,13 +58,12 @@ using namespace llvm; STATISTIC(NumBytes, "Number of bytes of machine code compiled"); STATISTIC(NumRelos, "Number of relocations applied"); STATISTIC(NumRetries, "Number of retries with more memory"); -static JIT *TheJIT = 0; // A declaration may stop being a declaration once it's fully read from bitcode. // This function returns true if F is fully read and is still a declaration. static bool isNonGhostDeclaration(const Function *F) { - return F->isDeclaration() && !F->hasNotBeenReadFromBitcode(); + return F->isDeclaration() && !F->isMaterializable(); } //===----------------------------------------------------------------------===// @@ -109,9 +109,13 @@ namespace { /// particular GlobalVariable so that we can reuse them if necessary. GlobalToIndirectSymMapTy GlobalToIndirectSymMap; + /// Instance of the JIT this ResolverState serves. + JIT *TheJIT; + public: - JITResolverState() : FunctionToLazyStubMap(this), - FunctionToCallSitesMap(this) {} + JITResolverState(JIT *jit) : FunctionToLazyStubMap(this), + FunctionToCallSitesMap(this), + TheJIT(jit) {} FunctionToLazyStubMapTy& getFunctionToLazyStubMap( const MutexGuard& locked) { @@ -227,18 +231,13 @@ namespace { JITEmitter &JE; - static JITResolver *TheJITResolver; - public: - explicit JITResolver(JIT &jit, JITEmitter &je) : nextGOTIndex(0), JE(je) { - TheJIT = &jit; + /// Instance of JIT corresponding to this Resolver. + JIT *TheJIT; + public: + explicit JITResolver(JIT &jit, JITEmitter &je) + : state(&jit), nextGOTIndex(0), JE(je), TheJIT(&jit) { LazyResolverFn = jit.getJITInfo().getLazyResolverFunction(JITCompilerFn); - assert(TheJITResolver == 0 && "Multiple JIT resolvers?"); - TheJITResolver = this; - } - - ~JITResolver() { - TheJITResolver = 0; } /// getLazyFunctionStubIfAvailable - This returns a pointer to a function's @@ -273,6 +272,44 @@ namespace { static void *JITCompilerFn(void *Stub); }; + class StubToResolverMapTy { + /// Map a stub address to a specific instance of a JITResolver so that + /// lazily-compiled functions can find the right resolver to use. + /// + /// Guarded by Lock. + std::map<void*, JITResolver*> Map; + + /// Guards Map from concurrent accesses. + mutable sys::Mutex Lock; + + public: + /// Registers a Stub to be resolved by Resolver. + void RegisterStubResolver(void *Stub, JITResolver *Resolver) { + MutexGuard guard(Lock); + Map.insert(std::make_pair(Stub, Resolver)); + } + /// Unregisters the Stub when it's invalidated. + void UnregisterStubResolver(void *Stub) { + MutexGuard guard(Lock); + Map.erase(Stub); + } + /// Returns the JITResolver instance that owns the Stub. + JITResolver *getResolverFromStub(void *Stub) const { + MutexGuard guard(Lock); + // The address given to us for the stub may not be exactly right, it might + // be a little bit after the stub. As such, use upper_bound to find it. + // This is the same trick as in LookupFunctionFromCallSite from + // JITResolverState. + std::map<void*, JITResolver*>::const_iterator I = Map.upper_bound(Stub); + assert(I != Map.begin() && "This is not a known stub!"); + --I; + return I->second; + } + }; + /// This needs to be static so that a lazy call stub can access it with no + /// context except the address of the stub. + ManagedStatic<StubToResolverMapTy> StubToResolverMap; + /// JITEmitter - The JIT implementation of the MachineCodeEmitter, which is /// used to output functions to memory for execution. class JITEmitter : public JITCodeEmitter { @@ -371,10 +408,13 @@ namespace { DILocation PrevDLT; + /// Instance of the JIT + JIT *TheJIT; + public: JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM) : SizeEstimate(0), Resolver(jit, *this), MMI(0), CurFn(0), - EmittedFunctions(this), PrevDLT(NULL) { + EmittedFunctions(this), PrevDLT(NULL), TheJIT(&jit) { MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager(); if (jit.getJITInfo().needsGOT()) { MemMgr->AllocateGOT(); @@ -495,8 +535,6 @@ namespace { }; } -JITResolver *JITResolver::TheJITResolver = 0; - void CallSiteValueMapConfig::onDelete(JITResolverState *JRS, Function *F) { JRS->EraseAllCallSitesPrelocked(F); } @@ -551,6 +589,10 @@ void *JITResolver::getLazyFunctionStub(Function *F) { DEBUG(dbgs() << "JIT: Lazy stub emitted at [" << Stub << "] for function '" << F->getName() << "'\n"); + // Register this JITResolver as the one corresponding to this call site so + // JITCompilerFn will be able to find it. + StubToResolverMap->RegisterStubResolver(Stub, this); + // Finally, keep track of the stub-to-Function mapping so that the // JITCompilerFn knows which function to compile! state.AddCallSite(locked, Stub, F); @@ -637,6 +679,9 @@ void JITResolver::getRelocatableGVs(SmallVectorImpl<GlobalValue*> &GVs, GlobalValue *JITResolver::invalidateStub(void *Stub) { MutexGuard locked(TheJIT->lock); + // Remove the stub from the StubToResolverMap. + StubToResolverMap->UnregisterStubResolver(Stub); + GlobalToIndirectSymMapTy &GM = state.getGlobalToIndirectSymMap(locked); // Look up the cheap way first, to see if it's a function stub we are @@ -671,7 +716,8 @@ GlobalValue *JITResolver::invalidateStub(void *Stub) { /// been entered. It looks up which function this stub corresponds to, compiles /// it if necessary, then returns the resultant function pointer. void *JITResolver::JITCompilerFn(void *Stub) { - JITResolver &JR = *TheJITResolver; + JITResolver *JR = StubToResolverMap->getResolverFromStub(Stub); + assert(JR && "Unable to find the corresponding JITResolver to the call site"); Function* F = 0; void* ActualPtr = 0; @@ -680,24 +726,24 @@ void *JITResolver::JITCompilerFn(void *Stub) { // Only lock for getting the Function. The call getPointerToFunction made // in this function might trigger function materializing, which requires // JIT lock to be unlocked. - MutexGuard locked(TheJIT->lock); + MutexGuard locked(JR->TheJIT->lock); // The address given to us for the stub may not be exactly right, it might // be a little bit after the stub. As such, use upper_bound to find it. pair<void*, Function*> I = - JR.state.LookupFunctionFromCallSite(locked, Stub); + JR->state.LookupFunctionFromCallSite(locked, Stub); F = I.second; ActualPtr = I.first; } // If we have already code generated the function, just return the address. - void *Result = TheJIT->getPointerToGlobalIfAvailable(F); + void *Result = JR->TheJIT->getPointerToGlobalIfAvailable(F); if (!Result) { // Otherwise we don't have it, do lazy compilation now. // If lazy compilation is disabled, emit a useful error message and abort. - if (!TheJIT->isCompilingLazily()) { + if (!JR->TheJIT->isCompilingLazily()) { llvm_report_error("LLVM JIT requested to do lazy compilation of function '" + F->getName() + "' when lazy compiles are disabled!"); } @@ -706,11 +752,11 @@ void *JITResolver::JITCompilerFn(void *Stub) { << "' In stub ptr = " << Stub << " actual ptr = " << ActualPtr << "\n"); - Result = TheJIT->getPointerToFunction(F); + Result = JR->TheJIT->getPointerToFunction(F); } // Reacquire the lock to update the GOT map. - MutexGuard locked(TheJIT->lock); + MutexGuard locked(JR->TheJIT->lock); // We might like to remove the call site from the CallSiteToFunction map, but // we can't do that! Multiple threads could be stuck, waiting to acquire the @@ -725,8 +771,8 @@ void *JITResolver::JITCompilerFn(void *Stub) { // if they see it still using the stub address. // Note: this is done so the Resolver doesn't have to manage GOT memory // Do this without allocating map space if the target isn't using a GOT - if(JR.revGOTMap.find(Stub) != JR.revGOTMap.end()) - JR.revGOTMap[Result] = JR.revGOTMap[Stub]; + if(JR->revGOTMap.find(Stub) != JR->revGOTMap.end()) + JR->revGOTMap[Result] = JR->revGOTMap[Stub]; return Result; } @@ -839,7 +885,7 @@ static unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP, return Size; } -static unsigned GetJumpTableSizeInBytes(MachineJumpTableInfo *MJTI) { +static unsigned GetJumpTableSizeInBytes(MachineJumpTableInfo *MJTI, JIT *jit) { const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); if (JT.empty()) return 0; @@ -847,9 +893,7 @@ static unsigned GetJumpTableSizeInBytes(MachineJumpTableInfo *MJTI) { for (unsigned i = 0, e = JT.size(); i != e; ++i) NumEntries += JT[i].MBBs.size(); - unsigned EntrySize = MJTI->getEntrySize(); - - return NumEntries * EntrySize; + return NumEntries * MJTI->getEntrySize(*jit->getTargetData()); } static uintptr_t RoundUpToAlign(uintptr_t Size, unsigned Alignment) { @@ -1017,7 +1061,6 @@ void JITEmitter::startFunction(MachineFunction &F) { if (MemMgr->NeedsExactSize()) { DEBUG(dbgs() << "JIT: ExactSize\n"); const TargetInstrInfo* TII = F.getTarget().getInstrInfo(); - MachineJumpTableInfo *MJTI = F.getJumpTableInfo(); MachineConstantPool *MCP = F.getConstantPool(); // Ensure the constant pool/jump table info is at least 4-byte aligned. @@ -1029,11 +1072,14 @@ void JITEmitter::startFunction(MachineFunction &F) { // Add the constant pool size ActualSize += GetConstantPoolSizeInBytes(MCP, TheJIT->getTargetData()); - // Add the aligment of the jump table info - ActualSize = RoundUpToAlign(ActualSize, MJTI->getAlignment()); + if (MachineJumpTableInfo *MJTI = F.getJumpTableInfo()) { + // Add the aligment of the jump table info + ActualSize = RoundUpToAlign(ActualSize, + MJTI->getEntryAlignment(*TheJIT->getTargetData())); - // Add the jump table size - ActualSize += GetJumpTableSizeInBytes(MJTI); + // Add the jump table size + ActualSize += GetJumpTableSizeInBytes(MJTI, TheJIT); + } // Add the alignment for the function ActualSize = RoundUpToAlign(ActualSize, @@ -1062,7 +1108,8 @@ void JITEmitter::startFunction(MachineFunction &F) { emitAlignment(16); emitConstantPool(F.getConstantPool()); - initJumpTableInfo(F.getJumpTableInfo()); + if (MachineJumpTableInfo *MJTI = F.getJumpTableInfo()) + initJumpTableInfo(MJTI); // About to start emitting the machine code for the function. emitAlignment(std::max(F.getFunction()->getAlignment(), 8U)); @@ -1084,7 +1131,8 @@ bool JITEmitter::finishFunction(MachineFunction &F) { return true; } - emitJumpTableInfo(F.getJumpTableInfo()); + if (MachineJumpTableInfo *MJTI = F.getJumpTableInfo()) + emitJumpTableInfo(MJTI); // FnStart is the start of the text, not the start of the constant pool and // other per-function data. @@ -1404,13 +1452,14 @@ void JITEmitter::initJumpTableInfo(MachineJumpTableInfo *MJTI) { for (unsigned i = 0, e = JT.size(); i != e; ++i) NumEntries += JT[i].MBBs.size(); - unsigned EntrySize = MJTI->getEntrySize(); + unsigned EntrySize = MJTI->getEntrySize(*TheJIT->getTargetData()); // Just allocate space for all the jump tables now. We will fix up the actual // MBB entries in the tables after we emit the code for each block, since then // we will know the final locations of the MBBs in memory. JumpTable = MJTI; - JumpTableBase = allocateSpace(NumEntries * EntrySize, MJTI->getAlignment()); + JumpTableBase = allocateSpace(NumEntries * EntrySize, + MJTI->getEntryAlignment(*TheJIT->getTargetData())); } void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { @@ -1420,8 +1469,32 @@ void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); if (JT.empty() || JumpTableBase == 0) return; - if (TargetMachine::getRelocationModel() == Reloc::PIC_) { - assert(MJTI->getEntrySize() == 4 && "Cross JIT'ing?"); + + switch (MJTI->getEntryKind()) { + case MachineJumpTableInfo::EK_BlockAddress: { + // EK_BlockAddress - Each entry is a plain address of block, e.g.: + // .word LBB123 + assert(MJTI->getEntrySize(*TheJIT->getTargetData()) == sizeof(void*) && + "Cross JIT'ing?"); + + // For each jump table, map each target in the jump table to the address of + // an emitted MachineBasicBlock. + intptr_t *SlotPtr = (intptr_t*)JumpTableBase; + + for (unsigned i = 0, e = JT.size(); i != e; ++i) { + const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs; + // Store the address of the basic block for this jump table slot in the + // memory we allocated for the jump table in 'initJumpTableInfo' + for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) + *SlotPtr++ = getMachineBasicBlockAddress(MBBs[mi]); + } + break; + } + + case MachineJumpTableInfo::EK_Custom32: + case MachineJumpTableInfo::EK_GPRel32BlockAddress: + case MachineJumpTableInfo::EK_LabelDifference32: { + assert(MJTI->getEntrySize(*TheJIT->getTargetData()) == 4&&"Cross JIT'ing?"); // For each jump table, place the offset from the beginning of the table // to the target address. int *SlotPtr = (int*)JumpTableBase; @@ -1433,23 +1506,12 @@ void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { uintptr_t Base = (uintptr_t)SlotPtr; for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { uintptr_t MBBAddr = getMachineBasicBlockAddress(MBBs[mi]); + /// FIXME: USe EntryKind instead of magic "getPICJumpTableEntry" hook. *SlotPtr++ = TheJIT->getJITInfo().getPICJumpTableEntry(MBBAddr, Base); } } - } else { - assert(MJTI->getEntrySize() == sizeof(void*) && "Cross JIT'ing?"); - - // For each jump table, map each target in the jump table to the address of - // an emitted MachineBasicBlock. - intptr_t *SlotPtr = (intptr_t*)JumpTableBase; - - for (unsigned i = 0, e = JT.size(); i != e; ++i) { - const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs; - // Store the address of the basic block for this jump table slot in the - // memory we allocated for the jump table in 'initJumpTableInfo' - for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) - *SlotPtr++ = getMachineBasicBlockAddress(MBBs[mi]); - } + break; + } } } @@ -1505,9 +1567,9 @@ uintptr_t JITEmitter::getJumpTableEntryAddress(unsigned Index) const { const std::vector<MachineJumpTableEntry> &JT = JumpTable->getJumpTables(); assert(Index < JT.size() && "Invalid jump table index!"); - unsigned Offset = 0; - unsigned EntrySize = JumpTable->getEntrySize(); + unsigned EntrySize = JumpTable->getEntrySize(*TheJIT->getTargetData()); + unsigned Offset = 0; for (unsigned i = 0; i < Index; ++i) Offset += JT[i].MBBs.size(); @@ -1536,19 +1598,6 @@ JITCodeEmitter *JIT::createEmitter(JIT &jit, JITMemoryManager *JMM, return new JITEmitter(jit, JMM, tm); } -// getPointerToNamedFunction - This function is used as a global wrapper to -// JIT::getPointerToNamedFunction for the purpose of resolving symbols when -// bugpoint is debugging the JIT. In that scenario, we are loading an .so and -// need to resolve function(s) that are being mis-codegenerated, so we need to -// resolve their addresses at runtime, and this is the way to do it. -extern "C" { - void *getPointerToNamedFunction(const char *Name) { - if (Function *F = TheJIT->FindFunctionNamed(Name)) - return TheJIT->getPointerToFunction(F); - return TheJIT->getPointerToNamedFunction(Name); - } -} - // getPointerToFunctionOrStub - If the specified function has been // code-gen'd, return a pointer to the function. If not, compile it, or use // a stub to implement lazy compilation if available. |