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:
parent
6e1865dafb
commit
88c3d07bb9
@ -165,8 +165,9 @@ namespace cling {
|
|||||||
|
|
||||||
///\brief Unload a set of JIT symbols.
|
///\brief Unload a set of JIT symbols.
|
||||||
bool unloadModule(const std::shared_ptr<llvm::Module>& M) {
|
bool unloadModule(const std::shared_ptr<llvm::Module>& M) {
|
||||||
m_JIT->removeModule(M);
|
// FIXME: Propagate the error in a more verbose way.
|
||||||
// FIXME: Propagate if we removed a module or not.
|
if (auto Err = m_JIT->removeModule(M))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "cling/Utils/Platform.h"
|
#include "cling/Utils/Platform.h"
|
||||||
|
|
||||||
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
|
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
|
||||||
|
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
||||||
#include "llvm/Support/DynamicLibrary.h"
|
#include "llvm/Support/DynamicLibrary.h"
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@ -41,7 +42,7 @@ public:
|
|||||||
class NotifyFinalizedT {
|
class NotifyFinalizedT {
|
||||||
public:
|
public:
|
||||||
NotifyFinalizedT(cling::IncrementalJIT &jit) : m_JIT(jit) {}
|
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);
|
m_JIT.RemoveUnfinalizedSection(H);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,9 +221,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t getSymbolAddress(const std::string &Name) override {
|
uint64_t getSymbolAddress(const std::string &Name) override {
|
||||||
return m_jit.getSymbolAddressWithoutMangling(Name,
|
// 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*/)
|
true /*also use dlsym*/)
|
||||||
.getAddress();
|
.getAddress())
|
||||||
|
return *Addr;
|
||||||
|
|
||||||
|
return ~0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *getPointerToNamedFunction(const std::string &Name,
|
void *getPointerToNamedFunction(const std::string &Name,
|
||||||
@ -267,9 +274,10 @@ IncrementalJIT::IncrementalJIT(IncrementalExecutor& exe,
|
|||||||
m_Parent(exe),
|
m_Parent(exe),
|
||||||
m_TM(std::move(TM)),
|
m_TM(std::move(TM)),
|
||||||
m_TMDataLayout(m_TM->createDataLayout()),
|
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_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_CompileLayer(m_ObjectLayer, llvm::orc::SimpleCompiler(*m_TM)),
|
||||||
m_LazyEmitLayer(m_CompileLayer) {
|
m_LazyEmitLayer(m_CompileLayer) {
|
||||||
|
|
||||||
@ -343,9 +351,12 @@ IncrementalJIT::getSymbolAddressWithoutMangling(const std::string& Name,
|
|||||||
return Sym;
|
return Sym;
|
||||||
|
|
||||||
if (AlsoInProcess) {
|
if (AlsoInProcess) {
|
||||||
if (llvm::JITSymbol SymInfo = m_ExeMM->findSymbol(Name))
|
if (llvm::JITSymbol SymInfo = m_ExeMM->findSymbol(Name)) {
|
||||||
return llvm::JITSymbol(SymInfo.getAddress(),
|
if (auto AddrOrErr = SymInfo.getAddress())
|
||||||
llvm::JITSymbolFlags::Exported);
|
return llvm::JITSymbol(*AddrOrErr, llvm::JITSymbolFlags::Exported);
|
||||||
|
else
|
||||||
|
llvm_unreachable("Handle the error case");
|
||||||
|
}
|
||||||
#ifdef LLVM_ON_WIN32
|
#ifdef LLVM_ON_WIN32
|
||||||
// FIXME: DLSym symbol lookup can overlap m_ExeMM->findSymbol wasting time
|
// 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.
|
// 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.
|
// LLVM MERGE FIXME: update this to use new interfaces.
|
||||||
auto Resolver = llvm::orc::createLambdaResolver(
|
auto Resolver = llvm::orc::createLambdaResolver(
|
||||||
[&](const std::string &S) {
|
[&](const std::string &S) {
|
||||||
if (auto Sym = getInjectedSymbols(S))
|
if (auto Sym = getInjectedSymbols(S)) {
|
||||||
return JITSymbol((uint64_t)Sym.getAddress(), Sym.getFlags());
|
if (auto AddrOrErr = Sym.getAddress())
|
||||||
|
return JITSymbol((uint64_t)*AddrOrErr, Sym.getFlags());
|
||||||
|
else
|
||||||
|
llvm_unreachable("Handle the error case");
|
||||||
|
}
|
||||||
return m_ExeMM->findSymbol(S);
|
return m_ExeMM->findSymbol(S);
|
||||||
},
|
},
|
||||||
[&](const std::string &Name) {
|
[&](const std::string &Name) {
|
||||||
if (auto Sym = getSymbolAddressWithoutMangling(Name, true))
|
if (auto Sym = getSymbolAddressWithoutMangling(Name, true)) {
|
||||||
return JITSymbol(Sym.getAddress(), Sym.getFlags());
|
if (auto AddrOrErr = Sym.getAddress())
|
||||||
|
return JITSymbol(*AddrOrErr, Sym.getFlags());
|
||||||
|
else
|
||||||
|
llvm_unreachable("Handle the error case");
|
||||||
|
}
|
||||||
|
|
||||||
const std::string* NameNP = &Name;
|
const std::string* NameNP = &Name;
|
||||||
#ifdef MANGLE_PREFIX
|
#ifdef MANGLE_PREFIX
|
||||||
@ -401,16 +420,14 @@ void IncrementalJIT::addModule(const std::shared_ptr<llvm::Module>& module) {
|
|||||||
return JITSymbol(addr, llvm::JITSymbolFlags::Weak);
|
return JITSymbol(addr, llvm::JITSymbolFlags::Weak);
|
||||||
});
|
});
|
||||||
|
|
||||||
std::vector<llvm::Module*> moduleSet;
|
if (auto H = m_LazyEmitLayer.addModule(module, std::move(Resolver)))
|
||||||
moduleSet.push_back(module.get());
|
m_UnloadPoints[module.get()] = *H;
|
||||||
ModuleSetHandleT MSHandle =
|
else
|
||||||
m_LazyEmitLayer.addModuleSet(std::move(moduleSet),
|
llvm_unreachable("Handle the error case");
|
||||||
llvm::make_unique<Azog>(*this),
|
|
||||||
std::move(Resolver));
|
|
||||||
m_UnloadPoints[module.get()] = MSHandle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// 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.
|
// this is resolved we can remove this check enabling the assert.
|
||||||
auto IUnload = m_UnloadPoints.find(module.get());
|
auto IUnload = m_UnloadPoints.find(module.get());
|
||||||
|
@ -53,28 +53,24 @@ private:
|
|||||||
|
|
||||||
class NotifyObjectLoadedT {
|
class NotifyObjectLoadedT {
|
||||||
public:
|
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) {}
|
NotifyObjectLoadedT(IncrementalJIT &jit) : m_JIT(jit) {}
|
||||||
|
void operator()(llvm::orc::RTDyldObjectLinkingLayerBase::ObjHandleT H,
|
||||||
void operator()(llvm::orc::RTDyldObjectLinkingLayerBase::ObjSetHandleT H,
|
const llvm::orc::RTDyldObjectLinkingLayer::ObjectPtr &Object,
|
||||||
const ObjListT &Objects,
|
const llvm::LoadedObjectInfo &Info) const {
|
||||||
const LoadedObjInfoListT &Infos) const
|
|
||||||
{
|
|
||||||
m_JIT.m_UnfinalizedSections[H]
|
m_JIT.m_UnfinalizedSections[H]
|
||||||
= std::move(m_JIT.m_SectionsAllocatedSinceLastLoad);
|
= std::move(m_JIT.m_SectionsAllocatedSinceLastLoad);
|
||||||
m_JIT.m_SectionsAllocatedSinceLastLoad = SectionAddrSet();
|
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) {
|
// 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()) {
|
for (const auto &Symbol: Object->getBinary()->symbols()) {
|
||||||
auto Flags = Symbol.getFlags();
|
auto Flags = Symbol.getFlags();
|
||||||
if (Flags & llvm::object::BasicSymbolRef::SF_Undefined)
|
if (Flags & llvm::object::BasicSymbolRef::SF_Undefined)
|
||||||
@ -90,9 +86,8 @@ private:
|
|||||||
if (m_JIT.m_SymbolMap.find(Name) == m_JIT.m_SymbolMap.end()) {
|
if (m_JIT.m_SymbolMap.find(Name) == m_JIT.m_SymbolMap.end()) {
|
||||||
llvm::JITSymbol Sym
|
llvm::JITSymbol Sym
|
||||||
= m_JIT.m_CompileLayer.findSymbolIn(H, Name, true);
|
= m_JIT.m_CompileLayer.findSymbolIn(H, Name, true);
|
||||||
if (llvm::JITTargetAddress Addr = Sym.getAddress())
|
if (auto Addr = Sym.getAddress())
|
||||||
m_JIT.m_SymbolMap[Name] = Addr;
|
m_JIT.m_SymbolMap[Name] = *Addr;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,22 +95,21 @@ private:
|
|||||||
private:
|
private:
|
||||||
IncrementalJIT &m_JIT;
|
IncrementalJIT &m_JIT;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RemovableObjectLinkingLayer:
|
class RemovableObjectLinkingLayer:
|
||||||
public llvm::orc::RTDyldObjectLinkingLayer<NotifyObjectLoadedT> {
|
public llvm::orc::RTDyldObjectLinkingLayer {
|
||||||
public:
|
public:
|
||||||
using Base_t = llvm::orc::RTDyldObjectLinkingLayer<NotifyObjectLoadedT>;
|
using Base_t = llvm::orc::RTDyldObjectLinkingLayer;
|
||||||
using NotifyLoadedFtor = NotifyObjectLoadedT;
|
|
||||||
using NotifyFinalizedFtor = Base_t::NotifyFinalizedFtor;
|
using NotifyFinalizedFtor = Base_t::NotifyFinalizedFtor;
|
||||||
RemovableObjectLinkingLayer(SymbolMapT &SymMap,
|
RemovableObjectLinkingLayer(SymbolMapT &SymMap,
|
||||||
|
Base_t::MemoryManagerGetter MM,
|
||||||
NotifyObjectLoadedT NotifyLoaded,
|
NotifyObjectLoadedT NotifyLoaded,
|
||||||
NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()):
|
NotifyFinalizedFtor NotifyFinalized)
|
||||||
Base_t(NotifyLoaded, NotifyFinalized), m_SymbolMap(SymMap)
|
: Base_t(MM, NotifyLoaded, NotifyFinalized), m_SymbolMap(SymMap)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void
|
llvm::Error
|
||||||
removeObjectSet(llvm::orc::RTDyldObjectLinkingLayerBase::ObjSetHandleT H) {
|
removeObject(llvm::orc::RTDyldObjectLinkingLayerBase::ObjHandleT H) {
|
||||||
struct AccessSymbolTable: public LinkedObjectSet {
|
struct AccessSymbolTable: public LinkedObject {
|
||||||
const llvm::StringMap<llvm::JITEvaluatedSymbol>&
|
const llvm::StringMap<llvm::JITEvaluatedSymbol>&
|
||||||
getSymbolTable() const {
|
getSymbolTable() const {
|
||||||
return SymbolTable;
|
return SymbolTable;
|
||||||
@ -131,23 +125,24 @@ private:
|
|||||||
if (iterSymMap->second == NameSym.second.getAddress())
|
if (iterSymMap->second == NameSym.second.getAddress())
|
||||||
m_SymbolMap.erase(iterSymMap);
|
m_SymbolMap.erase(iterSymMap);
|
||||||
}
|
}
|
||||||
llvm::orc::RTDyldObjectLinkingLayer<NotifyObjectLoadedT>::removeObjectSet(H);
|
return llvm::orc::RTDyldObjectLinkingLayer::removeObject(H);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
SymbolMapT& m_SymbolMap;
|
SymbolMapT& m_SymbolMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef RemovableObjectLinkingLayer ObjectLayerT;
|
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 llvm::orc::LazyEmittingLayer<CompileLayerT> LazyEmitLayerT;
|
||||||
typedef LazyEmitLayerT::ModuleSetHandleT ModuleSetHandleT;
|
typedef LazyEmitLayerT::ModuleHandleT ModuleHandleT;
|
||||||
|
|
||||||
std::unique_ptr<llvm::TargetMachine> m_TM;
|
std::unique_ptr<llvm::TargetMachine> m_TM;
|
||||||
llvm::DataLayout m_TMDataLayout;
|
llvm::DataLayout m_TMDataLayout;
|
||||||
|
|
||||||
///\brief The RTDyldMemoryManager used to communicate with the
|
///\brief The RTDyldMemoryManager used to communicate with the
|
||||||
/// IncrementalExecutor to handle missing or special symbols.
|
/// IncrementalExecutor to handle missing or special symbols.
|
||||||
std::unique_ptr<llvm::RTDyldMemoryManager> m_ExeMM;
|
std::shared_ptr<llvm::RTDyldMemoryManager> m_ExeMM;
|
||||||
|
|
||||||
NotifyObjectLoadedT m_NotifyObjectLoaded;
|
NotifyObjectLoadedT m_NotifyObjectLoaded;
|
||||||
|
|
||||||
@ -155,22 +150,22 @@ private:
|
|||||||
CompileLayerT m_CompileLayer;
|
CompileLayerT m_CompileLayer;
|
||||||
LazyEmitLayerT m_LazyEmitLayer;
|
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
|
// that have been emitted but not yet finalized so that we can forward the
|
||||||
// mapSectionAddress calls appropriately.
|
// mapSectionAddress calls appropriately.
|
||||||
typedef std::set<const void *> SectionAddrSet;
|
typedef std::set<const void *> SectionAddrSet;
|
||||||
struct ObjSetHandleCompare {
|
struct ObjHandleCompare {
|
||||||
bool operator()(ObjectLayerT::ObjSetHandleT H1,
|
bool operator()(ObjectLayerT::ObjHandleT H1,
|
||||||
ObjectLayerT::ObjSetHandleT H2) const {
|
ObjectLayerT::ObjHandleT H2) const {
|
||||||
return &*H1 < &*H2;
|
return &*H1 < &*H2;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
SectionAddrSet m_SectionsAllocatedSinceLastLoad;
|
SectionAddrSet m_SectionsAllocatedSinceLastLoad;
|
||||||
std::map<ObjectLayerT::ObjSetHandleT, SectionAddrSet, ObjSetHandleCompare>
|
std::map<ObjectLayerT::ObjHandleT, SectionAddrSet, ObjHandleCompare>
|
||||||
m_UnfinalizedSections;
|
m_UnfinalizedSections;
|
||||||
|
|
||||||
///\brief Mapping between \c llvm::Module* and \c ModuleSetHandleT.
|
///\brief Mapping between \c llvm::Module* and \c ModuleHandleT.
|
||||||
std::map<llvm::Module*, ModuleSetHandleT> m_UnloadPoints;
|
std::map<llvm::Module*, ModuleHandleT> m_UnloadPoints;
|
||||||
|
|
||||||
std::string Mangle(llvm::StringRef Name) {
|
std::string Mangle(llvm::StringRef Name) {
|
||||||
stdstrstream MangledName;
|
stdstrstream MangledName;
|
||||||
@ -192,8 +187,14 @@ public:
|
|||||||
/// \param AlsoInProcess - Sometimes you only care about JITed symbols. If so,
|
/// \param AlsoInProcess - Sometimes you only care about JITed symbols. If so,
|
||||||
/// pass `false` here to not resolve the symbol through dlsym().
|
/// pass `false` here to not resolve the symbol through dlsym().
|
||||||
uint64_t getSymbolAddress(const std::string& Name, bool AlsoInProcess) {
|
uint64_t getSymbolAddress(const std::string& Name, bool AlsoInProcess) {
|
||||||
return getSymbolAddressWithoutMangling(Mangle(Name), AlsoInProcess)
|
// FIXME: We should decide if we want to handle the error here or make the
|
||||||
.getAddress();
|
// 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.
|
///\brief Get the address of a symbol from the JIT or the memory manager.
|
||||||
@ -202,12 +203,12 @@ public:
|
|||||||
bool AlsoInProcess);
|
bool AlsoInProcess);
|
||||||
|
|
||||||
void addModule(const std::shared_ptr<llvm::Module>& module);
|
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; }
|
IncrementalExecutor& getParent() const { return m_Parent; }
|
||||||
|
|
||||||
void RemoveUnfinalizedSection(
|
void RemoveUnfinalizedSection(
|
||||||
llvm::orc::RTDyldObjectLinkingLayerBase::ObjSetHandleT H) {
|
llvm::orc::RTDyldObjectLinkingLayerBase::ObjHandleT H) {
|
||||||
m_UnfinalizedSections.erase(H);
|
m_UnfinalizedSections.erase(H);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user