diff options
Diffstat (limited to 'include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h')
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h | 346 |
1 files changed, 222 insertions, 124 deletions
diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index a961992c2147..8bd21a0e3dd6 100644 --- a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -22,6 +22,8 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/Orc/Layer.h" +#include "llvm/ExecutionEngine/Orc/Legacy.h" #include "llvm/ExecutionEngine/Orc/OrcError.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/Attributes.h" @@ -56,7 +58,47 @@ class Value; namespace orc { -/// @brief Compile-on-demand layer. +class ExtractingIRMaterializationUnit; + +class CompileOnDemandLayer2 : public IRLayer { + friend class ExtractingIRMaterializationUnit; + +public: + /// Builder for IndirectStubsManagers. + using IndirectStubsManagerBuilder = + std::function<std::unique_ptr<IndirectStubsManager>()>; + + using GetAvailableContextFunction = std::function<LLVMContext &()>; + + CompileOnDemandLayer2(ExecutionSession &ES, IRLayer &BaseLayer, + JITCompileCallbackManager &CCMgr, + IndirectStubsManagerBuilder BuildIndirectStubsManager, + GetAvailableContextFunction GetAvailableContext); + + Error add(VSO &V, VModuleKey K, std::unique_ptr<Module> M) override; + + void emit(MaterializationResponsibility R, VModuleKey K, + std::unique_ptr<Module> M) override; + +private: + using StubManagersMap = + std::map<const VSO *, std::unique_ptr<IndirectStubsManager>>; + + IndirectStubsManager &getStubsManager(const VSO &V); + + void emitExtractedFunctionsModule(MaterializationResponsibility R, + std::unique_ptr<Module> M); + + mutable std::mutex CODLayerMutex; + + IRLayer &BaseLayer; + JITCompileCallbackManager &CCMgr; + IndirectStubsManagerBuilder BuildIndirectStubsManager; + StubManagersMap StubsMgrs; + GetAvailableContextFunction GetAvailableContext; +}; + +/// Compile-on-demand layer. /// /// When a module is added to this layer a stub is created for each of its /// function definitions. The stubs and other global values are immediately @@ -85,8 +127,6 @@ private: return LambdaMaterializer<MaterializerFtor>(std::move(M)); } - using BaseLayerModuleHandleT = typename BaseLayerT::ModuleHandleT; - // Provide type-erasure for the Modules and MemoryManagers. template <typename ResourceT> class ResourceOwner { @@ -138,18 +178,22 @@ private: }; struct LogicalDylib { - using SymbolResolverFtor = std::function<JITSymbol(const std::string&)>; - struct SourceModuleEntry { - std::shared_ptr<Module> SourceMod; + std::unique_ptr<Module> SourceMod; std::set<Function*> StubsToClone; }; using SourceModulesList = std::vector<SourceModuleEntry>; using SourceModuleHandle = typename SourceModulesList::size_type; - SourceModuleHandle - addSourceModule(std::shared_ptr<Module> M) { + LogicalDylib() = default; + + LogicalDylib(VModuleKey K, std::shared_ptr<SymbolResolver> BackingResolver, + std::unique_ptr<IndirectStubsMgrT> StubsMgr) + : K(std::move(K)), BackingResolver(std::move(BackingResolver)), + StubsMgr(std::move(StubsMgr)) {} + + SourceModuleHandle addSourceModule(std::unique_ptr<Module> M) { SourceModuleHandle H = SourceModules.size(); SourceModules.push_back(SourceModuleEntry()); SourceModules.back().SourceMod = std::move(M); @@ -168,8 +212,8 @@ private: bool ExportedSymbolsOnly) { if (auto Sym = StubsMgr->findStub(Name, ExportedSymbolsOnly)) return Sym; - for (auto BLH : BaseLayerHandles) - if (auto Sym = BaseLayer.findSymbolIn(BLH, Name, ExportedSymbolsOnly)) + for (auto BLK : BaseLayerVModuleKeys) + if (auto Sym = BaseLayer.findSymbolIn(BLK, Name, ExportedSymbolsOnly)) return Sym; else if (auto Err = Sym.takeError()) return std::move(Err); @@ -177,91 +221,94 @@ private: } Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) { - for (auto &BLH : BaseLayerHandles) - if (auto Err = BaseLayer.removeModule(BLH)) + for (auto &BLK : BaseLayerVModuleKeys) + if (auto Err = BaseLayer.removeModule(BLK)) return Err; return Error::success(); } - std::shared_ptr<JITSymbolResolver> ExternalSymbolResolver; + VModuleKey K; + std::shared_ptr<SymbolResolver> BackingResolver; std::unique_ptr<IndirectStubsMgrT> StubsMgr; StaticGlobalRenamer StaticRenamer; SourceModulesList SourceModules; - std::vector<BaseLayerModuleHandleT> BaseLayerHandles; + std::vector<VModuleKey> BaseLayerVModuleKeys; }; - using LogicalDylibList = std::list<LogicalDylib>; - public: - /// @brief Handle to loaded module. - using ModuleHandleT = typename LogicalDylibList::iterator; - - /// @brief Module partitioning functor. + /// Module partitioning functor. using PartitioningFtor = std::function<std::set<Function*>(Function&)>; - /// @brief Builder for IndirectStubsManagers. + /// Builder for IndirectStubsManagers. using IndirectStubsManagerBuilderT = std::function<std::unique_ptr<IndirectStubsMgrT>()>; - /// @brief Construct a compile-on-demand layer instance. - CompileOnDemandLayer(BaseLayerT &BaseLayer, PartitioningFtor Partition, + using SymbolResolverGetter = + std::function<std::shared_ptr<SymbolResolver>(VModuleKey K)>; + + using SymbolResolverSetter = + std::function<void(VModuleKey K, std::shared_ptr<SymbolResolver> R)>; + + /// Construct a compile-on-demand layer instance. + CompileOnDemandLayer(ExecutionSession &ES, BaseLayerT &BaseLayer, + SymbolResolverGetter GetSymbolResolver, + SymbolResolverSetter SetSymbolResolver, + PartitioningFtor Partition, CompileCallbackMgrT &CallbackMgr, IndirectStubsManagerBuilderT CreateIndirectStubsManager, bool CloneStubsIntoPartitions = true) - : BaseLayer(BaseLayer), Partition(std::move(Partition)), - CompileCallbackMgr(CallbackMgr), + : ES(ES), BaseLayer(BaseLayer), + GetSymbolResolver(std::move(GetSymbolResolver)), + SetSymbolResolver(std::move(SetSymbolResolver)), + Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr), CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)), CloneStubsIntoPartitions(CloneStubsIntoPartitions) {} ~CompileOnDemandLayer() { // FIXME: Report error on log. while (!LogicalDylibs.empty()) - consumeError(removeModule(LogicalDylibs.begin())); + consumeError(removeModule(LogicalDylibs.begin()->first)); } - /// @brief Add a module to the compile-on-demand layer. - Expected<ModuleHandleT> - addModule(std::shared_ptr<Module> M, - std::shared_ptr<JITSymbolResolver> Resolver) { + /// Add a module to the compile-on-demand layer. + Error addModule(VModuleKey K, std::unique_ptr<Module> M) { - LogicalDylibs.push_back(LogicalDylib()); - auto &LD = LogicalDylibs.back(); - LD.ExternalSymbolResolver = std::move(Resolver); - LD.StubsMgr = CreateIndirectStubsManager(); + assert(!LogicalDylibs.count(K) && "VModuleKey K already in use"); + auto I = LogicalDylibs.insert( + LogicalDylibs.end(), + std::make_pair(K, LogicalDylib(K, GetSymbolResolver(K), + CreateIndirectStubsManager()))); - // Process each of the modules in this module set. - if (auto Err = addLogicalModule(LD, std::move(M))) - return std::move(Err); - - return std::prev(LogicalDylibs.end()); + return addLogicalModule(I->second, std::move(M)); } - /// @brief Add extra modules to an existing logical module. - Error addExtraModule(ModuleHandleT H, std::shared_ptr<Module> M) { - return addLogicalModule(*H, std::move(M)); + /// Add extra modules to an existing logical module. + Error addExtraModule(VModuleKey K, std::unique_ptr<Module> M) { + return addLogicalModule(LogicalDylibs[K], std::move(M)); } - /// @brief Remove the module represented by the given handle. + /// Remove the module represented by the given key. /// /// This will remove all modules in the layers below that were derived from - /// the module represented by H. - Error removeModule(ModuleHandleT H) { - auto Err = H->removeModulesFromBaseLayer(BaseLayer); - LogicalDylibs.erase(H); + /// the module represented by K. + Error removeModule(VModuleKey K) { + auto I = LogicalDylibs.find(K); + assert(I != LogicalDylibs.end() && "VModuleKey K not valid here"); + auto Err = I->second.removeModulesFromBaseLayer(BaseLayer); + LogicalDylibs.erase(I); return Err; } - /// @brief Search for the given named symbol. + /// Search for the given named symbol. /// @param Name The name of the symbol to search for. /// @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 Sym = LDI->StubsMgr->findStub(Name, ExportedSymbolsOnly)) + for (auto &KV : LogicalDylibs) { + if (auto Sym = KV.second.StubsMgr->findStub(Name, ExportedSymbolsOnly)) return Sym; - if (auto Sym = findSymbolIn(LDI, Name, ExportedSymbolsOnly)) + if (auto Sym = findSymbolIn(KV.first, Name, ExportedSymbolsOnly)) return Sym; else if (auto Err = Sym.takeError()) return std::move(Err); @@ -269,14 +316,15 @@ public: return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); } - /// @brief Get the address of a symbol provided by this layer, or some layer + /// Get the address of a symbol provided by this layer, or some layer /// below this one. - JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name, + JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, bool ExportedSymbolsOnly) { - return H->findSymbol(BaseLayer, Name, ExportedSymbolsOnly); + assert(LogicalDylibs.count(K) && "VModuleKey K is not valid here"); + return LogicalDylibs[K].findSymbol(BaseLayer, Name, ExportedSymbolsOnly); } - /// @brief Update the stub for the given function to point at FnBodyAddr. + /// Update the stub for the given function to point at FnBodyAddr. /// This can be used to support re-optimization. /// @return true if the function exists and the stub is updated, false /// otherwise. @@ -302,15 +350,14 @@ public: } private: - - Error addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcMPtr) { + Error addLogicalModule(LogicalDylib &LD, std::unique_ptr<Module> SrcMPtr) { // Rename all static functions / globals to $static.X : // This will unique the names across all modules in the logical dylib, // simplifying symbol lookup. LD.StaticRenamer.rename(*SrcMPtr); - // Bump the linkage and rename any anonymous/privote members in SrcM to + // Bump the linkage and rename any anonymous/private members in SrcM to // ensure that everything will resolve properly after we partition SrcM. makeAllSymbolsExternallyAccessible(*SrcMPtr); @@ -343,22 +390,21 @@ private: // Create a callback, associate it with the stub for the function, // and set the compile action to compile the partition containing the // function. - if (auto CCInfoOrErr = CompileCallbackMgr.getCompileCallback()) { - auto &CCInfo = *CCInfoOrErr; + auto CompileAction = [this, &LD, LMId, &F]() -> JITTargetAddress { + if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F)) + return *FnImplAddrOrErr; + else { + // FIXME: Report error, return to 'abort' or something similar. + consumeError(FnImplAddrOrErr.takeError()); + return 0; + } + }; + if (auto CCAddr = + CompileCallbackMgr.getCompileCallback(std::move(CompileAction))) StubInits[MangledName] = - std::make_pair(CCInfo.getAddress(), - JITSymbolFlags::fromGlobalValue(F)); - CCInfo.setCompileAction([this, &LD, LMId, &F]() -> JITTargetAddress { - if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F)) - return *FnImplAddrOrErr; - else { - // FIXME: Report error, return to 'abort' or something similar. - consumeError(FnImplAddrOrErr.takeError()); - return 0; - } - }); - } else - return CCInfoOrErr.takeError(); + std::make_pair(*CCAddr, JITSymbolFlags::fromGlobalValue(F)); + else + return CCAddr.takeError(); } if (auto Err = LD.StubsMgr->createStubs(StubInits)) @@ -396,9 +442,8 @@ private: // Initializers may refer to functions declared (but not defined) in this // module. Build a materializer to clone decls on demand. - Error MaterializerErrors = Error::success(); auto Materializer = createLambdaMaterializer( - [&LD, &GVsM, &MaterializerErrors](Value *V) -> Value* { + [&LD, &GVsM](Value *V) -> Value* { if (auto *F = dyn_cast<Function>(V)) { // Decls in the original module just get cloned. if (F->isDeclaration()) @@ -410,18 +455,8 @@ private: const DataLayout &DL = GVsM->getDataLayout(); std::string FName = mangle(F->getName(), DL); unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType()); - JITTargetAddress StubAddr = 0; - - // Get the address for the stub. If we encounter an error while - // doing so, stash it in the MaterializerErrors variable and use a - // null address as a placeholder. - if (auto StubSym = LD.StubsMgr->findStub(FName, false)) { - if (auto StubAddrOrErr = StubSym.getAddress()) - StubAddr = *StubAddrOrErr; - else - MaterializerErrors = joinErrors(std::move(MaterializerErrors), - StubAddrOrErr.takeError()); - } + JITTargetAddress StubAddr = + LD.StubsMgr->findStub(FName, false).getAddress(); ConstantInt *StubAddrCI = ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr)); @@ -450,29 +485,58 @@ private: NewA->setAliasee(cast<Constant>(Init)); } - if (MaterializerErrors) - return MaterializerErrors; - // Build a resolver for the globals module and add it to the base layer. - auto GVsResolver = createLambdaResolver( - [this, &LD](const std::string &Name) -> JITSymbol { - if (auto Sym = LD.StubsMgr->findStub(Name, false)) - return Sym; - if (auto Sym = LD.findSymbol(BaseLayer, Name, false)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name); + auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol { + if (auto Sym = LD.StubsMgr->findStub(Name, false)) + return Sym; + + if (auto Sym = LD.findSymbol(BaseLayer, Name, false)) + return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); + + return nullptr; + }; + + auto GVsResolver = createSymbolResolver( + [&LD, LegacyLookup](const SymbolNameSet &Symbols) { + auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup); + + if (!SymbolFlags) { + logAllUnhandledErrors(SymbolFlags.takeError(), errs(), + "CODLayer/GVsResolver flags lookup failed: "); + return SymbolFlagsMap(); + } + + if (SymbolFlags->size() == Symbols.size()) + return *SymbolFlags; + + SymbolNameSet NotFoundViaLegacyLookup; + for (auto &S : Symbols) + if (!SymbolFlags->count(S)) + NotFoundViaLegacyLookup.insert(S); + auto SymbolFlags2 = + LD.BackingResolver->lookupFlags(NotFoundViaLegacyLookup); + + for (auto &KV : SymbolFlags2) + (*SymbolFlags)[KV.first] = std::move(KV.second); + + return *SymbolFlags; }, - [&LD](const std::string &Name) { - return LD.ExternalSymbolResolver->findSymbol(Name); + [this, &LD, + LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query, + SymbolNameSet Symbols) { + auto NotFoundViaLegacyLookup = + lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup); + return LD.BackingResolver->lookup(Query, NotFoundViaLegacyLookup); }); - if (auto GVsHOrErr = - BaseLayer.addModule(std::move(GVsM), std::move(GVsResolver))) - LD.BaseLayerHandles.push_back(*GVsHOrErr); - else - return GVsHOrErr.takeError(); + SetSymbolResolver(LD.K, std::move(GVsResolver)); + + if (auto Err = BaseLayer.addModule(LD.K, std::move(GVsM))) + return Err; + + LD.BaseLayerVModuleKeys.push_back(LD.K); return Error::success(); } @@ -501,11 +565,11 @@ private: JITTargetAddress CalledAddr = 0; auto Part = Partition(F); - if (auto PartHOrErr = emitPartition(LD, LMId, Part)) { - auto &PartH = *PartHOrErr; + if (auto PartKeyOrErr = emitPartition(LD, LMId, Part)) { + auto &PartKey = *PartKeyOrErr; for (auto *SubF : Part) { std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout()); - if (auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false)) { + if (auto FnBodySym = BaseLayer.findSymbolIn(PartKey, FnName, false)) { if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) { JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr; @@ -526,15 +590,15 @@ private: llvm_unreachable("Function not emitted for partition"); } - LD.BaseLayerHandles.push_back(PartH); + LD.BaseLayerVModuleKeys.push_back(PartKey); } else - return PartHOrErr.takeError(); + return PartKeyOrErr.takeError(); return CalledAddr; } template <typename PartitionT> - Expected<BaseLayerModuleHandleT> + Expected<VModuleKey> emitPartition(LogicalDylib &LD, typename LogicalDylib::SourceModuleHandle LMId, const PartitionT &Part) { @@ -596,28 +660,62 @@ private: for (auto *F : Part) moveFunctionBody(*F, VMap, &Materializer); + auto K = ES.allocateVModule(); + + auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol { + return LD.findSymbol(BaseLayer, Name, false); + }; + // Create memory manager and symbol resolver. - auto Resolver = createLambdaResolver( - [this, &LD](const std::string &Name) -> JITSymbol { - if (auto Sym = LD.findSymbol(BaseLayer, Name, false)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name); + auto Resolver = createSymbolResolver( + [&LD, LegacyLookup](const SymbolNameSet &Symbols) { + auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup); + if (!SymbolFlags) { + logAllUnhandledErrors(SymbolFlags.takeError(), errs(), + "CODLayer/SubResolver flags lookup failed: "); + return SymbolFlagsMap(); + } + + if (SymbolFlags->size() == Symbols.size()) + return *SymbolFlags; + + SymbolNameSet NotFoundViaLegacyLookup; + for (auto &S : Symbols) + if (!SymbolFlags->count(S)) + NotFoundViaLegacyLookup.insert(S); + + auto SymbolFlags2 = + LD.BackingResolver->lookupFlags(NotFoundViaLegacyLookup); + + for (auto &KV : SymbolFlags2) + (*SymbolFlags)[KV.first] = std::move(KV.second); + + return *SymbolFlags; }, - [&LD](const std::string &Name) { - return LD.ExternalSymbolResolver->findSymbol(Name); + [this, &LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q, + SymbolNameSet Symbols) { + auto NotFoundViaLegacyLookup = + lookupWithLegacyFn(ES, *Q, Symbols, LegacyLookup); + return LD.BackingResolver->lookup(Q, + std::move(NotFoundViaLegacyLookup)); }); + SetSymbolResolver(K, std::move(Resolver)); + + if (auto Err = BaseLayer.addModule(std::move(K), std::move(M))) + return std::move(Err); - return BaseLayer.addModule(std::move(M), std::move(Resolver)); + return K; } + ExecutionSession &ES; BaseLayerT &BaseLayer; + SymbolResolverGetter GetSymbolResolver; + SymbolResolverSetter SetSymbolResolver; PartitioningFtor Partition; CompileCallbackMgrT &CompileCallbackMgr; IndirectStubsManagerBuilderT CreateIndirectStubsManager; - LogicalDylibList LogicalDylibs; + std::map<VModuleKey, LogicalDylib> LogicalDylibs; bool CloneStubsIntoPartitions; }; |