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.
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
// 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();
|
||||
.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());
|
||||
|
@ -53,28 +53,24 @@ 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) {
|
||||
// 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)
|
||||
@ -90,9 +86,8 @@ private:
|
||||
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;
|
||||
}
|
||||
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,8 +187,14 @@ 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.
|
||||
@ -202,12 +203,12 @@ public:
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user