Add support for targets that require stubs for external functions.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21313 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index cb12642..8b5071b 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -138,6 +138,9 @@
     // to.
     std::map<void*, Function*> StubToFunctionMap;
 
+    /// ExternalFnToStubMap - This is the equivalent of FunctionToStubMap for
+    /// external functions.
+    std::map<void*, void*> ExternalFnToStubMap;
   public:
     JITResolver(MachineCodeEmitter &mce) : MCE(mce) {
       LazyResolverFn =
@@ -148,6 +151,10 @@
     /// one on demand as needed.
     void *getFunctionStub(Function *F);
 
+    /// getExternalFunctionStub - Return a stub for the function at the
+    /// specified address, created lazily on demand.
+    void *getExternalFunctionStub(void *FnAddr);
+
     /// 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.
@@ -204,6 +211,20 @@
   return Stub;
 }
 
+/// getExternalFunctionStub - Return a stub for the function at the
+/// specified address, created lazily on demand.
+void *JITResolver::getExternalFunctionStub(void *FnAddr) {
+  // If we already have a stub for this function, recycle it.
+  void *&Stub = ExternalFnToStubMap[FnAddr];
+  if (Stub) return Stub;
+
+  Stub = TheJIT->getJITInfo().emitFunctionStub(FnAddr, MCE);
+  DEBUG(std::cerr << "JIT: Stub emitted at [" << Stub
+        << "] for external function at '" << FnAddr << "'\n");
+  return Stub;
+}
+
+
 /// JITCompilerFn - This function is called when a lazy compilation stub has
 /// been entered.  It looks up which function this stub corresponds to, compiles
 /// it if necessary, then returns the resultant function pointer.
@@ -350,9 +371,13 @@
     for (unsigned i = 0, e = Relocations.size(); i != e; ++i) {
       MachineRelocation &MR = Relocations[i];
       void *ResultPtr;
-      if (MR.isString())
+      if (MR.isString()) {
         ResultPtr = TheJIT->getPointerToNamedFunction(MR.getString());
-      else
+        
+        // If the target REALLY wants a stub for this function, emit it now.
+        if (!MR.doesntNeedFunctionStub())
+          ResultPtr = getJITResolver(this).getExternalFunctionStub(ResultPtr);
+      } else
         ResultPtr = getPointerToGlobal(MR.getGlobalValue(),
                                        CurBlock+MR.getMachineCodeOffset(),
                                        MR.doesntNeedFunctionStub());