| //===-- 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. |