[llvm] r239561 - [Orc] Make partition identification in the CompileOnDemand layer lazy.

Lang Hames lhames at gmail.com
Fri Jun 12 15:28:32 PDT 2015


Hi Dave,

Thanks for the review. Some suggestions applied in r239642, comments inline
below.

- Lang.

On Thu, Jun 11, 2015 at 3:18 PM, David Blaikie <dblaikie at gmail.com> wrote:

>
>
> On Thu, Jun 11, 2015 at 2:45 PM, Lang Hames <lhames at gmail.com> wrote:
>
>> Author: lhames
>> Date: Thu Jun 11 16:45:19 2015
>> New Revision: 239561
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=239561&view=rev
>> Log:
>> [Orc] Make partition identification in the CompileOnDemand layer lazy.
>>
>> This also breaks out the logical dylib symbol resolution logic.
>>
>>
>> Added:
>>     llvm/trunk/include/llvm/ExecutionEngine/Orc/LogicalDylib.h
>> Modified:
>>     llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
>>     llvm/trunk/tools/lli/OrcLazyJIT.h
>>
>> Modified:
>> llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h?rev=239561&r1=239560&r2=239561&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
>> (original)
>> +++ llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
>> Thu Jun 11 16:45:19 2015
>> @@ -15,9 +15,9 @@
>>  #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"
>> @@ -36,7 +36,9 @@ 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,
>> +          typename PartitioningFtor =
>> +            std::function<std::set<Function*>(Function&)>>
>>
>
> I can't seem to find where/why this is a template parameter - it looks
> like it's a private implementation detail that users of this class couldn't
> change even if they wanted to? (the only place it's used is for the
> Partitioner member of the private nested struct, and the only thing that's
> initialized with is a lambda of the same type in the addModuleSet function)
>
> Are there other uses/pieces of this class I should be looking at to get
> the whole picture?
>

I plan to expose the partitioning stuff soon, but am holding off while I
consider exactly how I want the user to supply it. Passing it along with
the module set to the addModuleSet method seems like the best option, but I
want to keep that method's signature as uniform as possible across layers
to maximize opportunities for composition.

 class CompileOnDemandLayer {
>>  private:
>>
>> @@ -58,311 +60,23 @@ private:
>>    };
>>
>>    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;
>> +  struct LogicalModuleResources {
>> +    std::shared_ptr<Module> SourceModule;
>>    };
>>
>> -  // 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;
>> -  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;
>> -  };
>> -
>> -  template <typename ResolverPtrT>
>> -  class LogicalDylibImpl : public LogicalDylib  {
>> -  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);
>> -    }
>> -
>> -  private:
>> -    ResolverPtrT Resolver;
>> +  struct LogicalDylibResources {
>> +    typedef std::function<RuntimeDyld::SymbolInfo(const std::string&)>
>> +      SymbolResolverFtor;
>> +    SymbolResolverFtor ExternalSymbolResolver;
>> +    PartitioningFtor Partitioner;
>>    };
>>
>> -  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));
>> -  }
>> +  typedef LogicalDylib<BaseLayerT, LogicalModuleResources,
>> +                       LogicalDylibResources> CODLogicalDylib;
>>
>> -  // Uncompiled partition.
>> -  //
>> -  // Represents one as-yet uncompiled portion of a module.
>> -  class UncompiledPartition {
>> -  public:
>> -
>> -    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);
>> -    }
>> -
>> -    // Set the ID for this partition.
>> -    void setID(typename LogicalDylib::UncompiledPartitionID ID) {
>> -      this->ID = ID;
>> -    }
>> -
>> -    // Set the function set and callbacks for this partition.
>> -    void setPartitionEntries(PartitionEntryList PartitionEntries) {
>> -      this->PartitionEntries = std::move(PartitionEntries);
>> -    }
>> -
>> -    // 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));
>> -      }
>> -
>> -      // Finally, clear the partition structure so we don't try to
>> -      // double-release the callbacks in the UncompiledPartition
>> destructor.
>> -      PartitionEntries.clear();
>> -
>> -      return CalledAddr;
>> -    }
>> -
>> -  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;
>> -  };
>> -
>> -  typedef std::list<std::unique_ptr<LogicalDylib>> LogicalDylibList;
>> +  typedef typename CODLogicalDylib::LogicalModuleHandle
>> LogicalModuleHandle;
>> +  typedef std::list<CODLogicalDylib> LogicalDylibList;
>>
>>  public:
>>    /// @brief Handle to a set of loaded modules.
>> @@ -382,20 +96,25 @@ 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 &LDLResources = LogicalDylibs.back().getDylibResources();
>> +
>> +    LDLResources.ExternalSymbolResolver =
>> +      [Resolver](const std::string &Name) {
>> +        return Resolver->findSymbol(Name);
>> +      };
>> +
>> +    LDLResources.Partitioner =
>> +      [](Function &F) {
>> +        std::set<Function*> Partition;
>> +        Partition.insert(&F);
>> +        return Partition;
>> +      };
>>
>
> Maybe run this through clang-format (might be worth just clang-formatting
> this whole patch, see if it looks better that way)? It looks like this:
>
>     LDLResources.Partitioner = [](Function &F) {
>       std::set<Function *> Partition;
>       Partition.insert(&F);
>       return Partition;
>     };
>
> Which is possibly more idiomatic.
>

