summaryrefslogtreecommitdiff
path: root/lib/ExecutionEngine
diff options
context:
space:
mode:
authorAndrew Lenharth <andrewl@lenharth.org>2005-07-28 12:44:13 +0000
committerAndrew Lenharth <andrewl@lenharth.org>2005-07-28 12:44:13 +0000
commit6a9746127a168306a670eaff11925605dbea9d4f (patch)
tree56a2b1ef8b41c868fc5a5f9d452ed70511c14bba /lib/ExecutionEngine
parent988b1dd608ed596879e29ad27d4aafdbf3a8f1ac (diff)
downloadllvm-6a9746127a168306a670eaff11925605dbea9d4f.tar.gz
llvm-6a9746127a168306a670eaff11925605dbea9d4f.tar.bz2
llvm-6a9746127a168306a670eaff11925605dbea9d4f.tar.xz
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22537 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r--lib/ExecutionEngine/JIT/JIT.cpp3
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp89
2 files changed, 78 insertions, 14 deletions
diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp
index 3907511750..1e879a9166 100644
--- a/lib/ExecutionEngine/JIT/JIT.cpp
+++ b/lib/ExecutionEngine/JIT/JIT.cpp
@@ -294,7 +294,8 @@ void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) {
// 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);
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index 172084a334..0d47a97e2f 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -60,6 +60,8 @@ namespace {
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 @@ unsigned char *JITMemoryManager::allocateConstant(unsigned ConstantSize,
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 @@ namespace {
/// 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 @@ namespace {
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 @@ void *JITResolver::getExternalFunctionStub(void *FnAddr) {
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 @@ void *JITResolver::JITCompilerFn(void *Stub) {
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 @@ namespace {
public:
JITEmitter(JIT &jit)
- :MemMgr(jit.getJITInfo().needsGOT()),
- nextGOTIndex(0)
+ :MemMgr(jit.getJITInfo().needsGOT())
{
TheJIT = &jit;
DEBUG(std::cerr <<
@@ -365,11 +411,10 @@ namespace {
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 @@ void JITEmitter::finishFunction(MachineFunction &F) {
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 @@ void JITEmitter::finishFunction(MachineFunction &F) {
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 @@ uint64_t JITEmitter::getConstantPoolEntryAddress(unsigned ConstantNum) {
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.
//