[Orc] Rename JITCompileCallbackManagerBase to JITCompileCallbackManager.
[oota-llvm.git] / include / llvm / ExecutionEngine / Orc / CompileOnDemandLayer.h
index 074d55e5034e03ef9c00187e9edf61600326a6b4..b7ee9b5937f70bf780b4f308b481735e4f17c3b6 100644 (file)
 #ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
 #define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
 
-//#include "CloneSubModule.h"
 #include "IndirectionUtils.h"
 #include "LambdaResolver.h"
+#include "LogicalDylib.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
 #include "llvm/Transforms/Utils/Cloning.h"
 #include <list>
+#include <memory>
 #include <set>
 
 #include "llvm/Support/Debug.h"
@@ -36,341 +37,118 @@ namespace orc {
 /// added to the layer below. When a stub is called it triggers the extraction
 /// of the function body from the original module. The extracted body is then
 /// compiled and executed.
-template <typename BaseLayerT, typename CompileCallbackMgrT>
+template <typename BaseLayerT,
+          typename CompileCallbackMgrT = JITCompileCallbackManager,
+          typename IndirectStubsMgrT = IndirectStubsManagerBase>
 class CompileOnDemandLayer {
 private:
 
-  // Utility class for MapValue. Only materializes declarations for global
-  // variables.
-  class GlobalDeclMaterializer : public ValueMaterializer {
+  template <typename MaterializerFtor>
+  class LambdaMaterializer final : public ValueMaterializer {
   public:
-    GlobalDeclMaterializer(Module &Dst) : Dst(Dst) {}
-    Value* materializeValueFor(Value *V) final {
-      if (auto *GV = dyn_cast<GlobalVariable>(V))
-        return cloneGlobalVariableDecl(Dst, *GV);
-      else if (auto *F = dyn_cast<Function>(V))
-        return cloneFunctionDecl(Dst, *F);
-      // Else.
-      return nullptr;
-    }
+    LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {}
+    Value *materializeDeclFor(Value *V) final { return M(V); }
+
   private:
-    Module &Dst;
+    MaterializerFtor M;
   };
 
+  template <typename MaterializerFtor>
+  LambdaMaterializer<MaterializerFtor>
+  createLambdaMaterializer(MaterializerFtor M) {
+    return LambdaMaterializer<MaterializerFtor>(std::move(M));
+  }
+
   typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
-  class UncompiledPartition;
-
-  // Logical module.
-  //
-  //   This struct contains the handles for the global values and stubs (which
-  // cover the external symbols of the original module), plus the handes for
-  // each of the extracted partitions. These handleds are used for lookup (only
-  // the globals/stubs module is searched) and memory management. The actual
-  // searching and resource management are handled by the LogicalDylib that owns
-  // the LogicalModule.
-  struct LogicalModule {
-    LogicalModule() {}
-
-    LogicalModule(LogicalModule &&Other)
-        : SrcM(std::move(Other.SrcM)),
-          GVsAndStubsHandle(std::move(Other.GVsAndStubsHandle)),
-          ImplHandles(std::move(Other.ImplHandles)) {}
-
-    std::unique_ptr<Module> SrcM;
-    BaseLayerModuleSetHandleT GVsAndStubsHandle;
-    std::vector<BaseLayerModuleSetHandleT> ImplHandles;
-  };
 
-  // Logical dylib.
-  //
-  //   This class handles symbol resolution and resource management for a set of
-  // modules that were added together as a logical dylib.
-  //
-  //   A logical dylib contains one-or-more LogicalModules plus a set of
-  // UncompiledPartitions. LogicalModules support symbol resolution and resource
-  // management for for code that has already been emitted. UncompiledPartitions
-  // represent code that has not yet been compiled.
-  class LogicalDylib {
-  private:
-    friend class UncompiledPartition;
-    typedef std::list<LogicalModule> LogicalModuleList;
+  class ModuleOwner {
   public:
-
-    typedef unsigned UncompiledPartitionID;
-    typedef typename LogicalModuleList::iterator LMHandle;
-
-    // Construct a logical dylib.
-    LogicalDylib(CompileOnDemandLayer &CODLayer) : CODLayer(CODLayer) { }
-
-    // Delete this logical dylib, release logical module resources.
-    virtual ~LogicalDylib() {
-      releaseLogicalModuleResources();
-    }
-
-    // Get a reference to the containing layer.
-    CompileOnDemandLayer& getCODLayer() { return CODLayer; }
-
-    // Get a reference to the base layer.
-    BaseLayerT& getBaseLayer() { return CODLayer.BaseLayer; }
-
-    // Start a new context for a single logical module.
-    LMHandle createLogicalModule() {
-      LogicalModules.push_back(LogicalModule());
-      return std::prev(LogicalModules.end());
-    }
-
-    // Set the global-values-and-stubs module handle for this logical module.
-    void setGVsAndStubsHandle(LMHandle LMH, BaseLayerModuleSetHandleT H) {
-      LMH->GVsAndStubsHandle = H;
-    }
-
-    // Return the global-values-and-stubs module handle for this logical module.
-    BaseLayerModuleSetHandleT getGVsAndStubsHandle(LMHandle LMH) {
-      return LMH->GVsAndStubsHandle;
-    }
-
-    //   Add a handle to a module containing lazy function bodies to the given
-    // logical module.
-    void addToLogicalModule(LMHandle LMH, BaseLayerModuleSetHandleT H) {
-      LMH->ImplHandles.push_back(H);
-    }
-
-    // Create an UncompiledPartition attached to this LogicalDylib.
-    UncompiledPartition& createUncompiledPartition(LMHandle LMH,
-                                                   std::shared_ptr<Module> SrcM);
-
-    // Take ownership of the given UncompiledPartition from the logical dylib.
-    std::unique_ptr<UncompiledPartition>
-    takeUPOwnership(UncompiledPartitionID ID);
-
-    // Look up a symbol in this context.
-    JITSymbol findSymbolInternally(LMHandle LMH, const std::string &Name) {
-      if (auto Symbol = getBaseLayer().findSymbolIn(LMH->GVsAndStubsHandle,
-                                                    Name, false))
-        return Symbol;
-
-      for (auto I = LogicalModules.begin(), E = LogicalModules.end(); I != E;
-           ++I)
-        if (I != LMH)
-          if (auto Symbol = getBaseLayer().findSymbolIn(I->GVsAndStubsHandle,
-                                                        Name, false))
-            return Symbol;
-
-      return nullptr;
-    }
-
-    JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
-      for (auto &LM : LogicalModules)
-        if (auto Symbol = getBaseLayer().findSymbolIn(LM.GVsAndStubsHandle,
-                                                      Name,
-                                                      ExportedSymbolsOnly))
-          return Symbol;
-      return nullptr;
-    }
-
-    // Find an external symbol (via the user supplied SymbolResolver).
-    virtual RuntimeDyld::SymbolInfo
-    findSymbolExternally(const std::string &Name) const = 0;
-
-  private:
-
-    void releaseLogicalModuleResources() {
-      for (auto I = LogicalModules.begin(), E = LogicalModules.end(); I != E;
-           ++I) {
-        getBaseLayer().removeModuleSet(I->GVsAndStubsHandle);
-        for (auto H : I->ImplHandles)
-          getBaseLayer().removeModuleSet(H);
-      }
-    }
-
-    CompileOnDemandLayer &CODLayer;
-    LogicalModuleList LogicalModules;
-    std::vector<std::unique_ptr<UncompiledPartition>> UncompiledPartitions;
+    ModuleOwner() = default;
+    ModuleOwner(const ModuleOwner&) = delete;
+    ModuleOwner& operator=(const ModuleOwner&) = delete;
+    virtual ~ModuleOwner() { }
+    virtual Module& getModule() const = 0;
   };
 
-  template <typename ResolverPtrT>
-  class LogicalDylibImpl : public LogicalDylib  {
+  template <typename ModulePtrT>
+  class ModuleOwnerImpl : public ModuleOwner {
   public:
-    LogicalDylibImpl(CompileOnDemandLayer &CODLayer, ResolverPtrT Resolver)
-      : LogicalDylib(CODLayer), Resolver(std::move(Resolver)) {}
-
-    RuntimeDyld::SymbolInfo
-    findSymbolExternally(const std::string &Name) const override {
-      return Resolver->findSymbol(Name);
-    }
-
+    ModuleOwnerImpl(ModulePtrT ModulePtr) : ModulePtr(std::move(ModulePtr)) {}
+    Module& getModule() const override { return *ModulePtr; }
   private:
-    ResolverPtrT Resolver;
+    ModulePtrT ModulePtr;
   };
 
-  template <typename ResolverPtrT>
-  static std::unique_ptr<LogicalDylib>
-  createLogicalDylib(CompileOnDemandLayer &CODLayer,
-                     ResolverPtrT Resolver) {
-    typedef LogicalDylibImpl<ResolverPtrT> Impl;
-    return llvm::make_unique<Impl>(CODLayer, std::move(Resolver));
+  template <typename ModulePtrT>
+  std::unique_ptr<ModuleOwner> wrapOwnership(ModulePtrT ModulePtr) {
+    return llvm::make_unique<ModuleOwnerImpl<ModulePtrT>>(std::move(ModulePtr));
   }
 
-  // Uncompiled partition.
-  //
-  // Represents one as-yet uncompiled portion of a module.
-  class UncompiledPartition {
-  public:
+  struct LogicalModuleResources {
+    std::unique_ptr<ModuleOwner> SourceModuleOwner;
+    std::set<const Function*> StubsToClone;
+    std::unique_ptr<IndirectStubsMgrT> StubsMgr;
 
-    struct PartitionEntry {
-      PartitionEntry(Function *F, TargetAddress CallbackID)
-          : F(F), CallbackID(CallbackID) {}
-      Function *F;
-      TargetAddress CallbackID;
-    };
-
-    typedef std::vector<PartitionEntry> PartitionEntryList;
-
-    // Creates an uncompiled partition with the list of functions that make up
-    // this partition.
-    UncompiledPartition(LogicalDylib &LD, typename LogicalDylib::LMHandle LMH,
-                        std::shared_ptr<Module> SrcM)
-        : LD(LD), LMH(LMH), SrcM(std::move(SrcM)), ID(~0U) {}
-
-    ~UncompiledPartition() {
-      // FIXME: When we want to support threaded lazy compilation we'll need to
-      //        lock the callback manager here.
-      auto &CCMgr = LD.getCODLayer().CompileCallbackMgr;
-      for (auto PEntry : PartitionEntries)
-        CCMgr.releaseCompileCallback(PEntry.CallbackID);
-    }
+    LogicalModuleResources() = default;
 
-    // Set the ID for this partition.
-    void setID(typename LogicalDylib::UncompiledPartitionID ID) {
-      this->ID = ID;
-    }
+    // Explicit move constructor to make MSVC happy.
+    LogicalModuleResources(LogicalModuleResources &&Other)
+        : SourceModuleOwner(std::move(Other.SourceModuleOwner)),
+          StubsToClone(std::move(Other.StubsToClone)),
+          StubsMgr(std::move(Other.StubsMgr)) {}
 
-    // Set the function set and callbacks for this partition.
-    void setPartitionEntries(PartitionEntryList PartitionEntries) {
-      this->PartitionEntries = std::move(PartitionEntries);
+    // Explicit move assignment to make MSVC happy.
+    LogicalModuleResources& operator=(LogicalModuleResources &&Other) {
+      SourceModuleOwner = std::move(Other.SourceModuleOwner);
+      StubsToClone = std::move(Other.StubsToClone);
+      StubsMgr = std::move(Other.StubsMgr);
     }
 
-    // Handle a compile callback for the function at index FnIdx.
-    TargetAddress compile(unsigned FnIdx) {
-      // Take ownership of self. This will ensure we delete the partition and
-      // free all its resources once we're done compiling.
-      std::unique_ptr<UncompiledPartition> This = LD.takeUPOwnership(ID);
-
-      // Release all other compile callbacks for this partition.
-      // We skip the callback for this function because that's the one that
-      // called us, and the callback manager will already have removed it.
-      auto &CCMgr = LD.getCODLayer().CompileCallbackMgr;
-      for (unsigned I = 0; I < PartitionEntries.size(); ++I)
-        if (I != FnIdx)
-          CCMgr.releaseCompileCallback(PartitionEntries[I].CallbackID);
-
-      // Grab the name of the function being called here.
-      Function *F = PartitionEntries[FnIdx].F;
-      std::string CalledFnName = Mangle(F->getName(), SrcM->getDataLayout());
-
-      // Extract the function and add it to the base layer.
-      auto PartitionImplH = emitPartition();
-      LD.addToLogicalModule(LMH, PartitionImplH);
-
-      // Update body pointers.
-      // FIXME: When we start supporting remote lazy jitting this will need to
-      //        be replaced with a user-supplied callback for updating the
-      //        remote pointers.
-      TargetAddress CalledAddr = 0;
-      for (unsigned I = 0; I < PartitionEntries.size(); ++I) {
-        auto F = PartitionEntries[I].F;
-        std::string FName(F->getName());
-        auto FnBodySym =
-          LD.getBaseLayer().findSymbolIn(PartitionImplH,
-                                         Mangle(FName, SrcM->getDataLayout()),
-                                         false);
-        auto FnPtrSym =
-          LD.getBaseLayer().findSymbolIn(LD.getGVsAndStubsHandle(LMH),
-                                         Mangle(FName + "$orc_addr",
-                                                SrcM->getDataLayout()),
-                                         false);
-        assert(FnBodySym && "Couldn't find function body.");
-        assert(FnPtrSym && "Couldn't find function body pointer.");
-
-        auto FnBodyAddr = FnBodySym.getAddress();
-        void *FnPtrAddr = reinterpret_cast<void*>(
-                            static_cast<uintptr_t>(FnPtrSym.getAddress()));
-
-        // If this is the function we're calling record the address so we can
-        // return it from this function.
-        if (I == FnIdx)
-          CalledAddr = FnBodyAddr;
-
-        memcpy(FnPtrAddr, &FnBodyAddr, sizeof(uintptr_t));
+    JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
+      if (Name.endswith("$stub_ptr") && !ExportedSymbolsOnly) {
+        assert(!ExportedSymbolsOnly && "Stubs are never exported");
+        return StubsMgr->findPointer(Name.drop_back(9));
       }
-
-      // Finally, clear the partition structure so we don't try to
-      // double-release the callbacks in the UncompiledPartition destructor.
-      PartitionEntries.clear();
-
-      return CalledAddr;
+      return StubsMgr->findStub(Name, ExportedSymbolsOnly);
     }
 
-  private:
+  };
 
-    BaseLayerModuleSetHandleT emitPartition() {
-      // Create the module.
-      std::string NewName(SrcM->getName());
-      for (auto &PEntry : PartitionEntries) {
-        NewName += ".";
-        NewName += PEntry.F->getName();
-      }
-      auto PM = llvm::make_unique<Module>(NewName, SrcM->getContext());
-      PM->setDataLayout(SrcM->getDataLayout());
-      ValueToValueMapTy VMap;
-      GlobalDeclMaterializer GDM(*PM);
-
-      // Create decls in the new module.
-      for (auto &PEntry : PartitionEntries)
-        cloneFunctionDecl(*PM, *PEntry.F, &VMap);
-
-      // Move the function bodies.
-      for (auto &PEntry : PartitionEntries)
-        moveFunctionBody(*PEntry.F, VMap);
-
-      // Create memory manager and symbol resolver.
-      auto MemMgr = llvm::make_unique<SectionMemoryManager>();
-      auto Resolver = createLambdaResolver(
-          [this](const std::string &Name) {
-            if (auto Symbol = LD.findSymbolInternally(LMH, Name))
-              return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
-                                             Symbol.getFlags());
-            return LD.findSymbolExternally(Name);
-          },
-          [this](const std::string &Name) {
-            if (auto Symbol = LD.findSymbolInternally(LMH, Name))
-              return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
-                                             Symbol.getFlags());
-            return RuntimeDyld::SymbolInfo(nullptr);
-          });
-      std::vector<std::unique_ptr<Module>> PartMSet;
-      PartMSet.push_back(std::move(PM));
-      return LD.getBaseLayer().addModuleSet(std::move(PartMSet),
-                                            std::move(MemMgr),
-                                            std::move(Resolver));
-    }
 
-    LogicalDylib &LD;
-    typename LogicalDylib::LMHandle LMH;
-    std::shared_ptr<Module> SrcM;
-    typename LogicalDylib::UncompiledPartitionID ID;
-    PartitionEntryList PartitionEntries;
+
+  struct LogicalDylibResources {
+    typedef std::function<RuntimeDyld::SymbolInfo(const std::string&)>
+      SymbolResolverFtor;
+    SymbolResolverFtor ExternalSymbolResolver;
   };
 
-  typedef std::list<std::unique_ptr<LogicalDylib>> LogicalDylibList;
+  typedef LogicalDylib<BaseLayerT, LogicalModuleResources,
+                       LogicalDylibResources> CODLogicalDylib;
+
+  typedef typename CODLogicalDylib::LogicalModuleHandle LogicalModuleHandle;
+  typedef std::list<CODLogicalDylib> LogicalDylibList;
 
 public:
+
   /// @brief Handle to a set of loaded modules.
   typedef typename LogicalDylibList::iterator ModuleSetHandleT;
 
+  /// @brief Module partitioning functor.
+  typedef std::function<std::set<Function*>(Function&)> PartitioningFtor;
+
+  /// @brief Builder for IndirectStubsManagers.
+  typedef std::function<std::unique_ptr<IndirectStubsMgrT>()>
+    IndirectStubsManagerBuilderT;
+
   /// @brief Construct a compile-on-demand layer instance.
-  CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr)
-      : BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr) {}
+  CompileOnDemandLayer(BaseLayerT &BaseLayer, PartitioningFtor Partition,
+                       CompileCallbackMgrT &CallbackMgr,
+                       IndirectStubsManagerBuilderT CreateIndirectStubsManager,
+                       bool CloneStubsIntoPartitions = true)
+      : BaseLayer(BaseLayer),  Partition(Partition),
+        CompileCallbackMgr(CallbackMgr),
+        CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
+        CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
 
   /// @brief Add a module to the compile-on-demand layer.
   template <typename ModuleSetT, typename MemoryManagerPtrT,
@@ -382,20 +160,17 @@ public:
     assert(MemMgr == nullptr &&
            "User supplied memory managers not supported with COD yet.");
 
-    LogicalDylibs.push_back(createLogicalDylib(*this, std::move(Resolver)));
+    LogicalDylibs.push_back(CODLogicalDylib(BaseLayer));
+    auto &LDResources = LogicalDylibs.back().getDylibResources();
+
+    LDResources.ExternalSymbolResolver =
+      [Resolver](const std::string &Name) {
+        return Resolver->findSymbol(Name);
+      };
 
     // Process each of the modules in this module set.
-    for (auto &M : Ms) {
-      std::vector<std::vector<Function*>> Partitioning;
-      for (auto &F : *M) {
-        if (F.isDeclaration())
-          continue;
-        Partitioning.emplace_back(1, &F);
-      }
-      addLogicalModule(*LogicalDylibs.back(),
-                       std::shared_ptr<Module>(std::move(M)),
-                       std::move(Partitioning));
-    }
+    for (auto &M : Ms)
+      addLogicalModule(LogicalDylibs.back(), std::move(M));
 
     return std::prev(LogicalDylibs.end());
   }
@@ -413,6 +188,10 @@ public:
   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
   /// @return A handle for the given named symbol, if it exists.
   JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
+    for (auto LDI = LogicalDylibs.begin(), LDE = LogicalDylibs.end();
+         LDI != LDE; ++LDI)
+      if (auto Symbol = findSymbolIn(LDI, Name, ExportedSymbolsOnly))
+        return Symbol;
     return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
   }
 
@@ -420,126 +199,281 @@ public:
   ///        below this one.
   JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
                          bool ExportedSymbolsOnly) {
-    return (*H)->findSymbol(Name, ExportedSymbolsOnly);
+    return H->findSymbol(Name, ExportedSymbolsOnly);
   }
 
 private:
 
-  void addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcM,
-                        std::vector<std::vector<Function*>> Partitions) {
+  template <typename ModulePtrT>
+  void addLogicalModule(CODLogicalDylib &LD, ModulePtrT SrcMPtr) {
 
     // Bump the linkage and rename any anonymous/privote members in SrcM to
     // ensure that everything will resolve properly after we partition SrcM.
-    makeAllSymbolsExternallyAccessible(*SrcM);
+    makeAllSymbolsExternallyAccessible(*SrcMPtr);
 
     // Create a logical module handle for SrcM within the logical dylib.
     auto LMH = LD.createLogicalModule();
+    auto &LMResources =  LD.getLogicalModuleResources(LMH);
+
+    LMResources.SourceModuleOwner = wrapOwnership(std::move(SrcMPtr));
+
+    Module &SrcM = LMResources.SourceModuleOwner->getModule();
+
+    // Create the GlobalValues module.
+    const DataLayout &DL = SrcM.getDataLayout();
+    auto GVsM = llvm::make_unique<Module>((SrcM.getName() + ".globals").str(),
+                                          SrcM.getContext());
+    GVsM->setDataLayout(DL);
 
-    // Create the GVs-and-stubs module.
-    auto GVsAndStubsM = llvm::make_unique<Module>(
-                          (SrcM->getName() + ".globals_and_stubs").str(),
-                          SrcM->getContext());
-    GVsAndStubsM->setDataLayout(SrcM->getDataLayout());
+    // Create function stubs.
     ValueToValueMapTy VMap;
+    {
+      typename IndirectStubsMgrT::StubInitsMap StubInits;
+      for (auto &F : SrcM) {
+        // Skip declarations.
+        if (F.isDeclaration())
+          continue;
 
-    // Process partitions and create stubs.
-    // We create the stubs before copying the global variables as we know the
-    // stubs won't refer to any globals (they only refer to their implementation
-    // pointer) so there's no ordering/value-mapping issues.
-    for (auto& Partition : Partitions) {
-      auto &UP = LD.createUncompiledPartition(LMH, SrcM);
-      typename UncompiledPartition::PartitionEntryList PartitionEntries;
-      for (auto &F : Partition) {
-        assert(!F->isDeclaration() &&
-               "Partition should only contain definitions");
-        unsigned FnIdx = PartitionEntries.size();
-        auto CCI = CompileCallbackMgr.getCompileCallback(SrcM->getContext());
-        PartitionEntries.push_back(
-          typename UncompiledPartition::PartitionEntry(F, CCI.getAddress()));
-        Function *StubF = cloneFunctionDecl(*GVsAndStubsM, *F, &VMap);
-        GlobalVariable *FnBodyPtr =
-          createImplPointer(*StubF->getType(), *StubF->getParent(),
-                            StubF->getName() + "$orc_addr",
-                            createIRTypedAddress(*StubF->getFunctionType(),
-                                                 CCI.getAddress()));
-        makeStub(*StubF, *FnBodyPtr);
-        CCI.setCompileAction([&UP, FnIdx]() { return UP.compile(FnIdx); });
+        // Record all functions defined by this module.
+        if (CloneStubsIntoPartitions)
+          LMResources.StubsToClone.insert(&F);
+
+        // Create a callback, associate it with the stub for the function,
+        // and set the compile action to compile the partition containing the
+        // function.
+        auto CCInfo = CompileCallbackMgr.getCompileCallback();
+        StubInits[mangle(F.getName(), DL)] =
+          std::make_pair(CCInfo.getAddress(),
+                         JITSymbolBase::flagsFromGlobalValue(F));
+        CCInfo.setCompileAction([this, &LD, LMH, &F]() {
+          return this->extractAndCompile(LD, LMH, F);
+        });
       }
 
-      UP.setPartitionEntries(std::move(PartitionEntries));
+      LMResources.StubsMgr = CreateIndirectStubsManager();
+      auto EC = LMResources.StubsMgr->createStubs(StubInits);
+      (void)EC;
+      // FIXME: This should be propagated back to the user. Stub creation may
+      //        fail for remote JITs.
+      assert(!EC && "Error generating stubs");
     }
 
-    // Now clone the global variable declarations.
-    GlobalDeclMaterializer GDMat(*GVsAndStubsM);
-    for (auto &GV : SrcM->globals())
-      if (!GV.isDeclaration())
-        cloneGlobalVariableDecl(*GVsAndStubsM, GV, &VMap);
-
-    // Then clone the initializers.
-    for (auto &GV : SrcM->globals())
+    // Clone global variable decls.
+    for (auto &GV : SrcM.globals())
+      if (!GV.isDeclaration() && !VMap.count(&GV))
+        cloneGlobalVariableDecl(*GVsM, GV, &VMap);
+
+    // And the aliases.
+    for (auto &A : SrcM.aliases())
+      if (!VMap.count(&A))
+        cloneGlobalAliasDecl(*GVsM, A, VMap);
+
+    // Now we need to clone the GV and alias initializers.
+
+    // Initializers may refer to functions declared (but not defined) in this
+    // module. Build a materializer to clone decls on demand.
+    auto Materializer = createLambdaMaterializer(
+      [this, &GVsM, &LMResources](Value *V) -> Value* {
+        if (auto *F = dyn_cast<Function>(V)) {
+          // Decls in the original module just get cloned.
+          if (F->isDeclaration())
+            return cloneFunctionDecl(*GVsM, *F);
+
+          // Definitions in the original module (which we have emitted stubs
+          // for at this point) get turned into a constant alias to the stub
+          // instead.
+          const DataLayout &DL = GVsM->getDataLayout();
+          std::string FName = mangle(F->getName(), DL);
+          auto StubSym = LMResources.StubsMgr->findStub(FName, false);
+          unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
+          ConstantInt *StubAddr =
+            ConstantInt::get(GVsM->getContext(),
+                             APInt(PtrBitWidth, StubSym.getAddress()));
+          Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr,
+                                                 StubAddr, F->getType());
+          return GlobalAlias::create(F->getFunctionType(),
+                                     F->getType()->getAddressSpace(),
+                                     F->getLinkage(), F->getName(),
+                                     Init, GVsM.get());
+        }
+        // else....
+        return nullptr;
+      });
+
+    // Clone the global variable initializers.
+    for (auto &GV : SrcM.globals())
       if (!GV.isDeclaration())
-        moveGlobalVariableInitializer(GV, VMap, &GDMat);
+        moveGlobalVariableInitializer(GV, VMap, &Materializer);
+
+    // Clone the global alias initializers.
+    for (auto &A : SrcM.aliases()) {
+      auto *NewA = cast<GlobalAlias>(VMap[&A]);
+      assert(NewA && "Alias not cloned?");
+      Value *Init = MapValue(A.getAliasee(), VMap, RF_None, nullptr,
+                             &Materializer);
+      NewA->setAliasee(cast<Constant>(Init));
+    }
 
-    // Build a resolver for the stubs module and add it to the base layer.
-    auto GVsAndStubsResolver = createLambdaResolver(
-        [&LD](const std::string &Name) {
-          if (auto Symbol = LD.findSymbol(Name, false))
-            return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
-                                           Symbol.getFlags());
-          return LD.findSymbolExternally(Name);
+    // Build a resolver for the globals module and add it to the base layer.
+    auto GVsResolver = createLambdaResolver(
+        [&LD, LMH](const std::string &Name) {
+          auto &LMResources = LD.getLogicalModuleResources(LMH);
+          if (auto Sym = LMResources.StubsMgr->findStub(Name, false))
+            return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
+          return LD.getDylibResources().ExternalSymbolResolver(Name);
         },
-        [&LD](const std::string &Name) {
+        [](const std::string &Name) {
           return RuntimeDyld::SymbolInfo(nullptr);
         });
 
-    std::vector<std::unique_ptr<Module>> GVsAndStubsMSet;
-    GVsAndStubsMSet.push_back(std::move(GVsAndStubsM));
-    auto GVsAndStubsH =
-      BaseLayer.addModuleSet(std::move(GVsAndStubsMSet),
+    std::vector<std::unique_ptr<Module>> GVsMSet;
+    GVsMSet.push_back(std::move(GVsM));
+    auto GVsH =
+      BaseLayer.addModuleSet(std::move(GVsMSet),
                              llvm::make_unique<SectionMemoryManager>(),
-                             std::move(GVsAndStubsResolver));
-    LD.setGVsAndStubsHandle(LMH, GVsAndStubsH);
+                             std::move(GVsResolver));
+    LD.addToLogicalModule(LMH, GVsH);
   }
 
-  static std::string Mangle(StringRef Name, const DataLayout &DL) {
-    Mangler M(&DL);
+  static std::string mangle(StringRef Name, const DataLayout &DL) {
     std::string MangledName;
     {
       raw_string_ostream MangledNameStream(MangledName);
-      M.getNameWithPrefix(MangledNameStream, Name);
+      Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
     }
     return MangledName;
   }
 
+  TargetAddress extractAndCompile(CODLogicalDylib &LD,
+                                  LogicalModuleHandle LMH,
+                                  Function &F) {
+    auto &LMResources = LD.getLogicalModuleResources(LMH);
+    Module &SrcM = LMResources.SourceModuleOwner->getModule();
+
+    // If F is a declaration we must already have compiled it.
+    if (F.isDeclaration())
+      return 0;
+
+    // Grab the name of the function being called here.
+    std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout());
+
+    auto Part = Partition(F);
+    auto PartH = emitPartition(LD, LMH, Part);
+
+    TargetAddress CalledAddr = 0;
+    for (auto *SubF : Part) {
+      std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
+      auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false);
+      assert(FnBodySym && "Couldn't find function body.");
+
+      TargetAddress FnBodyAddr = FnBodySym.getAddress();
+
+      // If this is the function we're calling record the address so we can
+      // return it from this function.
+      if (SubF == &F)
+        CalledAddr = FnBodyAddr;
+
+      // Update the function body pointer for the stub.
+      if (auto EC = LMResources.StubsMgr->updatePointer(FnName, FnBodyAddr))
+        return 0;
+    }
+
+    return CalledAddr;
+  }
+
+  template <typename PartitionT>
+  BaseLayerModuleSetHandleT emitPartition(CODLogicalDylib &LD,
+                                          LogicalModuleHandle LMH,
+                                          const PartitionT &Part) {
+    auto &LMResources = LD.getLogicalModuleResources(LMH);
+    Module &SrcM = LMResources.SourceModuleOwner->getModule();
+
+    // Create the module.
+    std::string NewName = SrcM.getName();
+    for (auto *F : Part) {
+      NewName += ".";
+      NewName += F->getName();
+    }
+
+    auto M = llvm::make_unique<Module>(NewName, SrcM.getContext());
+    M->setDataLayout(SrcM.getDataLayout());
+    ValueToValueMapTy VMap;
+
+    auto Materializer = createLambdaMaterializer([this, &LMResources, &M,
+                                                  &VMap](Value *V) -> Value * {
+      if (auto *GV = dyn_cast<GlobalVariable>(V))
+        return cloneGlobalVariableDecl(*M, *GV);
+
+      if (auto *F = dyn_cast<Function>(V)) {
+        // Check whether we want to clone an available_externally definition.
+        if (!LMResources.StubsToClone.count(F))
+          return cloneFunctionDecl(*M, *F);
+
+        // Ok - we want an inlinable stub. For that to work we need a decl
+        // for the stub pointer.
+        auto *StubPtr = createImplPointer(*F->getType(), *M,
+                                          F->getName() + "$stub_ptr", nullptr);
+        auto *ClonedF = cloneFunctionDecl(*M, *F);
+        makeStub(*ClonedF, *StubPtr);
+        ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage);
+        ClonedF->addFnAttr(Attribute::AlwaysInline);
+        return ClonedF;
+      }
+
+      if (auto *A = dyn_cast<GlobalAlias>(V)) {
+        auto *Ty = A->getValueType();
+        if (Ty->isFunctionTy())
+          return Function::Create(cast<FunctionType>(Ty),
+                                  GlobalValue::ExternalLinkage, A->getName(),
+                                  M.get());
+
+        return new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage,
+                                  nullptr, A->getName(), nullptr,
+                                  GlobalValue::NotThreadLocal,
+                                  A->getType()->getAddressSpace());
+      }
+
+      return nullptr;
+    });
+
+    // Create decls in the new module.
+    for (auto *F : Part)
+      cloneFunctionDecl(*M, *F, &VMap);
+
+    // Move the function bodies.
+    for (auto *F : Part)
+      moveFunctionBody(*F, VMap, &Materializer);
+
+    // Create memory manager and symbol resolver.
+    auto MemMgr = llvm::make_unique<SectionMemoryManager>();
+    auto Resolver = createLambdaResolver(
+        [this, &LD, LMH](const std::string &Name) {
+          if (auto Symbol = LD.findSymbolInternally(LMH, Name))
+            return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
+                                           Symbol.getFlags());
+          return LD.getDylibResources().ExternalSymbolResolver(Name);
+        },
+        [this, &LD, LMH](const std::string &Name) {
+          if (auto Symbol = LD.findSymbolInternally(LMH, Name))
+            return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
+                                           Symbol.getFlags());
+          return RuntimeDyld::SymbolInfo(nullptr);
+        });
+    std::vector<std::unique_ptr<Module>> PartMSet;
+    PartMSet.push_back(std::move(M));
+    return BaseLayer.addModuleSet(std::move(PartMSet), std::move(MemMgr),
+                                  std::move(Resolver));
+  }
+
   BaseLayerT &BaseLayer;