Yep. I'll probably run clang-format over all the Orc headers soon - I
suspect there are a few bits of non-idiomatic formatting in there.


>>      // 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::shared_ptr<Module>(std::move(M)));
>>
>>      return std::prev(LogicalDylibs.end());
>>    }
>> @@ -420,13 +139,12 @@ 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) {
>> +  void addLogicalModule(CODLogicalDylib &LD, std::shared_ptr<Module>
>> SrcM) {
>>
>>      // Bump the linkage and rename any anonymous/privote members in SrcM
>> to
>>      // ensure that everything will resolve properly after we partition
>> SrcM.
>> @@ -434,6 +152,7 @@ private:
>>
>>      // Create a logical module handle for SrcM within the logical dylib.
>>      auto LMH = LD.createLogicalModule();
>> +    LD.getLogicalModuleResources(LMH).SourceModule = SrcM;
>>
>>      // Create the GVs-and-stubs module.
>>      auto GVsAndStubsM = llvm::make_unique<Module>(
>> @@ -442,31 +161,31 @@ private:
>>      GVsAndStubsM->setDataLayout(SrcM->getDataLayout());
>>      ValueToValueMapTy VMap;
>>
>> -    // Process partitions and create stubs.
>> +    // Process module 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);
>> });
>> -      }
>> +    for (auto &F : *SrcM) {
>>
>> -      UP.setPartitionEntries(std::move(PartitionEntries));
>> +      // Skip declarations.
>> +      if (F.isDeclaration())
>> +        continue;
>> +
>> +      // For each definition: create a callback, a stub, and a function
>> body
>> +      // pointer. Initialize the function body pointer to point at the
>> callback,
>> +      // and set the callback to compile the function body.
>> +      auto CCInfo =
>> CompileCallbackMgr.getCompileCallback(SrcM->getContext());
>> +      Function *StubF = cloneFunctionDecl(*GVsAndStubsM, F, &VMap);
>> +      GlobalVariable *FnBodyPtr =
>> +        createImplPointer(*StubF->getType(), *StubF->getParent(),
>> +                          StubF->getName() + "$orc_addr",
>> +                          createIRTypedAddress(*StubF->getFunctionType(),
>> +                                               CCInfo.getAddress()));
>> +      makeStub(*StubF, *FnBodyPtr);
>> +      CCInfo.setCompileAction(
>> +        [this, &LD, LMH, &F]() {
>> +          return extractAndCompile(LD, LMH, F);
>> +        });
>>      }
>>
>>      // Now clone the global variable declarations.
>> @@ -483,12 +202,9 @@ private:
>>      // 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);
>> +          return LD.getDylibResources().ExternalSymbolResolver(Name);
>>          },
>> -        [&LD](const std::string &Name) {
>> +        [](const std::string &Name) {
>>            return RuntimeDyld::SymbolInfo(nullptr);
>>          });
>>
>> @@ -498,7 +214,7 @@ private:
>>        BaseLayer.addModuleSet(std::move(GVsAndStubsMSet),
>>                               llvm::make_unique<SectionMemoryManager>(),
>>                               std::move(GVsAndStubsResolver));
>> -    LD.setGVsAndStubsHandle(LMH, GVsAndStubsH);
>> +    LD.addToLogicalModule(LMH, GVsAndStubsH);
>>    }
>>
>>    static std::string Mangle(StringRef Name, const DataLayout &DL) {
>> @@ -511,35 +227,101 @@ private:
>>      return MangledName;
>>    }
>>
>> +  TargetAddress extractAndCompile(CODLogicalDylib &LD,
>> +                                  LogicalModuleHandle LMH,
>> +                                  Function &F) {
>> +    Module &SrcM = *LD.getLogicalModuleResources(LMH).SourceModule;
>> +
>> +    // 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());
>> +
>> +    const auto &Partition = LD.getDylibResources().Partitioner(F);
>>
>
> Taking this by const (auto) ref is a bit confusing - what's the intent
> there? To support non-value-returning partitioning functors/functions? (&
> like the feedback above, I'm still a bit confused by what kind of
> instantiations of this class can exist/what types can be specified for the
> PartitioningFtor type)
>

That's a think-o: the partition should be taken by value. Fixed in r239642.


> +    auto PartitionH = emitPartition(LD, LMH, Partition);
>>
>
> In fact, emitPartition here requires that Partition be a  " const
> std::set<Function*> &" - so perhaps it'd be easier if Partition were just
> declared as a "std::set<Function*>" directly (no reference lifetime
> extensions of temporaries, etc)?
>

What heresy is this? You love 'auto'. ;)
I think the real problem is that I'd pinned down the return type of the
Partitioner. That has also been fixed in r239642.


