//===-- 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 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 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 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(*MemoryManager, Resolver); RTDyld->setProcessAllSections(ProcessAllSections); { std::lock_guard 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 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 Lock(RTDyldLayerMutex); ActiveRTDylds.erase(K); } if (RTDyld->hasError()) { ES.reportError(make_error(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 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.