[llvm-commits] CVS: llvm/lib/ExecutionEngine/JIT/JIT.cpp JITEmitter.cpp
Andrew Lenharth
alenhar2 at cs.uiuc.edu
Thu Jul 28 05:44:25 PDT 2005
Changes in directory llvm/lib/ExecutionEngine/JIT:
JIT.cpp updated: 1.57 -> 1.58
JITEmitter.cpp updated: 1.72 -> 1.73
---
Log message:
Like constants, globals on some platforms are GOT relative. This means they have to be allocated
near the GOT, which new doesn't do. So break out the allocate into a new function.
Also move GOT index handling into JITResolver. This lets it update the mapping when a Lazy
function is JITed. It doesn't managed the table, just the mapping. Note that this is
still non-ideal, as any function that takes a function address should also take a GOT
index, but that is a lot of changes. The relocation resolve process updates any GOT entry
it sees is out of date.
---
Diffs of the changes: (+78 -14)
JIT.cpp | 3 +
JITEmitter.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 78 insertions(+), 14 deletions(-)
Index: llvm/lib/ExecutionEngine/JIT/JIT.cpp
diff -u llvm/lib/ExecutionEngine/JIT/JIT.cpp:1.57 llvm/lib/ExecutionEngine/JIT/JIT.cpp:1.58
--- llvm/lib/ExecutionEngine/JIT/JIT.cpp:1.57 Wed Jul 27 01:12:33 2005
+++ llvm/lib/ExecutionEngine/JIT/JIT.cpp Thu Jul 28 07:44:13 2005
@@ -294,7 +294,8 @@
// actually initialize the global after current function has finished
// compilation.
uint64_t S = getTargetData().getTypeSize(GV->getType()->getElementType());
- Ptr = new char[(size_t)S];
+ unsigned char A = getTargetData().getTypeAlignment(GV->getType()->getElementType());
+ Ptr = MCE->allocateGlobal(S, A);
state.getPendingGlobals(locked).push_back(GV);
}
addGlobalMapping(GV, Ptr);
Index: llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp
diff -u llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp:1.72 llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp:1.73
--- llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp:1.72 Wed Jul 27 01:12:33 2005
+++ llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp Thu Jul 28 07:44:13 2005
@@ -60,6 +60,8 @@
inline unsigned char *allocateStub(unsigned StubSize);
inline unsigned char *allocateConstant(unsigned ConstantSize,
unsigned Alignment);
+ inline unsigned char* allocateGlobal(unsigned Size,
+ unsigned Alignment);
inline unsigned char *startFunctionBody();
inline void endFunctionBody(unsigned char *FunctionEnd);
inline unsigned char* getGOTBase() const;
@@ -115,6 +117,21 @@
return CurConstantPtr;
}
+unsigned char *JITMemoryManager::allocateGlobal(unsigned Size,
+ unsigned Alignment) {
+ // For now, intersperse them with Constants
+ // Reserve space and align pointer.
+ CurConstantPtr -= Size;
+ CurConstantPtr =
+ (unsigned char *)((intptr_t)CurConstantPtr & ~((intptr_t)Alignment - 1));
+
+ if (CurConstantPtr < ConstantPool) {
+ std::cerr << "JIT ran out of memory for Globals!\n";
+ abort();
+ }
+ return CurConstantPtr;
+}
+
unsigned char *JITMemoryManager::startFunctionBody() {
// Round up to an even multiple of 8 bytes, this should eventually be target
// specific.
@@ -175,8 +192,13 @@
/// ExternalFnToStubMap - This is the equivalent of FunctionToStubMap for
/// external functions.
std::map<void*, void*> ExternalFnToStubMap;
+
+ //map addresses to indexes in the GOT
+ std::map<void*, unsigned> revGOTMap;
+ unsigned nextGOTIndex;
+
public:
- JITResolver(MachineCodeEmitter &mce) : MCE(mce) {
+ JITResolver(MachineCodeEmitter &mce) : MCE(mce), nextGOTIndex(0) {
LazyResolverFn =
TheJIT->getJITInfo().getLazyResolverFunction(JITCompilerFn);
}
@@ -199,6 +221,11 @@
return (void*)LazyResolverFn;
}
+ /// getGOTIndexForAddress - Return a new or existing index in the GOT for
+ /// and address. This function only manages slots, it does not manage the
+ /// contents of the slots or the memory associated with the GOT.
+ unsigned getGOTIndexForAddr(void* addr);
+
/// JITCompilerFn - This function is called to resolve a stub to a compiled
/// address. If the LLVM Function corresponding to the stub has not yet
/// been compiled, this function compiles it first.
@@ -261,6 +288,17 @@
return Stub;
}
+unsigned JITResolver::getGOTIndexForAddr(void* addr) {
+ unsigned idx = revGOTMap[addr];
+ if (!idx) {
+ idx = ++nextGOTIndex;
+ revGOTMap[addr] = idx;
+ DEBUG(std::cerr << "Adding GOT entry " << idx
+ << " for addr " << addr << "\n");
+ // ((void**)MemMgr.getGOTBase())[idx] = addr;
+ }
+ return idx;
+}
/// JITCompilerFn - This function is called when a lazy compilation stub has
/// been entered. It looks up which function this stub corresponds to, compiles
@@ -294,6 +332,15 @@
JR.state.getFunctionToStubMap(locked).erase(F);
// FIXME: We could rewrite all references to this stub if we knew them.
+
+ // What we will do is set the compiled function address to map to the
+ // same GOT entry as the stub so that later clients may update the GOT
+ // 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];
+
return Result;
}
@@ -340,8 +387,7 @@
public:
JITEmitter(JIT &jit)
- :MemMgr(jit.getJITInfo().needsGOT()),
- nextGOTIndex(0)
+ :MemMgr(jit.getJITInfo().needsGOT())
{
TheJIT = &jit;
DEBUG(std::cerr <<
@@ -365,11 +411,10 @@
virtual uint64_t getCurrentPCValue();
virtual uint64_t getCurrentPCOffset();
virtual uint64_t getConstantPoolEntryAddress(unsigned Entry);
+ virtual unsigned char* allocateGlobal(unsigned size, unsigned alignment);
private:
void *getPointerToGlobal(GlobalValue *GV, void *Reference, bool NoNeedStub);
- unsigned nextGOTIndex;
- std::map<void*, unsigned> revGOTMap;
};
}
@@ -441,14 +486,17 @@
MR.setResultPointer(ResultPtr);
- // if we are managing the got, check to see if this pointer has all ready
- // been allocated a GOT entry. If not, give it the next one.
- if (MemMgr.isManagingGOT()) {
- if (!revGOTMap[ResultPtr])
- revGOTMap[ResultPtr] = ++nextGOTIndex;
- ((void**)MemMgr.getGOTBase())[revGOTMap[ResultPtr]] = ResultPtr;
- if(MR.isGOTRelative())
- MR.setGOTIndex(revGOTMap[ResultPtr]);
+ // if we are managing the GOT and the relocation wants an index,
+ // give it one
+ if (MemMgr.isManagingGOT() && !MR.isConstantPoolIndex() &&
+ MR.isGOTRelative()) {
+ unsigned idx = getJITResolver(this).getGOTIndexForAddr(ResultPtr);
+ MR.setGOTIndex(idx);
+ if (((void**)MemMgr.getGOTBase())[idx] != ResultPtr) {
+ DEBUG(std::cerr << "GOT was out of date for " << ResultPtr
+ << " pointing at " << ((void**)MemMgr.getGOTBase())[idx] << "\n");
+ ((void**)MemMgr.getGOTBase())[idx] = ResultPtr;
+ }
}
}
@@ -456,6 +504,16 @@
Relocations.size(), MemMgr.getGOTBase());
}
+ //Update the GOT entry for F to point to the new code.
+ if(MemMgr.isManagingGOT()) {
+ unsigned idx = getJITResolver(this).getGOTIndexForAddr((void*)CurBlock);
+ if (((void**)MemMgr.getGOTBase())[idx] != (void*)CurBlock) {
+ DEBUG(std::cerr << "GOT was out of date for " << (void*)CurBlock
+ << " pointing at " << ((void**)MemMgr.getGOTBase())[idx] << "\n");
+ ((void**)MemMgr.getGOTBase())[idx] = (void*)CurBlock;
+ }
+ }
+
DEBUG(std::cerr << "JIT: Finished CodeGen of [" << (void*)CurBlock
<< "] Function: " << F.getFunction()->getName()
<< ": " << CurByte-CurBlock << " bytes of text, "
@@ -516,6 +574,11 @@
return (intptr_t)ConstantPoolAddresses[ConstantNum];
}
+unsigned char* JITEmitter::allocateGlobal(unsigned size, unsigned alignment)
+{
+ return MemMgr.allocateGlobal(size, alignment);
+}
+
// getCurrentPCValue - This returns the address that the next emitted byte
// will be output to.
//
More information about the llvm-commits
mailing list