#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
#define LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/ExecutionEngine/Orc/Speculation.h"
namespace llvm {
class Triple;
namespace orc {
class LazyCallThroughManager {
public:
using NotifyResolvedFunction =
unique_function<Error(JITTargetAddress ResolvedAddr)>;
LazyCallThroughManager(ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP);
Expected<JITTargetAddress>
getCallThroughTrampoline(JITDylib &SourceJD, SymbolStringPtr SymbolName,
NotifyResolvedFunction NotifyResolved);
void resolveTrampolineLandingAddress(
JITTargetAddress TrampolineAddr,
TrampolinePool::NotifyLandingResolvedFunction NotifyLandingResolved);
virtual ~LazyCallThroughManager() = default;
protected:
using NotifyLandingResolvedFunction =
TrampolinePool::NotifyLandingResolvedFunction;
struct ReexportsEntry {
JITDylib *SourceJD;
SymbolStringPtr SymbolName;
};
JITTargetAddress reportCallThroughError(Error Err);
Expected<ReexportsEntry> findReexport(JITTargetAddress TrampolineAddr);
Error notifyResolved(JITTargetAddress TrampolineAddr,
JITTargetAddress ResolvedAddr);
void setTrampolinePool(TrampolinePool &TP) { this->TP = &TP; }
private:
using ReexportsMap = std::map<JITTargetAddress, ReexportsEntry>;
using NotifiersMap = std::map<JITTargetAddress, NotifyResolvedFunction>;
std::mutex LCTMMutex;
ExecutionSession &ES;
JITTargetAddress ErrorHandlerAddr;
TrampolinePool *TP = nullptr;
ReexportsMap Reexports;
NotifiersMap Notifiers;
};
class LocalLazyCallThroughManager : public LazyCallThroughManager {
private:
using NotifyTargetResolved = unique_function<void(JITTargetAddress)>;
LocalLazyCallThroughManager(ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddr)
: LazyCallThroughManager(ES, ErrorHandlerAddr, nullptr) {}
template <typename ORCABI> Error init() {
auto TP = LocalTrampolinePool<ORCABI>::Create(
[this](JITTargetAddress TrampolineAddr,
TrampolinePool::NotifyLandingResolvedFunction
NotifyLandingResolved) {
resolveTrampolineLandingAddress(TrampolineAddr,
std::move(NotifyLandingResolved));
});
if (!TP)
return TP.takeError();
this->TP = std::move(*TP);
setTrampolinePool(*this->TP);
return Error::success();
}
std::unique_ptr<TrampolinePool> TP;
public:
template <typename ORCABI>
static Expected<std::unique_ptr<LocalLazyCallThroughManager>>
Create(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr) {
auto LLCTM = std::unique_ptr<LocalLazyCallThroughManager>(
new LocalLazyCallThroughManager(ES, ErrorHandlerAddr));
if (auto Err = LLCTM->init<ORCABI>())
return std::move(Err);
return std::move(LLCTM);
}
};
Expected<std::unique_ptr<LazyCallThroughManager>>
createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddr);
class LazyReexportsMaterializationUnit : public MaterializationUnit {
public:
LazyReexportsMaterializationUnit(LazyCallThroughManager &LCTManager,
IndirectStubsManager &ISManager,
JITDylib &SourceJD,
SymbolAliasMap CallableAliases,
ImplSymbolMap *SrcJDLoc);
StringRef getName() const override;
private:
void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
static MaterializationUnit::Interface
extractFlags(const SymbolAliasMap &Aliases);
LazyCallThroughManager &LCTManager;
IndirectStubsManager &ISManager;
JITDylib &SourceJD;
SymbolAliasMap CallableAliases;
ImplSymbolMap *AliaseeTable;
};
inline std::unique_ptr<LazyReexportsMaterializationUnit>
lazyReexports(LazyCallThroughManager &LCTManager,
IndirectStubsManager &ISManager, JITDylib &SourceJD,
SymbolAliasMap CallableAliases,
ImplSymbolMap *SrcJDLoc = nullptr) {
return std::make_unique<LazyReexportsMaterializationUnit>(
LCTManager, ISManager, SourceJD, std::move(CallableAliases), SrcJDLoc);
}
} }
#endif