Follow recent LLVM changes.

The orc jit API evolved as follows:
  * Use better error handling via llvm::Error and llvm::Expected<>
  * Switch back to the single llvm::Module concept as opposed to sets.
  * Use more expressive ownership model: extensive use of smart ptrs.
This commit is contained in:
Vassil Vassilev 2017-10-12 15:48:03 +02:00 committed by sftnight
parent 6e1865dafb
commit 88c3d07bb9
3 changed files with 102 additions and 83 deletions

View File

@ -165,8 +165,9 @@ namespace cling {
///\brief Unload a set of JIT symbols.
bool unloadModule(const std::shared_ptr<llvm::Module>& 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;
}

View File

@ -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<uint64_t> 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<ClingMemoryManager>(m_Parent)),
m_ExeMM(std::make_shared<ClingMemoryManager>(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<llvm::Module>& 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<llvm::Module>& module) {
return JITSymbol(addr, llvm::JITSymbolFlags::Weak);
});
std::vector<llvm::Module*> moduleSet;
moduleSet.push_back(module.get());
ModuleSetHandleT MSHandle =
m_LazyEmitLayer.addModuleSet(std::move(moduleSet),
llvm::make_unique<Azog>(*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<llvm::Module>& module) {
llvm::Error
IncrementalJIT::removeModule(const std::shared_ptr<llvm::Module>& 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());

View File

@ -53,46 +53,41 @@ private:
class NotifyObjectLoadedT {
public:
typedef std::vector<std::unique_ptr<llvm::object::OwningBinary<llvm::object::ObjectFile>>> ObjListT;
typedef std::vector<std::unique_ptr<llvm::RuntimeDyld::LoadedObjectInfo>>
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<NotifyObjectLoadedT> {
public llvm::orc::RTDyldObjectLinkingLayer {
public:
using Base_t = llvm::orc::RTDyldObjectLinkingLayer<NotifyObjectLoadedT>;
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<llvm::JITEvaluatedSymbol>&
getSymbolTable() const {
return SymbolTable;
@ -131,23 +125,24 @@ private:
if (iterSymMap->second == NameSym.second.getAddress())
m_SymbolMap.erase(iterSymMap);
}
llvm::orc::RTDyldObjectLinkingLayer<NotifyObjectLoadedT>::removeObjectSet(H);
return llvm::orc::RTDyldObjectLinkingLayer::removeObject(H);
}
private:
SymbolMapT& m_SymbolMap;
};
typedef RemovableObjectLinkingLayer ObjectLayerT;
typedef llvm::orc::IRCompileLayer<ObjectLayerT> CompileLayerT;
typedef llvm::orc::IRCompileLayer<ObjectLayerT,
llvm::orc::SimpleCompiler> CompileLayerT;
typedef llvm::orc::LazyEmittingLayer<CompileLayerT> LazyEmitLayerT;
typedef LazyEmitLayerT::ModuleSetHandleT ModuleSetHandleT;
typedef LazyEmitLayerT::ModuleHandleT ModuleHandleT;
std::unique_ptr<llvm::TargetMachine> m_TM;
llvm::DataLayout m_TMDataLayout;
///\brief The RTDyldMemoryManager used to communicate with the
/// IncrementalExecutor to handle missing or special symbols.
std::unique_ptr<llvm::RTDyldMemoryManager> m_ExeMM;
std::shared_ptr<llvm::RTDyldMemoryManager> 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<const void *> 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<ObjectLayerT::ObjSetHandleT, SectionAddrSet, ObjSetHandleCompare>
std::map<ObjectLayerT::ObjHandleT, SectionAddrSet, ObjHandleCompare>
m_UnfinalizedSections;
///\brief Mapping between \c llvm::Module* and \c ModuleSetHandleT.
std::map<llvm::Module*, ModuleSetHandleT> m_UnloadPoints;
///\brief Mapping between \c llvm::Module* and \c ModuleHandleT.
std::map<llvm::Module*, ModuleHandleT> 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<uint64_t> 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<llvm::Module>& module);
void removeModule(const std::shared_ptr<llvm::Module>& module);
llvm::Error removeModule(const std::shared_ptr<llvm::Module>& module);
IncrementalExecutor& getParent() const { return m_Parent; }
void RemoveUnfinalizedSection(
llvm::orc::RTDyldObjectLinkingLayerBase::ObjSetHandleT H) {
llvm::orc::RTDyldObjectLinkingLayerBase::ObjHandleT H) {
m_UnfinalizedSections.erase(H);
}