diff options
Diffstat (limited to 'lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp')
-rw-r--r-- | lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp new file mode 100644 index 000000000000..71b4b73ca6d3 --- /dev/null +++ b/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp @@ -0,0 +1,177 @@ +//===-- RTDyldObjectLinkingLayer.cpp - RuntimeDyld backed ORC ObjectLayer -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" + +namespace { + +using namespace llvm; +using namespace llvm::orc; + +class VSOSearchOrderResolver : public JITSymbolResolver { +public: + VSOSearchOrderResolver(MaterializationResponsibility &MR) : MR(MR) {} + + Expected<LookupResult> lookup(const LookupSet &Symbols) { + auto &ES = MR.getTargetVSO().getExecutionSession(); + SymbolNameSet InternedSymbols; + + for (auto &S : Symbols) + InternedSymbols.insert(ES.getSymbolStringPool().intern(S)); + + auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) { + MR.addDependenciesForAll(Deps); + }; + + auto InternedResult = + MR.getTargetVSO().withSearchOrderDo([&](const VSOList &VSOs) { + return ES.lookup(VSOs, InternedSymbols, RegisterDependencies, false); + }); + + if (!InternedResult) + return InternedResult.takeError(); + + LookupResult Result; + for (auto &KV : *InternedResult) + Result[*KV.first] = std::move(KV.second); + + return Result; + } + + Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) { + auto &ES = MR.getTargetVSO().getExecutionSession(); + + SymbolNameSet InternedSymbols; + + for (auto &S : Symbols) + InternedSymbols.insert(ES.getSymbolStringPool().intern(S)); + + SymbolFlagsMap InternedResult; + MR.getTargetVSO().withSearchOrderDo([&](const VSOList &VSOs) { + // An empty search order is pathalogical, but allowed. + if (VSOs.empty()) + return; + + assert(VSOs.front() && "VSOList entry can not be null"); + InternedResult = VSOs.front()->lookupFlags(InternedSymbols); + }); + + LookupFlagsResult Result; + for (auto &KV : InternedResult) + Result[*KV.first] = std::move(KV.second); + + return Result; + } + +private: + MaterializationResponsibility &MR; +}; + +} // end anonymous namespace + +namespace llvm { +namespace orc { + +RTDyldObjectLinkingLayer2::RTDyldObjectLinkingLayer2( + ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager, + NotifyLoadedFunction NotifyLoaded, NotifyFinalizedFunction NotifyFinalized) + : ObjectLayer(ES), GetMemoryManager(GetMemoryManager), + NotifyLoaded(std::move(NotifyLoaded)), + NotifyFinalized(std::move(NotifyFinalized)), ProcessAllSections(false) {} + +void RTDyldObjectLinkingLayer2::emit(MaterializationResponsibility R, + VModuleKey K, + std::unique_ptr<MemoryBuffer> O) { + assert(O && "Object must not be null"); + + auto &ES = getExecutionSession(); + + auto ObjFile = object::ObjectFile::createObjectFile(*O); + if (!ObjFile) { + getExecutionSession().reportError(ObjFile.takeError()); + R.failMaterialization(); + } + + auto MemoryManager = GetMemoryManager(K); + + VSOSearchOrderResolver Resolver(R); + auto RTDyld = llvm::make_unique<RuntimeDyld>(*MemoryManager, Resolver); + RTDyld->setProcessAllSections(ProcessAllSections); + + { + std::lock_guard<std::mutex> Lock(RTDyldLayerMutex); + + assert(!ActiveRTDylds.count(K) && + "An active RTDyld already exists for this key?"); + ActiveRTDylds[K] = RTDyld.get(); + + assert(!MemMgrs.count(K) && + "A memory manager already exists for this key?"); + MemMgrs[K] = std::move(MemoryManager); + } + + auto Info = RTDyld->loadObject(**ObjFile); + + { + std::set<StringRef> InternalSymbols; + for (auto &Sym : (*ObjFile)->symbols()) { + if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) { + if (auto SymName = Sym.getName()) + InternalSymbols.insert(*SymName); + else { + ES.reportError(SymName.takeError()); + R.failMaterialization(); + return; + } + } + } + + SymbolMap Symbols; + for (auto &KV : RTDyld->getSymbolTable()) + if (!InternalSymbols.count(KV.first)) + Symbols[ES.getSymbolStringPool().intern(KV.first)] = KV.second; + + R.resolve(Symbols); + } + + if (NotifyLoaded) + NotifyLoaded(K, **ObjFile, *Info); + + RTDyld->finalizeWithMemoryManagerLocking(); + + { + std::lock_guard<std::mutex> Lock(RTDyldLayerMutex); + ActiveRTDylds.erase(K); + } + + if (RTDyld->hasError()) { + ES.reportError(make_error<StringError>(RTDyld->getErrorString(), + inconvertibleErrorCode())); + R.failMaterialization(); + return; + } + + R.finalize(); + + if (NotifyFinalized) + NotifyFinalized(K); +} + +void RTDyldObjectLinkingLayer2::mapSectionAddress( + VModuleKey K, const void *LocalAddress, JITTargetAddress TargetAddr) const { + std::lock_guard<std::mutex> Lock(RTDyldLayerMutex); + auto ActiveRTDyldItr = ActiveRTDylds.find(K); + + assert(ActiveRTDyldItr != ActiveRTDylds.end() && + "No active RTDyld instance found for key"); + ActiveRTDyldItr->second->mapSectionAddress(LocalAddress, TargetAddr); +} + +} // End namespace orc. +} // End namespace llvm. |