summaryrefslogtreecommitdiff
path: root/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h')
-rw-r--r--include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h341
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;
};