summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h226
-rw-r--r--llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h35
-rw-r--r--llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp34
-rw-r--r--llvm/lib/ExecutionEngine/Orc/LLJIT.cpp14
-rw-r--r--llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h91
-rw-r--r--llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp13
6 files changed, 285 insertions, 128 deletions
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
index a8a32bfaeee..8842dd1a5be 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
@@ -47,92 +47,101 @@ class Value;
namespace orc {
-/// Target-independent base class for compile callback management.
-class JITCompileCallbackManager {
+/// Base class for pools of compiler re-entry trampolines.
+/// These trampolines are callable addresses that save all register state
+/// before calling a supplied function to return the trampoline landing
+/// address, then restore all state before jumping to that address. They
+/// are used by various ORC APIs to support lazy compilation
+class TrampolinePool {
public:
- using CompileFunction = std::function<JITTargetAddress()>;
-
- /// Construct a JITCompileCallbackManager.
- /// @param ErrorHandlerAddress The address of an error handler in the target
- /// process to be used if a compile callback fails.
- JITCompileCallbackManager(ExecutionSession &ES,
- JITTargetAddress ErrorHandlerAddress)
- : ES(ES), CallbacksJD(ES.createJITDylib("<Callbacks>")),
- ErrorHandlerAddress(ErrorHandlerAddress) {}
+ virtual ~TrampolinePool() {}
- virtual ~JITCompileCallbackManager() = default;
+ /// Get an available trampoline address.
+ /// Returns an error if no trampoline can be created.
+ virtual Expected<JITTargetAddress> getTrampoline() = 0;
- /// Reserve a compile callback.
- Expected<JITTargetAddress> getCompileCallback(CompileFunction Compile);
-
- /// Execute the callback for the given trampoline id. Called by the JIT
- /// to compile functions on demand.
- JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr);
+private:
+ virtual void anchor();
+};
-protected:
- std::vector<JITTargetAddress> AvailableTrampolines;
+/// A trampoline pool for trampolines within the current process.
+template <typename ORCABI> class LocalTrampolinePool : public TrampolinePool {
+public:
+ using GetTrampolineLandingFunction =
+ std::function<JITTargetAddress(JITTargetAddress TrampolineAddr)>;
+
+ /// Creates a LocalTrampolinePool with the given RunCallback function.
+ /// Returns an error if this function is unable to correctly allocate, write
+ /// and protect the resolver code block.
+ static Expected<std::unique_ptr<LocalTrampolinePool>>
+ Create(GetTrampolineLandingFunction GetTrampolineLanding) {
+ Error Err = Error::success();
+
+ auto LTP = std::unique_ptr<LocalTrampolinePool>(
+ new LocalTrampolinePool(std::move(GetTrampolineLanding), Err));
+
+ if (Err)
+ return std::move(Err);
+ return std::move(LTP);
+ }
-private:
- Expected<JITTargetAddress> getAvailableTrampolineAddr() {
- if (this->AvailableTrampolines.empty())
+ /// Get a free trampoline. Returns an error if one can not be provide (e.g.
+ /// because the pool is empty and can not be grown).
+ Expected<JITTargetAddress> getTrampoline() override {
+ std::lock_guard<std::mutex> Lock(LTPMutex);
+ if (AvailableTrampolines.empty()) {
if (auto Err = grow())
return std::move(Err);
- assert(!this->AvailableTrampolines.empty() &&
- "Failed to grow available trampolines.");
- JITTargetAddress TrampolineAddr = this->AvailableTrampolines.back();
- this->AvailableTrampolines.pop_back();
+ }
+ assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool");
+ auto TrampolineAddr = AvailableTrampolines.back();
+ AvailableTrampolines.pop_back();
return TrampolineAddr;
}
- // Create new trampolines - to be implemented in subclasses.
- virtual Error grow() = 0;
+ /// Returns the given trampoline to the pool for re-use.
+ void releaseTrampoline(JITTargetAddress TrampolineAddr) {
+ std::lock_guard<std::mutex> Lock(LTPMutex);
+ AvailableTrampolines.push_back(TrampolineAddr);
+ }
- virtual void anchor();
+private:
+ static JITTargetAddress reenter(void *TrampolinePoolPtr, void *TrampolineId) {
+ LocalTrampolinePool<ORCABI> *TrampolinePool =
+ static_cast<LocalTrampolinePool *>(TrampolinePoolPtr);
+ return TrampolinePool->GetTrampolineLanding(static_cast<JITTargetAddress>(
+ reinterpret_cast<uintptr_t>(TrampolineId)));
+ }
- std::mutex CCMgrMutex;
- ExecutionSession &ES;
- JITDylib &CallbacksJD;
- JITTargetAddress ErrorHandlerAddress;
- std::map<JITTargetAddress, SymbolStringPtr> AddrToSymbol;
- size_t NextCallbackId = 0;
-};
+ LocalTrampolinePool(GetTrampolineLandingFunction GetTrampolineLanding,
+ Error &Err)
+ : GetTrampolineLanding(std::move(GetTrampolineLanding)) {
-/// Manage compile callbacks for in-process JITs.
-template <typename TargetT>
-class LocalJITCompileCallbackManager : public JITCompileCallbackManager {
-public:
- /// Construct a InProcessJITCompileCallbackManager.
- /// @param ErrorHandlerAddress The address of an error handler in the target
- /// process to be used if a compile callback fails.
- LocalJITCompileCallbackManager(ExecutionSession &ES,
- JITTargetAddress ErrorHandlerAddress)
- : JITCompileCallbackManager(ES, ErrorHandlerAddress) {
- /// Set up the resolver block.
+ ErrorAsOutParameter _(&Err);
+
+ /// Try to set up the resolver block.
std::error_code EC;
ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
- TargetT::ResolverCodeSize, nullptr,
+ ORCABI::ResolverCodeSize, nullptr,
sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
- assert(!EC && "Failed to allocate resolver block");
+ if (EC) {
+ Err = errorCodeToError(EC);
+ return;
+ }
- TargetT::writeResolverCode(static_cast<uint8_t *>(ResolverBlock.base()),
- &reenter, this);
+ ORCABI::writeResolverCode(static_cast<uint8_t *>(ResolverBlock.base()),
+ &reenter, this);
EC = sys::Memory::protectMappedMemory(ResolverBlock.getMemoryBlock(),
sys::Memory::MF_READ |
sys::Memory::MF_EXEC);
- assert(!EC && "Failed to mprotect resolver block");
- }
-
-private:
- static JITTargetAddress reenter(void *CCMgr, void *TrampolineId) {
- JITCompileCallbackManager *Mgr =
- static_cast<JITCompileCallbackManager *>(CCMgr);
- return Mgr->executeCompileCallback(
- static_cast<JITTargetAddress>(
- reinterpret_cast<uintptr_t>(TrampolineId)));
+ if (EC) {
+ Err = errorCodeToError(EC);
+ return;
+ }
}
- Error grow() override {
+ Error grow() {
assert(this->AvailableTrampolines.empty() && "Growing prematurely?");
std::error_code EC;
@@ -144,17 +153,17 @@ private:
return errorCodeToError(EC);
unsigned NumTrampolines =
- (sys::Process::getPageSize() - TargetT::PointerSize) /
- TargetT::TrampolineSize;
+ (sys::Process::getPageSize() - ORCABI::PointerSize) /
+ ORCABI::TrampolineSize;
uint8_t *TrampolineMem = static_cast<uint8_t *>(TrampolineBlock.base());
- TargetT::writeTrampolines(TrampolineMem, ResolverBlock.base(),
- NumTrampolines);
+ ORCABI::writeTrampolines(TrampolineMem, ResolverBlock.base(),
+ NumTrampolines);
for (unsigned I = 0; I < NumTrampolines; ++I)
this->AvailableTrampolines.push_back(
static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(
- TrampolineMem + (I * TargetT::TrampolineSize))));
+ TrampolineMem + (I * ORCABI::TrampolineSize))));
if (auto EC = sys::Memory::protectMappedMemory(
TrampolineBlock.getMemoryBlock(),
@@ -165,8 +174,87 @@ private:
return Error::success();
}
+ GetTrampolineLandingFunction GetTrampolineLanding;
+
+ std::mutex LTPMutex;
sys::OwningMemoryBlock ResolverBlock;
std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
+ std::vector<JITTargetAddress> AvailableTrampolines;
+};
+
+/// Target-independent base class for compile callback management.
+class JITCompileCallbackManager {
+public:
+ using CompileFunction = std::function<JITTargetAddress()>;
+
+ virtual ~JITCompileCallbackManager() = default;
+
+ /// Reserve a compile callback.
+ Expected<JITTargetAddress> getCompileCallback(CompileFunction Compile);
+
+ /// Execute the callback for the given trampoline id. Called by the JIT
+ /// to compile functions on demand.
+ JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr);
+
+protected:
+ /// Construct a JITCompileCallbackManager.
+ JITCompileCallbackManager(std::unique_ptr<TrampolinePool> TP,
+ ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddress)
+ : TP(std::move(TP)), ES(ES),
+ CallbacksJD(ES.createJITDylib("<Callbacks>")),
+ ErrorHandlerAddress(ErrorHandlerAddress) {}
+
+ void setTrampolinePool(std::unique_ptr<TrampolinePool> TP) {
+ this->TP = std::move(TP);
+ }
+
+private:
+ std::mutex CCMgrMutex;
+ std::unique_ptr<TrampolinePool> TP;
+ ExecutionSession &ES;
+ JITDylib &CallbacksJD;
+ JITTargetAddress ErrorHandlerAddress;
+ std::map<JITTargetAddress, SymbolStringPtr> AddrToSymbol;
+ size_t NextCallbackId = 0;
+};
+
+/// Manage compile callbacks for in-process JITs.
+template <typename ORCABI>
+class LocalJITCompileCallbackManager : public JITCompileCallbackManager {
+public:
+ /// Create a new LocalJITCompileCallbackManager.
+ static Expected<std::unique_ptr<LocalJITCompileCallbackManager>>
+ Create(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddress) {
+ Error Err = Error::success();
+ auto CCMgr = std::unique_ptr<LocalJITCompileCallbackManager>(
+ new LocalJITCompileCallbackManager(ES, ErrorHandlerAddress, Err));
+ if (Err)
+ return std::move(Err);
+ return std::move(CCMgr);
+ }
+
+private:
+ /// Construct a InProcessJITCompileCallbackManager.
+ /// @param ErrorHandlerAddress The address of an error handler in the target
+ /// process to be used if a compile callback fails.
+ LocalJITCompileCallbackManager(ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddress,
+ Error &Err)
+ : JITCompileCallbackManager(nullptr, ES, ErrorHandlerAddress) {
+ ErrorAsOutParameter _(&Err);
+ auto TP = LocalTrampolinePool<ORCABI>::Create(
+ [this](JITTargetAddress TrampolineAddr) {
+ return executeCompileCallback(TrampolineAddr);
+ });
+
+ if (!TP) {
+ Err = TP.takeError();
+ return;
+ }
+
+ setTrampolinePool(std::move(*TP));
+ }
};
/// Base class for managing collections of named indirect stubs.
@@ -299,7 +387,7 @@ private:
/// The given target triple will determine the ABI, and the given
/// ErrorHandlerAddress will be used by the resulting compile callback
/// manager if a compile callback fails.
-std::unique_ptr<JITCompileCallbackManager>
+Expected<std::unique_ptr<JITCompileCallbackManager>>
createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddress);
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
index 739e5ba47c1..4cbf19ac254 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
@@ -447,16 +447,24 @@ public:
StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
};
- /// Remote compile callback manager.
- class RemoteCompileCallbackManager : public JITCompileCallbackManager {
+ class RemoteTrampolinePool : public TrampolinePool {
public:
- RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
- ExecutionSession &ES,
- JITTargetAddress ErrorHandlerAddress)
- : JITCompileCallbackManager(ES, ErrorHandlerAddress), Client(Client) {}
+ RemoteTrampolinePool(OrcRemoteTargetClient &Client) : Client(Client) {}
+
+ Expected<JITTargetAddress> getTrampoline() override {
+ std::lock_guard<std::mutex> Lock(RTPMutex);
+ if (AvailableTrampolines.empty()) {
+ if (auto Err = grow())
+ return std::move(Err);
+ }
+ assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool");
+ auto TrampolineAddr = AvailableTrampolines.back();
+ AvailableTrampolines.pop_back();
+ return TrampolineAddr;
+ }
private:
- Error grow() override {
+ Error grow() {
JITTargetAddress BlockAddr = 0;
uint32_t NumTrampolines = 0;
if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock())
@@ -471,7 +479,20 @@ public:
return Error::success();
}
+ std::mutex RTPMutex;
OrcRemoteTargetClient &Client;
+ std::vector<JITTargetAddress> AvailableTrampolines;
+ };
+
+ /// Remote compile callback manager.
+ class RemoteCompileCallbackManager : public JITCompileCallbackManager {
+ public:
+ RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
+ ExecutionSession &ES,
+ JITTargetAddress ErrorHandlerAddress)
+ : JITCompileCallbackManager(
+ llvm::make_unique<RemoteTrampolinePool>(Client), ES,
+ ErrorHandlerAddress) {}
};
/// Create an OrcRemoteTargetClient.
diff --git a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
index 80a227f0a1e..54baed237b2 100644
--- a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
@@ -52,12 +52,12 @@ private:
namespace llvm {
namespace orc {
-void JITCompileCallbackManager::anchor() {}
void IndirectStubsManager::anchor() {}
+void TrampolinePool::anchor() {}
Expected<JITTargetAddress>
JITCompileCallbackManager::getCompileCallback(CompileFunction Compile) {
- if (auto TrampolineAddr = getAvailableTrampolineAddr()) {
+ if (auto TrampolineAddr = TP->getTrampoline()) {
auto CallbackName = ES.getSymbolStringPool().intern(
std::string("cc") + std::to_string(++NextCallbackId));
@@ -107,44 +107,46 @@ JITTargetAddress JITCompileCallbackManager::executeCompileCallback(
}
}
-std::unique_ptr<JITCompileCallbackManager>
+Expected<std::unique_ptr<JITCompileCallbackManager>>
createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddress) {
switch (T.getArch()) {
- default: return nullptr;
-
- case Triple::aarch64: {
- typedef orc::LocalJITCompileCallbackManager<orc::OrcAArch64> CCMgrT;
- return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
+ default:
+ return make_error<StringError>(
+ std::string("No callback manager available for ") + T.str(),
+ inconvertibleErrorCode());
+ case Triple::aarch64: {
+ typedef orc::LocalJITCompileCallbackManager<orc::OrcAArch64> CCMgrT;
+ return CCMgrT::Create(ES, ErrorHandlerAddress);
}
case Triple::x86: {
typedef orc::LocalJITCompileCallbackManager<orc::OrcI386> CCMgrT;
- return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
+ return CCMgrT::Create(ES, ErrorHandlerAddress);
}
case Triple::mips: {
typedef orc::LocalJITCompileCallbackManager<orc::OrcMips32Be> CCMgrT;
- return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
+ return CCMgrT::Create(ES, ErrorHandlerAddress);
}
case Triple::mipsel: {
typedef orc::LocalJITCompileCallbackManager<orc::OrcMips32Le> CCMgrT;
- return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
+ return CCMgrT::Create(ES, ErrorHandlerAddress);
}
-
+
case Triple::mips64:
case Triple::mips64el: {
typedef orc::LocalJITCompileCallbackManager<orc::OrcMips64> CCMgrT;
- return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
+ return CCMgrT::Create(ES, ErrorHandlerAddress);
}
-
+
case Triple::x86_64: {
if ( T.getOS() == Triple::OSType::Win32 ) {
typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_Win32> CCMgrT;
- return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
+ return CCMgrT::Create(ES, ErrorHandlerAddress);
} else {
typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_SysV> CCMgrT;
- return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
+ return CCMgrT::Create(ES, ErrorHandlerAddress);
}
}
diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index ecdfd862c3b..a3da0741e11 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -153,9 +153,7 @@ Expected<std::unique_ptr<LLLazyJIT>>
auto CCMgr = createLocalCompileCallbackManager(TT, *ES, 0);
if (!CCMgr)
- return make_error<StringError>(
- std::string("No callback manager available for ") + TT.str(),
- inconvertibleErrorCode());
+ return CCMgr.takeError();
auto ISMBuilder = createLocalIndirectStubsManagerBuilder(TT);
if (!ISMBuilder)
@@ -168,13 +166,13 @@ Expected<std::unique_ptr<LLLazyJIT>>
if (!TM)
return TM.takeError();
return std::unique_ptr<LLLazyJIT>(
- new LLLazyJIT(std::move(ES), std::move(*TM), std::move(DL),
- std::move(CCMgr), std::move(ISMBuilder)));
+ new LLLazyJIT(std::move(ES), std::move(*TM), std::move(DL),
+ std::move(*CCMgr), std::move(ISMBuilder)));
}
- return std::unique_ptr<LLLazyJIT>(
- new LLLazyJIT(std::move(ES), std::move(JTMB), std::move(DL),
- NumCompileThreads, std::move(CCMgr), std::move(ISMBuilder)));
+ return std::unique_ptr<LLLazyJIT>(new LLLazyJIT(
+ std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads,
+ std::move(*CCMgr), std::move(ISMBuilder)));
}
Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) {
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
index d59030abab3..3fedba1caa6 100644
--- a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
+++ b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
@@ -183,10 +183,17 @@ private:
// 2. Runtime overrides.
// 3. External resolver (if present).
- if (auto Sym = Stack.CODLayer.findSymbol(Name, true))
- return Sym;
- else if (auto Err = Sym.takeError())
- return Sym.takeError();
+ if (Stack.CODLayer) {
+ if (auto Sym = Stack.CODLayer->findSymbol(Name, true))
+ return Sym;
+ else if (auto Err = Sym.takeError())
+ return Sym.takeError();
+ } else {
+ if (auto Sym = Stack.CompileLayer.findSymbol(Name, true))
+ return Sym;
+ else if (auto Err = Sym.takeError())
+ return Sym.takeError();
+ }
if (auto Sym = Stack.CXXRuntimeOverrides.searchOverrides(Name))
return Sym;
@@ -206,8 +213,8 @@ private:
public:
OrcCBindingsStack(TargetMachine &TM,
IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
- : CCMgr(createLocalCompileCallbackManager(TM.getTargetTriple(), ES, 0)),
- DL(TM.createDataLayout()), IndirectStubsMgr(IndirectStubsMgrBuilder()),
+ : CCMgr(createCompileCallbackManager(TM, ES)), DL(TM.createDataLayout()),
+ IndirectStubsMgr(IndirectStubsMgrBuilder()),
ObjectLayer(ES,
[this](orc::VModuleKey K) {
auto ResolverI = Resolvers.find(K);
@@ -227,20 +234,8 @@ public:
this->notifyFreed(K, Obj);
}),
CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)),
- CODLayer(ES, CompileLayer,
- [this](orc::VModuleKey K) {
- auto ResolverI = Resolvers.find(K);
- assert(ResolverI != Resolvers.end() &&
- "No resolver for module K");
- return ResolverI->second;
- },
- [this](orc::VModuleKey K,
- std::shared_ptr<orc::SymbolResolver> Resolver) {
- assert(!Resolvers.count(K) && "Resolver already present");
- Resolvers[K] = std::move(Resolver);
- },
- [](Function &F) { return std::set<Function *>({&F}); },
- *this->CCMgr, std::move(IndirectStubsMgrBuilder), false),
+ CODLayer(createCODLayer(ES, CompileLayer, CCMgr.get(),
+ std::move(IndirectStubsMgrBuilder), Resolvers)),
CXXRuntimeOverrides(
[this](const std::string &S) { return mangle(S); }) {}
@@ -286,6 +281,7 @@ public:
Error setIndirectStubPointer(StringRef Name, JITTargetAddress Addr) {
return IndirectStubsMgr->updatePointer(Name, Addr);
}
+
template <typename LayerT>
Expected<orc::VModuleKey>
addIRModule(LayerT &Layer, std::unique_ptr<Module> M,
@@ -338,7 +334,12 @@ public:
addIRModuleLazy(std::unique_ptr<Module> M,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
- return addIRModule(CODLayer, std::move(M),
+ if (!CODLayer)
+ return make_error<StringError>("Can not add lazy module: No compile "
+ "callback manager available",
+ inconvertibleErrorCode());
+
+ return addIRModule(*CODLayer, std::move(M),
llvm::make_unique<SectionMemoryManager>(),
std::move(ExternalResolver), ExternalResolverCtx);
}
@@ -376,7 +377,9 @@ public:
bool ExportedSymbolsOnly) {
if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
return Sym;
- return CODLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
+ if (CODLayer)
+ return CODLayer->findSymbol(mangle(Name), ExportedSymbolsOnly);
+ return CompileLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
}
JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
@@ -440,6 +443,46 @@ public:
}
private:
+ using ResolverMap =
+ std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>>;
+
+ static std::unique_ptr<CompileCallbackMgr>
+ createCompileCallbackManager(TargetMachine &TM, orc::ExecutionSession &ES) {
+ auto CCMgr = createLocalCompileCallbackManager(TM.getTargetTriple(), ES, 0);
+ if (!CCMgr) {
+ // FIXME: It would be good if we could report this somewhere, but we do
+ // have an instance yet.
+ logAllUnhandledErrors(CCMgr.takeError(), errs(), "ORC error: ");
+ return nullptr;
+ }
+ return std::move(*CCMgr);
+ }
+
+ static std::unique_ptr<CODLayerT>
+ createCODLayer(orc::ExecutionSession &ES, CompileLayerT &CompileLayer,
+ CompileCallbackMgr *CCMgr,
+ IndirectStubsManagerBuilder IndirectStubsMgrBuilder,
+ ResolverMap &Resolvers) {
+ // If there is no compile callback manager available we can not create a
+ // compile on demand layer.
+ if (!CCMgr)
+ return nullptr;
+
+ return llvm::make_unique<CODLayerT>(
+ ES, CompileLayer,
+ [&Resolvers](orc::VModuleKey K) {
+ auto ResolverI = Resolvers.find(K);
+ assert(ResolverI != Resolvers.end() && "No resolver for module K");
+ return ResolverI->second;
+ },
+ [&Resolvers](orc::VModuleKey K,
+ std::shared_ptr<orc::SymbolResolver> Resolver) {
+ assert(!Resolvers.count(K) && "Resolver already present");
+ Resolvers[K] = std::move(Resolver);
+ },
+ [](Function &F) { return std::set<Function *>({&F}); }, *CCMgr,
+ std::move(IndirectStubsMgrBuilder), false);
+ }
void reportError(Error Err) {
// FIXME: Report errors on the execution session.
@@ -470,7 +513,7 @@ private:
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;
- CODLayerT CODLayer;
+ std::unique_ptr<CODLayerT> CODLayer;
std::map<orc::VModuleKey, std::unique_ptr<detail::GenericLayer>> KeyLayers;
@@ -478,7 +521,7 @@ private:
std::vector<orc::CtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
std::string ErrMsg;
- std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>> Resolvers;
+ ResolverMap Resolvers;
};
} // end namespace llvm
diff --git a/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp
index a1f864bae01..9aa4437550b 100644
--- a/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp
@@ -16,13 +16,18 @@ using namespace llvm::orc;
namespace {
-class DummyCallbackManager : public orc::JITCompileCallbackManager {
+class DummyTrampolinePool : public orc::TrampolinePool {
public:
- DummyCallbackManager(ExecutionSession &ES)
- : JITCompileCallbackManager(ES, 0) {}
+ Expected<JITTargetAddress> getTrampoline() {
+ llvm_unreachable("Unimplemented");
+ }
+};
+class DummyCallbackManager : public JITCompileCallbackManager {
public:
- Error grow() override { llvm_unreachable("not implemented"); }
+ DummyCallbackManager(ExecutionSession &ES)
+ : JITCompileCallbackManager(llvm::make_unique<DummyTrampolinePool>(), ES,
+ 0) {}
};
class DummyStubsManager : public orc::IndirectStubsManager {
OpenPOWER on IntegriCloud