diff options
Diffstat (limited to 'include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h')
| -rw-r--r-- | include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h | 341 |
1 files changed, 199 insertions, 142 deletions
diff --git a/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h index 246c57341f35..48b3f7a58ed7 100644 --- a/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h +++ b/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h @@ -18,6 +18,9 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/ExecutionEngine/Orc/Layer.h" +#include "llvm/ExecutionEngine/Orc/Legacy.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Error.h" @@ -33,15 +36,62 @@ namespace llvm { namespace orc { -class RTDyldObjectLinkingLayerBase { +class RTDyldObjectLinkingLayer2 : public ObjectLayer { public: + /// Functor for receiving object-loaded notifications. + using NotifyLoadedFunction = + std::function<void(VModuleKey, const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &)>; + + /// Functor for receiving finalization notifications. + using NotifyFinalizedFunction = std::function<void(VModuleKey)>; - using ObjectPtr = - std::shared_ptr<object::OwningBinary<object::ObjectFile>>; + using GetMemoryManagerFunction = + std::function<std::shared_ptr<RuntimeDyld::MemoryManager>(VModuleKey)>; + + /// Construct an ObjectLinkingLayer with the given NotifyLoaded, + /// and NotifyFinalized functors. + RTDyldObjectLinkingLayer2( + ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager, + NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(), + NotifyFinalizedFunction NotifyFinalized = NotifyFinalizedFunction()); + + /// Emit the object. + void emit(MaterializationResponsibility R, VModuleKey K, + std::unique_ptr<MemoryBuffer> O) override; + + /// Map section addresses for the object associated with the + /// VModuleKey K. + void mapSectionAddress(VModuleKey K, const void *LocalAddress, + JITTargetAddress TargetAddr) const; + + /// Set the 'ProcessAllSections' flag. + /// + /// If set to true, all sections in each object file will be allocated using + /// the memory manager, rather than just the sections required for execution. + /// + /// This is kludgy, and may be removed in the future. + void setProcessAllSections(bool ProcessAllSections) { + this->ProcessAllSections = ProcessAllSections; + } + +private: + mutable std::mutex RTDyldLayerMutex; + GetMemoryManagerFunction GetMemoryManager; + NotifyLoadedFunction NotifyLoaded; + NotifyFinalizedFunction NotifyFinalized; + bool ProcessAllSections; + std::map<VModuleKey, RuntimeDyld *> ActiveRTDylds; + std::map<VModuleKey, std::shared_ptr<RuntimeDyld::MemoryManager>> MemMgrs; +}; + +class RTDyldObjectLinkingLayerBase { +public: + using ObjectPtr = std::unique_ptr<MemoryBuffer>; protected: - /// @brief Holds an object to be allocated/linked as a unit in the JIT. + /// Holds an object to be allocated/linked as a unit in the JIT. /// /// An instance of this class will be created for each object added /// via JITObjectLayer::addObject. Deleting the instance (via @@ -55,7 +105,7 @@ protected: void operator=(const LinkedObject&) = delete; virtual ~LinkedObject() = default; - virtual void finalize() = 0; + virtual Error finalize() = 0; virtual JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) = 0; @@ -79,15 +129,9 @@ protected: StringMap<JITEvaluatedSymbol> SymbolTable; bool Finalized = false; }; - - using LinkedObjectListT = std::list<std::unique_ptr<LinkedObject>>; - -public: - /// @brief Handle to a loaded object. - using ObjHandleT = LinkedObjectListT::iterator; }; -/// @brief Bare bones object linking layer. +/// Bare bones object linking layer. /// /// This class is intended to be used as the base layer for a JIT. It allows /// object files to be loaded into memory, linked, and the addresses of their @@ -98,67 +142,93 @@ public: using RTDyldObjectLinkingLayerBase::ObjectPtr; - /// @brief Functor for receiving object-loaded notifications. + /// Functor for receiving object-loaded notifications. using NotifyLoadedFtor = - std::function<void(ObjHandleT, const ObjectPtr &Obj, - const RuntimeDyld::LoadedObjectInfo &)>; + std::function<void(VModuleKey, const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &)>; - /// @brief Functor for receiving finalization notifications. - using NotifyFinalizedFtor = std::function<void(ObjHandleT)>; + /// Functor for receiving finalization notifications. + using NotifyFinalizedFtor = + std::function<void(VModuleKey, const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &)>; -private: + /// Functor for receiving deallocation notifications. + using NotifyFreedFtor = std::function<void(VModuleKey, const object::ObjectFile &Obj)>; +private: + using OwnedObject = object::OwningBinary<object::ObjectFile>; - template <typename MemoryManagerPtrT, typename SymbolResolverPtrT, - typename FinalizerFtor> + template <typename MemoryManagerPtrT> class ConcreteLinkedObject : public LinkedObject { public: - ConcreteLinkedObject(ObjectPtr Obj, MemoryManagerPtrT MemMgr, - SymbolResolverPtrT Resolver, - FinalizerFtor Finalizer, + ConcreteLinkedObject(RTDyldObjectLinkingLayer &Parent, VModuleKey K, + OwnedObject Obj, MemoryManagerPtrT MemMgr, + std::shared_ptr<SymbolResolver> Resolver, bool ProcessAllSections) - : MemMgr(std::move(MemMgr)), - PFC(llvm::make_unique<PreFinalizeContents>(std::move(Obj), - std::move(Resolver), - std::move(Finalizer), - ProcessAllSections)) { + : K(std::move(K)), + Parent(Parent), + MemMgr(std::move(MemMgr)), + PFC(llvm::make_unique<PreFinalizeContents>( + std::move(Obj), std::move(Resolver), + ProcessAllSections)) { buildInitialSymbolTable(PFC->Obj); } ~ConcreteLinkedObject() override { - MemMgr->deregisterEHFrames(); - } + if (this->Parent.NotifyFreed) + this->Parent.NotifyFreed(K, *ObjForNotify.getBinary()); - void setHandle(ObjHandleT H) { - PFC->Handle = H; + MemMgr->deregisterEHFrames(); } - void finalize() override { + Error finalize() override { assert(PFC && "mapSectionAddress called on finalized LinkedObject"); - RuntimeDyld RTDyld(*MemMgr, *PFC->Resolver); - RTDyld.setProcessAllSections(PFC->ProcessAllSections); - PFC->RTDyld = &RTDyld; + JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver, + nullptr); + PFC->RTDyld = llvm::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter); + PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections); + + Finalized = true; + + std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info = + PFC->RTDyld->loadObject(*PFC->Obj.getBinary()); + + // Copy the symbol table out of the RuntimeDyld instance. + { + auto SymTab = PFC->RTDyld->getSymbolTable(); + for (auto &KV : SymTab) + SymbolTable[KV.first] = KV.second; + } + + if (Parent.NotifyLoaded) + Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info); + + PFC->RTDyld->finalizeWithMemoryManagerLocking(); + + if (PFC->RTDyld->hasError()) + return make_error<StringError>(PFC->RTDyld->getErrorString(), + inconvertibleErrorCode()); - this->Finalized = true; - PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Obj), - [&]() { - this->updateSymbolTable(RTDyld); - }); + if (Parent.NotifyFinalized) + Parent.NotifyFinalized(K, *PFC->Obj.getBinary(), *Info); // Release resources. + if (this->Parent.NotifyFreed) + ObjForNotify = std::move(PFC->Obj); // needed for callback PFC = nullptr; + return Error::success(); } JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override { - return - [this, Name]() { - // The symbol may be materialized between the creation of this lambda - // and its execution, so we need to double check. - if (!this->Finalized) - this->finalize(); - return this->getSymbol(Name, false).getAddress(); - }; + return [this, Name]() -> Expected<JITTargetAddress> { + // The symbol may be materialized between the creation of this lambda + // and its execution, so we need to double check. + if (!this->Finalized) + if (auto Err = this->finalize()) + return std::move(Err); + return this->getSymbol(Name, false).getAddress(); + }; } void mapSectionAddress(const void *LocalAddress, @@ -169,9 +239,8 @@ private: } private: - - void buildInitialSymbolTable(const ObjectPtr &Obj) { - for (auto &Symbol : Obj->getBinary()->symbols()) { + void buildInitialSymbolTable(const OwnedObject &Obj) { + for (auto &Symbol : Obj.getBinary()->symbols()) { if (Symbol.getFlags() & object::SymbolRef::SF_Undefined) continue; Expected<StringRef> SymbolName = Symbol.getName(); @@ -186,65 +255,64 @@ private: } } - void updateSymbolTable(const RuntimeDyld &RTDyld) { - for (auto &SymEntry : SymbolTable) - SymEntry.second = RTDyld.getSymbol(SymEntry.first()); - } - // Contains the information needed prior to finalization: the object files, // memory manager, resolver, and flags needed for RuntimeDyld. struct PreFinalizeContents { - PreFinalizeContents(ObjectPtr Obj, SymbolResolverPtrT Resolver, - FinalizerFtor Finalizer, bool ProcessAllSections) - : Obj(std::move(Obj)), Resolver(std::move(Resolver)), - Finalizer(std::move(Finalizer)), - ProcessAllSections(ProcessAllSections) {} - - ObjectPtr Obj; - SymbolResolverPtrT Resolver; - FinalizerFtor Finalizer; + PreFinalizeContents(OwnedObject Obj, + std::shared_ptr<SymbolResolver> Resolver, + bool ProcessAllSections) + : Obj(std::move(Obj)), + Resolver(std::move(Resolver)), + ProcessAllSections(ProcessAllSections) {} + + OwnedObject Obj; + std::shared_ptr<SymbolResolver> Resolver; bool ProcessAllSections; - ObjHandleT Handle; - RuntimeDyld *RTDyld; + std::unique_ptr<RuntimeDyld> RTDyld; }; + VModuleKey K; + RTDyldObjectLinkingLayer &Parent; MemoryManagerPtrT MemMgr; + OwnedObject ObjForNotify; std::unique_ptr<PreFinalizeContents> PFC; }; - template <typename MemoryManagerPtrT, typename SymbolResolverPtrT, - typename FinalizerFtor> - std::unique_ptr< - ConcreteLinkedObject<MemoryManagerPtrT, SymbolResolverPtrT, FinalizerFtor>> - createLinkedObject(ObjectPtr Obj, MemoryManagerPtrT MemMgr, - SymbolResolverPtrT Resolver, - FinalizerFtor Finalizer, + template <typename MemoryManagerPtrT> + std::unique_ptr<ConcreteLinkedObject<MemoryManagerPtrT>> + createLinkedObject(RTDyldObjectLinkingLayer &Parent, VModuleKey K, + OwnedObject Obj, MemoryManagerPtrT MemMgr, + std::shared_ptr<SymbolResolver> Resolver, bool ProcessAllSections) { - using LOS = ConcreteLinkedObject<MemoryManagerPtrT, SymbolResolverPtrT, - FinalizerFtor>; - return llvm::make_unique<LOS>(std::move(Obj), std::move(MemMgr), - std::move(Resolver), std::move(Finalizer), + using LOS = ConcreteLinkedObject<MemoryManagerPtrT>; + return llvm::make_unique<LOS>(Parent, std::move(K), std::move(Obj), + std::move(MemMgr), std::move(Resolver), ProcessAllSections); } public: + struct Resources { + std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr; + std::shared_ptr<SymbolResolver> Resolver; + }; - /// @brief Functor for creating memory managers. - using MemoryManagerGetter = - std::function<std::shared_ptr<RuntimeDyld::MemoryManager>()>; + using ResourcesGetter = std::function<Resources(VModuleKey)>; - /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded, + /// Construct an ObjectLinkingLayer with the given NotifyLoaded, /// and NotifyFinalized functors. RTDyldObjectLinkingLayer( - MemoryManagerGetter GetMemMgr, + ExecutionSession &ES, ResourcesGetter GetResources, NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), - NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()) - : GetMemMgr(GetMemMgr), + NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(), + NotifyFreedFtor NotifyFreed = NotifyFreedFtor()) + : ES(ES), GetResources(std::move(GetResources)), NotifyLoaded(std::move(NotifyLoaded)), NotifyFinalized(std::move(NotifyFinalized)), - ProcessAllSections(false) {} + NotifyFreed(std::move(NotifyFreed)), + ProcessAllSections(false) { + } - /// @brief Set the 'ProcessAllSections' flag. + /// Set the 'ProcessAllSections' flag. /// /// If set to true, all sections in each object file will be allocated using /// the memory manager, rather than just the sections required for execution. @@ -254,44 +322,26 @@ public: this->ProcessAllSections = ProcessAllSections; } - /// @brief Add an object to the JIT. - /// - /// @return A handle that can be used to refer to the loaded object (for - /// symbol searching, finalization, freeing memory, etc.). - Expected<ObjHandleT> addObject(ObjectPtr Obj, - std::shared_ptr<JITSymbolResolver> Resolver) { - auto Finalizer = [&](ObjHandleT H, RuntimeDyld &RTDyld, - const ObjectPtr &ObjToLoad, - std::function<void()> LOSHandleLoad) { - std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info = - RTDyld.loadObject(*ObjToLoad->getBinary()); - - LOSHandleLoad(); - - if (this->NotifyLoaded) - this->NotifyLoaded(H, ObjToLoad, *Info); + /// Add an object to the JIT. + Error addObject(VModuleKey K, ObjectPtr ObjBuffer) { - RTDyld.finalizeWithMemoryManagerLocking(); + auto Obj = + object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); + if (!Obj) + return Obj.takeError(); - if (this->NotifyFinalized) - this->NotifyFinalized(H); - }; + assert(!LinkedObjects.count(K) && "VModuleKey already in use"); - auto LO = - createLinkedObject(std::move(Obj), GetMemMgr(), - std::move(Resolver), std::move(Finalizer), - ProcessAllSections); - // LOS is an owning-ptr. Keep a non-owning one so that we can set the handle - // below. - auto *LOPtr = LO.get(); + auto R = GetResources(K); - ObjHandleT Handle = LinkedObjList.insert(LinkedObjList.end(), std::move(LO)); - LOPtr->setHandle(Handle); + LinkedObjects[K] = createLinkedObject( + *this, K, OwnedObject(std::move(*Obj), std::move(ObjBuffer)), + std::move(R.MemMgr), std::move(R.Resolver), ProcessAllSections); - return Handle; + return Error::success(); } - /// @brief Remove the object associated with handle H. + /// Remove the object associated with VModuleKey K. /// /// All memory allocated for the object will be freed, and the sections and /// symbols it provided will no longer be available. No attempt is made to @@ -299,57 +349,64 @@ public: /// indirectly) will result in undefined behavior. If dependence tracking is /// required to detect or resolve such issues it should be added at a higher /// layer. - Error removeObject(ObjHandleT H) { + Error removeObject(VModuleKey K) { + assert(LinkedObjects.count(K) && "VModuleKey not associated with object"); // How do we invalidate the symbols in H? - LinkedObjList.erase(H); + LinkedObjects.erase(K); return Error::success(); } - /// @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 I = LinkedObjList.begin(), E = LinkedObjList.end(); I != E; - ++I) - if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly)) - return Symbol; + for (auto &KV : LinkedObjects) + if (auto Sym = KV.second->getSymbol(Name, ExportedSymbolsOnly)) + return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); return nullptr; } - /// @brief Search for the given named symbol in the context of the loaded - /// object represented by the handle H. - /// @param H The handle for the object to search in. + /// Search for the given named symbol in the context of the loaded + /// object represented by the VModuleKey K. + /// @param K The VModuleKey for the object to search in. /// @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 is found in the /// given object. - JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, + JITSymbol findSymbolIn(VModuleKey K, StringRef Name, bool ExportedSymbolsOnly) { - return (*H)->getSymbol(Name, ExportedSymbolsOnly); + assert(LinkedObjects.count(K) && "VModuleKey not associated with object"); + return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly); } - /// @brief Map section addresses for the object associated with the handle H. - void mapSectionAddress(ObjHandleT H, const void *LocalAddress, + /// Map section addresses for the object associated with the + /// VModuleKey K. + void mapSectionAddress(VModuleKey K, const void *LocalAddress, JITTargetAddress TargetAddr) { - (*H)->mapSectionAddress(LocalAddress, TargetAddr); + assert(LinkedObjects.count(K) && "VModuleKey not associated with object"); + LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr); } - /// @brief Immediately emit and finalize the object represented by the given - /// handle. - /// @param H Handle for object to emit/finalize. - Error emitAndFinalize(ObjHandleT H) { - (*H)->finalize(); - return Error::success(); + /// Immediately emit and finalize the object represented by the given + /// VModuleKey. + /// @param K VModuleKey for object to emit/finalize. + Error emitAndFinalize(VModuleKey K) { + assert(LinkedObjects.count(K) && "VModuleKey not associated with object"); + return LinkedObjects[K]->finalize(); } private: + ExecutionSession &ES; - LinkedObjectListT LinkedObjList; - MemoryManagerGetter GetMemMgr; + std::map<VModuleKey, std::unique_ptr<LinkedObject>> LinkedObjects; + ResourcesGetter GetResources; NotifyLoadedFtor NotifyLoaded; NotifyFinalizedFtor NotifyFinalized; + NotifyFreedFtor NotifyFreed; bool ProcessAllSections = false; }; |