+  PartitioningFtor Partition;
   CompileCallbackMgrT &CompileCallbackMgr;
+  IndirectStubsManagerBuilderT CreateIndirectStubsManager;
+
   LogicalDylibList LogicalDylibs;
+  bool CloneStubsIntoPartitions;
 };
 
-template <typename BaseLayerT, typename CompileCallbackMgrT>
-typename CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::
-           UncompiledPartition&
-CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::LogicalDylib::
-  createUncompiledPartition(LMHandle LMH, std::shared_ptr<Module> SrcM) {
-  UncompiledPartitions.push_back(
-      llvm::make_unique<UncompiledPartition>(*this, LMH, std::move(SrcM)));
-  UncompiledPartitions.back()->setID(UncompiledPartitions.size() - 1);
-  return *UncompiledPartitions.back();
-}
-
-template <typename BaseLayerT, typename CompileCallbackMgrT>
-std::unique_ptr<typename CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::
-                  UncompiledPartition>
-CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::LogicalDylib::
-  takeUPOwnership(UncompiledPartitionID ID) {
-
-  std::swap(UncompiledPartitions[ID], UncompiledPartitions.back());
-  UncompiledPartitions[ID]->setID(ID);
-  auto UP = std::move(UncompiledPartitions.back());
-  UncompiledPartitions.pop_back();
-  return UP;
-}
-
 } // End namespace orc.
 } // End namespace llvm.