X86 PIC JIT support fixes: encoding bugs, add lazy pointer stubs support.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45575 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index beeca3b..aa572a4 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -52,6 +52,10 @@
     /// corresponds to.
     std::map<void*, Function*> StubToFunctionMap;
 
+    /// GlobalToLazyPtrMap - Keep track of the lazy pointer created for a
+    /// particular GlobalVariable so that we can reuse them if necessary.
+    std::map<GlobalValue*, void*> GlobalToLazyPtrMap;
+
   public:
     std::map<Function*, void*>& getFunctionToStubMap(const MutexGuard& locked) {
       assert(locked.holds(TheJIT->lock));
@@ -62,6 +66,12 @@
       assert(locked.holds(TheJIT->lock));
       return StubToFunctionMap;
     }
+
+    std::map<GlobalValue*, void*>&
+    getGlobalToLazyPtrMap(const MutexGuard& locked) {
+      assert(locked.holds(TheJIT->lock));
+      return GlobalToLazyPtrMap;
+    }
   };
 
   /// JITResolver - Keep track of, and resolve, call sites for functions that
@@ -103,6 +113,10 @@
     /// specified address, created lazily on demand.
     void *getExternalFunctionStub(void *FnAddr);
 
+    /// getGlobalValueLazyPtr - Return a lazy pointer containing the specified
+    /// GV address.
+    void *getGlobalValueLazyPtr(GlobalValue *V, void *GVAddress);
+
     /// AddCallbackAtLocation - If the target is capable of rewriting an
     /// instruction without the use of a stub, record the location of the use so
     /// we know which function is being used at the location.
@@ -181,6 +195,25 @@
   return Stub;
 }
 
+/// getGlobalValueLazyPtr - Return a lazy pointer containing the specified
+/// GV address.
+void *JITResolver::getGlobalValueLazyPtr(GlobalValue *GV, void *GVAddress) {
+  MutexGuard locked(TheJIT->lock);
+
+  // If we already have a stub for this global variable, recycle it.
+  void *&LazyPtr = state.getGlobalToLazyPtrMap(locked)[GV];
+  if (LazyPtr) return LazyPtr;
+
+  // Otherwise, codegen a new lazy pointer.
+  LazyPtr = TheJIT->getJITInfo().emitGlobalValueLazyPtr(GVAddress,
+                                                    *TheJIT->getCodeEmitter());
+
+  DOUT << "JIT: Stub emitted at [" << LazyPtr << "] for GV '"
+       << GV->getName() << "'\n";
+
+  return LazyPtr;
+}
+
 /// getExternalFunctionStub - Return a stub for the function at the
 /// specified address, created lazily on demand.
 void *JITResolver::getExternalFunctionStub(void *FnAddr) {
@@ -361,6 +394,8 @@
     }
   private:
     void *getPointerToGlobal(GlobalValue *GV, void *Reference, bool NoNeedStub);
+    void *getPointerToGVLazyPtr(GlobalValue *V, void *Reference,
+                                bool NoNeedStub);
   };
 }
 
@@ -396,6 +431,16 @@
   return Resolver.getFunctionStub(F);
 }
 
+void *JITEmitter::getPointerToGVLazyPtr(GlobalValue *V, void *Reference,
+                                        bool DoesntNeedStub) {
+  // Make sure GV is emitted first.
+  // FIXME: For now, if the GV is an external function we force the JIT to
+  // compile it so the lazy pointer will contain the fully resolved address.
+  void *GVAddress = getPointerToGlobal(V, Reference, true);
+  return Resolver.getGlobalValueLazyPtr(V, GVAddress);
+}
+
+
 void JITEmitter::startFunction(MachineFunction &F) {
   uintptr_t ActualSize;
   BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
@@ -450,6 +495,10 @@
         ResultPtr = getPointerToGlobal(MR.getGlobalValue(),
                                        BufferBegin+MR.getMachineCodeOffset(),
                                        MR.doesntNeedStub());
+      } else if (MR.isGlobalValueLazyPtr()) {
+        ResultPtr = getPointerToGVLazyPtr(MR.getGlobalValue(),
+                                          BufferBegin+MR.getMachineCodeOffset(),
+                                          MR.doesntNeedStub());
       } else if (MR.isBasicBlock()) {
         ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock());
       } else if (MR.isConstantPoolIndex()) {