OSDN Git Service

Like constants, globals on some platforms are GOT relative. This means they have...
authorAndrew Lenharth <andrewl@lenharth.org>
Thu, 28 Jul 2005 12:44:13 +0000 (12:44 +0000)
committerAndrew Lenharth <andrewl@lenharth.org>
Thu, 28 Jul 2005 12:44:13 +0000 (12:44 +0000)
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

include/llvm/CodeGen/MachineCodeEmitter.h
lib/ExecutionEngine/JIT/JIT.cpp
lib/ExecutionEngine/JIT/JITEmitter.cpp

index f3155ba..59c5b61 100644 (file)
@@ -94,6 +94,12 @@ public:
   //
   virtual uint64_t getConstantPoolEntryAddress(unsigned Index) = 0;
 
+  // allocateGlobal - Allocate some space for a global variable.  This is
+  // used by the JIT to allocate space in the global variable region.
+  virtual unsigned char* allocateGlobal(unsigned size, unsigned alignment) {
+    return new unsigned char[(size_t)size];
+  }
+
   /// createDebugEmitter - Return a dynamically allocated machine
   /// code emitter, which just prints the opcodes and fields out the cout.  This
   /// can be used for debugging users of the MachineCodeEmitter interface.
index 3907511..1e879a9 100644 (file)
@@ -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);
index 172084a..0d47a97 100644 (file)
@@ -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.
 //