LazyEmittingLayer.h [plain text]
#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
#define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
#include "JITSymbol.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include <list>
namespace llvm {
namespace orc {
template <typename BaseLayerT> class LazyEmittingLayer {
public:
typedef typename BaseLayerT::ModuleSetHandleT BaseLayerHandleT;
private:
class EmissionDeferredSet {
public:
EmissionDeferredSet() : EmitState(NotEmitted) {}
virtual ~EmissionDeferredSet() {}
JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
switch (EmitState) {
case NotEmitted:
if (auto GV = searchGVs(Name, ExportedSymbolsOnly)) {
std::string PName = Name;
JITSymbolFlags Flags = JITSymbolBase::flagsFromGlobalValue(*GV);
auto GetAddress =
[this, ExportedSymbolsOnly, PName, &B]() -> TargetAddress {
if (this->EmitState == Emitting)
return 0;
else if (this->EmitState == NotEmitted) {
this->EmitState = Emitting;
Handle = this->emitToBaseLayer(B);
this->EmitState = Emitted;
}
auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly);
return Sym.getAddress();
};
return JITSymbol(std::move(GetAddress), Flags);
} else
return nullptr;
case Emitting:
return nullptr;
case Emitted:
return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
}
llvm_unreachable("Invalid emit-state.");
}
void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
if (EmitState != NotEmitted)
BaseLayer.removeModuleSet(Handle);
}
void emitAndFinalize(BaseLayerT &BaseLayer) {
assert(EmitState != Emitting &&
"Cannot emitAndFinalize while already emitting");
if (EmitState == NotEmitted) {
EmitState = Emitting;
Handle = emitToBaseLayer(BaseLayer);
EmitState = Emitted;
}
BaseLayer.emitAndFinalize(Handle);
}
template <typename ModuleSetT, typename MemoryManagerPtrT,
typename SymbolResolverPtrT>
static std::unique_ptr<EmissionDeferredSet>
create(BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver);
protected:
virtual const GlobalValue* searchGVs(StringRef Name,
bool ExportedSymbolsOnly) const = 0;
virtual BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) = 0;
private:
enum { NotEmitted, Emitting, Emitted } EmitState;
BaseLayerHandleT Handle;
};
template <typename ModuleSetT, typename MemoryManagerPtrT,
typename SymbolResolverPtrT>
class EmissionDeferredSetImpl : public EmissionDeferredSet {
public:
EmissionDeferredSetImpl(ModuleSetT Ms,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver)
: Ms(std::move(Ms)), MemMgr(std::move(MemMgr)),
Resolver(std::move(Resolver)) {}
protected:
const GlobalValue* searchGVs(StringRef Name,
bool ExportedSymbolsOnly) const override {
if (MangledSymbols) {
auto VI = MangledSymbols->find(Name);
if (VI == MangledSymbols->end())
return nullptr;
auto GV = VI->second;
if (!ExportedSymbolsOnly || GV->hasDefaultVisibility())
return GV;
return nullptr;
}
return buildMangledSymbols(Name, ExportedSymbolsOnly);
}
BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) override {
MangledSymbols.reset();
return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr),
std::move(Resolver));
}
private:
const GlobalValue* addGlobalValue(StringMap<const GlobalValue*> &Names,
const GlobalValue &GV,
const Mangler &Mang, StringRef SearchName,
bool ExportedSymbolsOnly) const {
if (GV.isDeclaration() || GV.hasCommonLinkage())
return nullptr;
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mang.getNameWithPrefix(MangledNameStream, &GV, false);
}
if (MangledName == SearchName)
if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
return &GV;
Names[MangledName] = &GV;
return nullptr;
}
const GlobalValue* buildMangledSymbols(StringRef SearchName,
bool ExportedSymbolsOnly) const {
assert(!MangledSymbols && "Mangled symbols map already exists?");
auto Symbols = llvm::make_unique<StringMap<const GlobalValue*>>();
for (const auto &M : Ms) {
Mangler Mang;
for (const auto &V : M->globals())
if (auto GV = addGlobalValue(*Symbols, V, Mang, SearchName,
ExportedSymbolsOnly))
return GV;
for (const auto &F : *M)
if (auto GV = addGlobalValue(*Symbols, F, Mang, SearchName,
ExportedSymbolsOnly))
return GV;
}
MangledSymbols = std::move(Symbols);
return nullptr;
}
ModuleSetT Ms;
MemoryManagerPtrT MemMgr;
SymbolResolverPtrT Resolver;
mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
};
typedef std::list<std::unique_ptr<EmissionDeferredSet>> ModuleSetListT;
BaseLayerT &BaseLayer;
ModuleSetListT ModuleSetList;
public:
typedef typename ModuleSetListT::iterator ModuleSetHandleT;
LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
template <typename ModuleSetT, typename MemoryManagerPtrT,
typename SymbolResolverPtrT>
ModuleSetHandleT addModuleSet(ModuleSetT Ms,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
return ModuleSetList.insert(
ModuleSetList.end(),
EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MemMgr),
std::move(Resolver)));
}
void removeModuleSet(ModuleSetHandleT H) {
(*H)->removeModulesFromBaseLayer(BaseLayer);
ModuleSetList.erase(H);
}
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
return Symbol;
for (auto &DeferredSet : ModuleSetList)
if (auto Symbol = DeferredSet->find(Name, ExportedSymbolsOnly, BaseLayer))
return Symbol;
return nullptr;
}
JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
bool ExportedSymbolsOnly) {
return (*H)->find(Name, ExportedSymbolsOnly, BaseLayer);
}
void emitAndFinalize(ModuleSetHandleT H) {
(*H)->emitAndFinalize(BaseLayer);
}
};
template <typename BaseLayerT>
template <typename ModuleSetT, typename MemoryManagerPtrT,
typename SymbolResolverPtrT>
std::unique_ptr<typename LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet>
LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet::create(
BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
typedef EmissionDeferredSetImpl<ModuleSetT, MemoryManagerPtrT, SymbolResolverPtrT>
EDS;
return llvm::make_unique<EDS>(std::move(Ms), std::move(MemMgr),
std::move(Resolver));
}
} }
#endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H