> +
>> +    TargetAddress CalledAddr = 0;
>> +    for (auto *SubF : Partition) {
>> +      std::string FName(SubF->getName());
>>
>
> Prefer copy-init over direct-init?
>

Yep. This is a hangover from the previous code. Fixed in r239642.


> +      auto FnBodySym =
>> +        BaseLayer.findSymbolIn(PartitionH, Mangle(FName,
>> SrcM.getDataLayout()),
>> +                               false);
>> +      auto FnPtrSym =
>> +        BaseLayer.findSymbolIn(*LD.moduleHandlesBegin(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();
>>
>
> Not sure if these autos improve readability (I guess they're all
> JITSymbols? (FnBodySym, FnPtrSym, FnBodyAddr))
>

The first two are JITSymbols. The latter is a TargetAddress. I think the
type is implied by the method names and variable suffixes (Sym/findSymbol,
Addr/getAddress), but that's a matter of personal taste. I've actually
spelled out the TargetAddress type in r239642. JITSymbol has been left to
deduction.

+      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 (SubF == &F)
>> +        CalledAddr = FnBodyAddr;
>> +
>> +      memcpy(FnPtrAddr, &FnBodyAddr, sizeof(uintptr_t));
>> +    }
>> +
>> +    return CalledAddr;
>> +  }
>> +
>> +  BaseLayerModuleSetHandleT emitPartition(CODLogicalDylib &LD,
>> +                                          LogicalModuleHandle LMH,
>> +                                          const std::set<Function*>
>> &Partition) {
>> +    Module &SrcM = *LD.getLogicalModuleResources(LMH).SourceModule;
>> +
>> +    // Create the module.
>> +    std::string NewName(SrcM.getName());
>>
>
> Copy-init over direct-init?
>

Yep. Fixed in r239642.


> +    for (auto *F : Partition) {
>> +      NewName += ".";
>> +      NewName += F->getName();
>> +    }
>> +
>> +    auto M = llvm::make_unique<Module>(NewName, SrcM.getContext());
>> +    M->setDataLayout(SrcM.getDataLayout());
>> +    ValueToValueMapTy VMap;
>> +    GlobalDeclMaterializer GDM(*M);
>> +
>> +    // Create decls in the new module.
>> +    for (auto *F : Partition)
>> +      cloneFunctionDecl(*M, *F, &VMap);
>> +
>> +    // Move the function bodies.
>> +    for (auto *F : Partition)
>> +      moveFunctionBody(*F, VMap);
>> +
>> +    // 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;
>>    CompileCallbackMgrT &CompileCallbackMgr;
>>    LogicalDylibList LogicalDylibs;
>>  };
>>
>> -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.
>>
>>
>> Added: llvm/trunk/include/llvm/ExecutionEngine/Orc/LogicalDylib.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/LogicalDylib.h?rev=239561&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/ExecutionEngine/Orc/LogicalDylib.h (added)
>> +++ llvm/trunk/include/llvm/ExecutionEngine/Orc/LogicalDylib.h Thu Jun 11
>> 16:45:19 2015
>> @@ -0,0 +1,118 @@
>> +//===--- LogicalDylib.h - Simulates dylib-style symbol lookup ---*- C++
>> -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// Simulates symbol resolution inside a dylib.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_EXECUTIONENGINE_ORC_LOGICALDYLIB_H
>> +#define LLVM_EXECUTIONENGINE_ORC_LOGICALDYLIB_H
>> +
>> +#include "llvm/ADT/iterator.h"
>> +#include "llvm/ADT/Optional.h"
>> +
>> +namespace llvm {
>> +namespace orc {
>> +
>> +template <typename BaseLayerT,
>> +          typename LogicalModuleResources,
>> +          typename LogicalDylibResources>
>> +class LogicalDylib {
>> +public:
>> +  typedef typename BaseLayerT::ModuleSetHandleT
>> BaseLayerModuleSetHandleT;
>> +private:
>> +
>> +  typedef std::vector<BaseLayerModuleSetHandleT> BaseLayerHandleList;
>> +
>> +  struct LogicalModule {
>> +    LogicalModuleResources Resources;
>> +    BaseLayerHandleList BaseLayerHandles;
>> +  };
>> +  typedef std::vector<LogicalModule> LogicalModuleList;
>> +
>> +public:
>> +
>> +  typedef typename BaseLayerHandleList::iterator BaseLayerHandleIterator;
>> +  typedef typename LogicalModuleList::iterator LogicalModuleHandle;
>> +
>> +  LogicalDylib(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
>> +
>> +  ~LogicalDylib() {
>> +    for (auto &LM : LogicalModules)
>> +      for (auto BLH : LM.BaseLayerHandles)
>> +        BaseLayer.removeModuleSet(BLH);
>> +  }
>> +
>> +  LogicalModuleHandle createLogicalModule() {
>> +    LogicalModules.push_back(LogicalModule());
>> +    return std::prev(LogicalModules.end());
>> +  }
>> +
>> +  void addToLogicalModule(LogicalModuleHandle LMH,
>> +                          BaseLayerModuleSetHandleT BaseLayerHandle) {
>> +    LMH->BaseLayerHandles.push_back(BaseLayerHandle);
>> +  }
>> +
>> +  LogicalModuleResources& getLogicalModuleResources(LogicalModuleHandle
>> LMH) {
>> +    return LMH->Resources;
>> +  }
>> +
>> +  BaseLayerHandleIterator moduleHandlesBegin(LogicalModuleHandle LMH) {
>> +    return LMH->BaseLayerHandles.begin();
>> +  }
>> +
>> +  BaseLayerHandleIterator moduleHandlesEnd(LogicalModuleHandle LMH) {
>> +    return LMH->BaseLayerHandles.end();
>> +  }
>> +
>> +  JITSymbol findSymbolInLogicalModule(LogicalModuleHandle LMH,
>> +                                      const std::string &Name) {
>> +    for (auto BLH : LMH->BaseLayerHandles)
>> +      if (auto Symbol = BaseLayer.findSymbolIn(BLH, Name, false))
>> +        return Symbol;
>> +    return nullptr;
>> +  }
>> +
>> +  JITSymbol findSymbolInternally(LogicalModuleHandle LMH,
>> +                                 const std::string &Name) {
>> +    if (auto Symbol = findSymbolInLogicalModule(LMH, Name))
>> +      return Symbol;
>> +
>> +    for (auto LMI = LogicalModules.begin(), LME = LogicalModules.end();
>> +           LMI != LME; ++LMI) {
>> +      if (LMI != LMH)
>> +        if (auto Symbol = findSymbolInLogicalModule(LMI, Name))
>> +          return Symbol;
>> +    }
>> +
>> +    return nullptr;
>> +  }
>> +
>> +  JITSymbol findSymbol(const std::string &Name, bool
>> ExportedSymbolsOnly) {
>> +    for (auto &LM : LogicalModules)
>> +      for (auto BLH : LM.BaseLayerHandles)
>> +        if (auto Symbol =
>> +            BaseLayer.findSymbolIn(BLH, Name, ExportedSymbolsOnly))
>> +          return Symbol;
>> +    return nullptr;
>> +  }
>> +
>> +  LogicalDylibResources& getDylibResources() { return DylibResources; }
>> +
>> +protected:
>> +  BaseLayerT BaseLayer;
>> +  LogicalModuleList LogicalModules;
>> +  LogicalDylibResources DylibResources;
>> +
>> +};
>> +
>> +} // End namespace orc.
>> +} // End namespace llvm.
>> +
>> +#endif // LLVM_EXECUTIONENGINE_ORC_LOGICALDYLIB_H
>>
>> Modified: llvm/trunk/tools/lli/OrcLazyJIT.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/OrcLazyJIT.h?rev=239561&r1=239560&r2=239561&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/tools/lli/OrcLazyJIT.h (original)
>> +++ llvm/trunk/tools/lli/OrcLazyJIT.h Thu Jun 11 16:45:19 2015
>> @@ -89,22 +89,26 @@ public:
>>      //   2) Check for C++ runtime overrides.
>>      //   3) Search the host process (LLI)'s symbol table.
>>      auto Resolver =
>> -      orc::createLambdaResolver(
>> -        [this](const std::string &Name) {
>> +      std::shared_ptr<RuntimeDyld::SymbolResolver>(
>>
>
> Prefer copy init over direct init (otherwise it looks like
> createLambdaResolver might be returning a raw pointer you're taking
> ownership of here - which raises a bit more care than is otherwise due) ^
>

This is copy-init, isn't it?


> +        orc::createLambdaResolver(
>> +          [this](const std::string &Name) {
>> +            if (auto Sym = CODLayer.findSymbol(Name, true))
>> +              return RuntimeDyld::SymbolInfo(Sym.getAddress(),
>> +                                             Sym.getFlags());
>> +
>> +            if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name))
>> +              return Sym;
>>
>> -          if (auto Sym = CODLayer.findSymbol(Name, true))
>> -            return RuntimeDyld::SymbolInfo(Sym.getAddress(),
>> Sym.getFlags());
>> +            if (auto Addr =
>> +                RTDyldMemoryManager::getSymbolAddressInProcess(Name))
>> +              return RuntimeDyld::SymbolInfo(Addr,
>> JITSymbolFlags::Exported);
>>
>> -          if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name))
>> -            return Sym;
>> -
>> -          if (auto Addr =
>> RTDyldMemoryManager::getSymbolAddressInProcess(Name))
>> -            return RuntimeDyld::SymbolInfo(Addr,
>> JITSymbolFlags::Exported);
>> -
>> -          return RuntimeDyld::SymbolInfo(nullptr);
>> -        },
>> -        [](const std::string &Name) { return
>> RuntimeDyld::SymbolInfo(nullptr); }
>> -      );
>> +            return RuntimeDyld::SymbolInfo(nullptr);
>> +          },
>> +          [](const std::string &Name) {
>> +            return RuntimeDyld::SymbolInfo(nullptr);
>> +          }
>> +        ));
>>
>>      // Add the module to the JIT.
>>      std::vector<std::unique_ptr<Module>> S;
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150612/31e44bf9/attachment.html>


More information about the llvm-commits mailing list