diff options
Diffstat (limited to 'include/llvm/ExecutionEngine/Orc')
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h | 554 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/LogicalDylib.h | 115 |
2 files changed, 296 insertions, 373 deletions
diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index 074d55e5034e..4c515dbfa8e8 100644 --- a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -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&)>> class CompileOnDemandLayer { private: @@ -44,333 +46,63 @@ private: // variables. class GlobalDeclMaterializer : public ValueMaterializer { public: - GlobalDeclMaterializer(Module &Dst) : Dst(Dst) {} + typedef std::set<const Function*> StubSet; + + GlobalDeclMaterializer(Module &Dst, const StubSet *StubsToClone = nullptr) + : Dst(Dst), StubsToClone(StubsToClone) {} + 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 if (auto *F = dyn_cast<Function>(V)) { + auto *ClonedF = cloneFunctionDecl(Dst, *F); + if (StubsToClone && StubsToClone->count(F)) { + GlobalVariable *FnBodyPtr = + createImplPointer(*ClonedF->getType(), *ClonedF->getParent(), + ClonedF->getName() + "$orc_addr", nullptr); + makeStub(*ClonedF, *FnBodyPtr); + ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage); + ClonedF->addFnAttr(Attribute::AlwaysInline); + } + return ClonedF; + } // Else. return nullptr; } private: Module &Dst; + const StubSet *StubsToClone; }; 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; - 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; + struct LogicalModuleResources { + std::shared_ptr<Module> SourceModule; + std::set<const Function*> StubsToClone; }; - 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. typedef typename LogicalDylibList::iterator ModuleSetHandleT; /// @brief Construct a compile-on-demand layer instance. - CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr) - : BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr) {} + CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr, + bool CloneStubsIntoPartitions) + : BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr), + CloneStubsIntoPartitions(CloneStubsIntoPartitions) {} /// @brief Add a module to the compile-on-demand layer. template <typename ModuleSetT, typename MemoryManagerPtrT, @@ -382,20 +114,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 &LDResources = LogicalDylibs.back().getDylibResources(); + + LDResources.ExternalSymbolResolver = + [Resolver](const std::string &Name) { + return Resolver->findSymbol(Name); + }; + + LDResources.Partitioner = + [](Function &F) { + std::set<Function*> Partition; + Partition.insert(&F); + return Partition; + }; // 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 +157,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 +170,8 @@ private: // Create a logical module handle for SrcM within the logical dylib. auto LMH = LD.createLogicalModule(); + auto &LMResources = LD.getLogicalModuleResources(LMH); + LMResources.SourceModule = SrcM; // Create the GVs-and-stubs module. auto GVsAndStubsM = llvm::make_unique<Module>( @@ -442,31 +180,35 @@ 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); }); - } - - UP.setPartitionEntries(std::move(PartitionEntries)); + for (auto &F : *SrcM) { + + // Skip declarations. + if (F.isDeclaration()) + continue; + + // Record all functions defined by this module. + if (CloneStubsIntoPartitions) + LMResources.StubsToClone.insert(&F); + + // 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 this->extractAndCompile(LD, LMH, F); + }); } // Now clone the global variable declarations. @@ -483,12 +225,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 +237,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 +250,104 @@ 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()); + + auto Partition = LD.getDylibResources().Partitioner(F); + auto PartitionH = emitPartition(LD, LMH, Partition); + + TargetAddress CalledAddr = 0; + for (auto *SubF : Partition) { + std::string FName = SubF->getName(); + 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."); + + TargetAddress 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 (SubF == &F) + CalledAddr = FnBodyAddr; + + memcpy(FnPtrAddr, &FnBodyAddr, sizeof(uintptr_t)); + } + + return CalledAddr; + } + + template <typename PartitionT> + BaseLayerModuleSetHandleT emitPartition(CODLogicalDylib &LD, + LogicalModuleHandle LMH, + const PartitionT &Partition) { + auto &LMResources = LD.getLogicalModuleResources(LMH); + Module &SrcM = *LMResources.SourceModule; + + // Create the module. + std::string NewName = SrcM.getName(); + 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, &LMResources.StubsToClone); + + // 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, &GDM); + + // 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; + 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. diff --git a/include/llvm/ExecutionEngine/Orc/LogicalDylib.h b/include/llvm/ExecutionEngine/Orc/LogicalDylib.h new file mode 100644 index 000000000000..28700ef347d6 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/LogicalDylib.h @@ -0,0 +1,115 @@ +//===--- 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 + +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 |