diff --git a/lib/Interpreter/IncrementalExecutor.h b/lib/Interpreter/IncrementalExecutor.h index f8bec764..61427482 100644 --- a/lib/Interpreter/IncrementalExecutor.h +++ b/lib/Interpreter/IncrementalExecutor.h @@ -165,8 +165,9 @@ namespace cling { ///\brief Unload a set of JIT symbols. bool unloadModule(const std::shared_ptr& M) { - m_JIT->removeModule(M); - // FIXME: Propagate if we removed a module or not. + // FIXME: Propagate the error in a more verbose way. + if (auto Err = m_JIT->removeModule(M)) + return false; return true; } diff --git a/lib/Interpreter/IncrementalJIT.cpp b/lib/Interpreter/IncrementalJIT.cpp index 5c7cd52b..9e413fc0 100644 --- a/lib/Interpreter/IncrementalJIT.cpp +++ b/lib/Interpreter/IncrementalJIT.cpp @@ -13,6 +13,7 @@ #include "cling/Utils/Platform.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/Support/DynamicLibrary.h" #ifdef __APPLE__ @@ -41,7 +42,7 @@ public: class NotifyFinalizedT { public: NotifyFinalizedT(cling::IncrementalJIT &jit) : m_JIT(jit) {} - void operator()(llvm::orc::RTDyldObjectLinkingLayerBase::ObjSetHandleT H) { + void operator()(llvm::orc::RTDyldObjectLinkingLayerBase::ObjHandleT H) { m_JIT.RemoveUnfinalizedSection(H); } @@ -220,9 +221,15 @@ public: } uint64_t getSymbolAddress(const std::string &Name) override { - return m_jit.getSymbolAddressWithoutMangling(Name, - true /*also use dlsym*/) - .getAddress(); + // FIXME: We should decide if we want to handle the error here or make the + // return type of the function llvm::Expected relying on the + // users to decide how to handle the error. + if (auto Addr = m_jit.getSymbolAddressWithoutMangling(Name, + true /*also use dlsym*/) + .getAddress()) + return *Addr; + + return ~0U; } void *getPointerToNamedFunction(const std::string &Name, @@ -267,9 +274,10 @@ IncrementalJIT::IncrementalJIT(IncrementalExecutor& exe, m_Parent(exe), m_TM(std::move(TM)), m_TMDataLayout(m_TM->createDataLayout()), - m_ExeMM(llvm::make_unique(m_Parent)), + m_ExeMM(std::make_shared(m_Parent)), m_NotifyObjectLoaded(*this), - m_ObjectLayer(m_SymbolMap, m_NotifyObjectLoaded, NotifyFinalizedT(*this)), + m_ObjectLayer(m_SymbolMap, [this] () { return this->m_ExeMM; }, + m_NotifyObjectLoaded, NotifyFinalizedT(*this)), m_CompileLayer(m_ObjectLayer, llvm::orc::SimpleCompiler(*m_TM)), m_LazyEmitLayer(m_CompileLayer) { @@ -343,9 +351,12 @@ IncrementalJIT::getSymbolAddressWithoutMangling(const std::string& Name, return Sym; if (AlsoInProcess) { - if (llvm::JITSymbol SymInfo = m_ExeMM->findSymbol(Name)) - return llvm::JITSymbol(SymInfo.getAddress(), - llvm::JITSymbolFlags::Exported); + if (llvm::JITSymbol SymInfo = m_ExeMM->findSymbol(Name)) { + if (auto AddrOrErr = SymInfo.getAddress()) + return llvm::JITSymbol(*AddrOrErr, llvm::JITSymbolFlags::Exported); + else + llvm_unreachable("Handle the error case"); + } #ifdef LLVM_ON_WIN32 // FIXME: DLSym symbol lookup can overlap m_ExeMM->findSymbol wasting time // looking for a symbol in libs where it is already known not to exist. @@ -374,13 +385,21 @@ void IncrementalJIT::addModule(const std::shared_ptr& module) { // LLVM MERGE FIXME: update this to use new interfaces. auto Resolver = llvm::orc::createLambdaResolver( [&](const std::string &S) { - if (auto Sym = getInjectedSymbols(S)) - return JITSymbol((uint64_t)Sym.getAddress(), Sym.getFlags()); + if (auto Sym = getInjectedSymbols(S)) { + if (auto AddrOrErr = Sym.getAddress()) + return JITSymbol((uint64_t)*AddrOrErr, Sym.getFlags()); + else + llvm_unreachable("Handle the error case"); + } return m_ExeMM->findSymbol(S); }, [&](const std::string &Name) { - if (auto Sym = getSymbolAddressWithoutMangling(Name, true)) - return JITSymbol(Sym.getAddress(), Sym.getFlags()); + if (auto Sym = getSymbolAddressWithoutMangling(Name, true)) { + if (auto AddrOrErr = Sym.getAddress()) + return JITSymbol(*AddrOrErr, Sym.getFlags()); + else + llvm_unreachable("Handle the error case"); + } const std::string* NameNP = &Name; #ifdef MANGLE_PREFIX @@ -401,16 +420,14 @@ void IncrementalJIT::addModule(const std::shared_ptr& module) { return JITSymbol(addr, llvm::JITSymbolFlags::Weak); }); - std::vector moduleSet; - moduleSet.push_back(module.get()); - ModuleSetHandleT MSHandle = - m_LazyEmitLayer.addModuleSet(std::move(moduleSet), - llvm::make_unique(*this), - std::move(Resolver)); - m_UnloadPoints[module.get()] = MSHandle; + if (auto H = m_LazyEmitLayer.addModule(module, std::move(Resolver))) + m_UnloadPoints[module.get()] = *H; + else + llvm_unreachable("Handle the error case"); } -void IncrementalJIT::removeModule(const std::shared_ptr& module) { +llvm::Error +IncrementalJIT::removeModule(const std::shared_ptr& module) { // FIXME: Track down what calls this routine on a not-yet-added module. Once // this is resolved we can remove this check enabling the assert. auto IUnload = m_UnloadPoints.find(module.get()); diff --git a/lib/Interpreter/IncrementalJIT.h b/lib/Interpreter/IncrementalJIT.h index 3ef0742e..05759065 100644 --- a/lib/Interpreter/IncrementalJIT.h +++ b/lib/Interpreter/IncrementalJIT.h @@ -53,46 +53,41 @@ private: class NotifyObjectLoadedT { public: - typedef std::vector>> ObjListT; - typedef std::vector> - LoadedObjInfoListT; - NotifyObjectLoadedT(IncrementalJIT &jit) : m_JIT(jit) {} - - void operator()(llvm::orc::RTDyldObjectLinkingLayerBase::ObjSetHandleT H, - const ObjListT &Objects, - const LoadedObjInfoListT &Infos) const - { + void operator()(llvm::orc::RTDyldObjectLinkingLayerBase::ObjHandleT H, + const llvm::orc::RTDyldObjectLinkingLayer::ObjectPtr &Object, + const llvm::LoadedObjectInfo &Info) const { m_JIT.m_UnfinalizedSections[H] = std::move(m_JIT.m_SectionsAllocatedSinceLastLoad); m_JIT.m_SectionsAllocatedSinceLastLoad = SectionAddrSet(); - assert(Objects.size() == Infos.size() && - "Incorrect number of Infos for Objects."); - if (auto GDBListener = m_JIT.m_GDBListener) { - for (size_t I = 0, N = Objects.size(); I < N; ++I) - GDBListener->NotifyObjectEmitted(*Objects[I]->getBinary(), - *Infos[I]); - } - for (const auto &Object: Objects) { - for (const auto &Symbol: Object->getBinary()->symbols()) { - auto Flags = Symbol.getFlags(); - if (Flags & llvm::object::BasicSymbolRef::SF_Undefined) - continue; - // FIXME: this should be uncommented once we serve incremental - // modules from a TU module. - //if (!(Flags & llvm::object::BasicSymbolRef::SF_Exported)) - // continue; - auto NameOrError = Symbol.getName(); - if (!NameOrError) - continue; - auto Name = NameOrError.get(); - if (m_JIT.m_SymbolMap.find(Name) == m_JIT.m_SymbolMap.end()) { - llvm::JITSymbol Sym - = m_JIT.m_CompileLayer.findSymbolIn(H, Name, true); - if (llvm::JITTargetAddress Addr = Sym.getAddress()) - m_JIT.m_SymbolMap[Name] = Addr; - } + // FIXME: NotifyObjectEmitted requires a RuntimeDyld::LoadedObjectInfo + // object. In order to get it one should call + // RTDyld.loadObject(*ObjToLoad->getBinary()) according to r306058. + // Moreover this should be done in the finalizer. Currently we are + // disabling this since we have globally disabled this functionality in + // IncrementalJIT.cpp (m_GDBListener = 0). + // + // if (auto GDBListener = m_JIT.m_GDBListener) + // GDBListener->NotifyObjectEmitted(*Object->getBinary(), Info); + + for (const auto &Symbol: Object->getBinary()->symbols()) { + auto Flags = Symbol.getFlags(); + if (Flags & llvm::object::BasicSymbolRef::SF_Undefined) + continue; + // FIXME: this should be uncommented once we serve incremental + // modules from a TU module. + //if (!(Flags & llvm::object::BasicSymbolRef::SF_Exported)) + // continue; + auto NameOrError = Symbol.getName(); + if (!NameOrError) + continue; + auto Name = NameOrError.get(); + if (m_JIT.m_SymbolMap.find(Name) == m_JIT.m_SymbolMap.end()) { + llvm::JITSymbol Sym + = m_JIT.m_CompileLayer.findSymbolIn(H, Name, true); + if (auto Addr = Sym.getAddress()) + m_JIT.m_SymbolMap[Name] = *Addr; } } } @@ -100,22 +95,21 @@ private: private: IncrementalJIT &m_JIT; }; - class RemovableObjectLinkingLayer: - public llvm::orc::RTDyldObjectLinkingLayer { + public llvm::orc::RTDyldObjectLinkingLayer { public: - using Base_t = llvm::orc::RTDyldObjectLinkingLayer; - using NotifyLoadedFtor = NotifyObjectLoadedT; + using Base_t = llvm::orc::RTDyldObjectLinkingLayer; using NotifyFinalizedFtor = Base_t::NotifyFinalizedFtor; RemovableObjectLinkingLayer(SymbolMapT &SymMap, + Base_t::MemoryManagerGetter MM, NotifyObjectLoadedT NotifyLoaded, - NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()): - Base_t(NotifyLoaded, NotifyFinalized), m_SymbolMap(SymMap) + NotifyFinalizedFtor NotifyFinalized) + : Base_t(MM, NotifyLoaded, NotifyFinalized), m_SymbolMap(SymMap) {} - void - removeObjectSet(llvm::orc::RTDyldObjectLinkingLayerBase::ObjSetHandleT H) { - struct AccessSymbolTable: public LinkedObjectSet { + llvm::Error + removeObject(llvm::orc::RTDyldObjectLinkingLayerBase::ObjHandleT H) { + struct AccessSymbolTable: public LinkedObject { const llvm::StringMap& getSymbolTable() const { return SymbolTable; @@ -131,23 +125,24 @@ private: if (iterSymMap->second == NameSym.second.getAddress()) m_SymbolMap.erase(iterSymMap); } - llvm::orc::RTDyldObjectLinkingLayer::removeObjectSet(H); + return llvm::orc::RTDyldObjectLinkingLayer::removeObject(H); } private: SymbolMapT& m_SymbolMap; }; typedef RemovableObjectLinkingLayer ObjectLayerT; - typedef llvm::orc::IRCompileLayer CompileLayerT; + typedef llvm::orc::IRCompileLayer CompileLayerT; typedef llvm::orc::LazyEmittingLayer LazyEmitLayerT; - typedef LazyEmitLayerT::ModuleSetHandleT ModuleSetHandleT; + typedef LazyEmitLayerT::ModuleHandleT ModuleHandleT; std::unique_ptr m_TM; llvm::DataLayout m_TMDataLayout; ///\brief The RTDyldMemoryManager used to communicate with the /// IncrementalExecutor to handle missing or special symbols. - std::unique_ptr m_ExeMM; + std::shared_ptr m_ExeMM; NotifyObjectLoadedT m_NotifyObjectLoaded; @@ -155,22 +150,22 @@ private: CompileLayerT m_CompileLayer; LazyEmitLayerT m_LazyEmitLayer; - // We need to store ObjLayerT::ObjSetHandles for each of the object sets + // We need to store ObjLayerT::ObjHandles for each of the object sets // that have been emitted but not yet finalized so that we can forward the // mapSectionAddress calls appropriately. typedef std::set SectionAddrSet; - struct ObjSetHandleCompare { - bool operator()(ObjectLayerT::ObjSetHandleT H1, - ObjectLayerT::ObjSetHandleT H2) const { + struct ObjHandleCompare { + bool operator()(ObjectLayerT::ObjHandleT H1, + ObjectLayerT::ObjHandleT H2) const { return &*H1 < &*H2; } }; SectionAddrSet m_SectionsAllocatedSinceLastLoad; - std::map + std::map m_UnfinalizedSections; - ///\brief Mapping between \c llvm::Module* and \c ModuleSetHandleT. - std::map m_UnloadPoints; + ///\brief Mapping between \c llvm::Module* and \c ModuleHandleT. + std::map m_UnloadPoints; std::string Mangle(llvm::StringRef Name) { stdstrstream MangledName; @@ -192,22 +187,28 @@ public: /// \param AlsoInProcess - Sometimes you only care about JITed symbols. If so, /// pass `false` here to not resolve the symbol through dlsym(). uint64_t getSymbolAddress(const std::string& Name, bool AlsoInProcess) { - return getSymbolAddressWithoutMangling(Mangle(Name), AlsoInProcess) - .getAddress(); + // FIXME: We should decide if we want to handle the error here or make the + // return type of the function llvm::Expected relying on the + // users to decide how to handle the error. + if (auto Sym = getSymbolAddressWithoutMangling(Mangle(Name), AlsoInProcess)) + if (auto AddrOrErr = Sym.getAddress()) + return *AddrOrErr; + + return ~0U; } ///\brief Get the address of a symbol from the JIT or the memory manager. /// Use this to resolve symbols of known, target-specific names. llvm::JITSymbol getSymbolAddressWithoutMangling(const std::string& Name, - bool AlsoInProcess); + bool AlsoInProcess); void addModule(const std::shared_ptr& module); - void removeModule(const std::shared_ptr& module); + llvm::Error removeModule(const std::shared_ptr& module); IncrementalExecutor& getParent() const { return m_Parent; } void RemoveUnfinalizedSection( - llvm::orc::RTDyldObjectLinkingLayerBase::ObjSetHandleT H) { + llvm::orc::RTDyldObjectLinkingLayerBase::ObjHandleT H) { m_UnfinalizedSections.erase(H); }