diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h index 6ee2deef04d09..887147a77026e 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h @@ -51,11 +51,32 @@ class EPCGenericDylibManager { /// Looks up symbols within the given dylib. Expected> - lookup(tpctypes::DylibHandle H, const SymbolLookupSet &Lookup); + lookup(tpctypes::DylibHandle H, const SymbolLookupSet &Lookup) { + std::promise>> RP; + auto RF = RP.get_future(); + lookupAsync(H, Lookup, [&RP](auto R) { RP.set_value(std::move(R)); }); + return RF.get(); + } /// Looks up symbols within the given dylib. Expected> - lookup(tpctypes::DylibHandle H, const RemoteSymbolLookupSet &Lookup); + lookup(tpctypes::DylibHandle H, const RemoteSymbolLookupSet &Lookup) { + std::promise>> RP; + auto RF = RP.get_future(); + lookupAsync(H, Lookup, [&RP](auto R) { RP.set_value(std::move(R)); }); + return RF.get(); + } + + using SymbolLookupCompleteFn = + unique_function>)>; + + /// Looks up symbols within the given dylib. + void lookupAsync(tpctypes::DylibHandle H, const SymbolLookupSet &Lookup, + SymbolLookupCompleteFn Complete); + + /// Looks up symbols within the given dylib. + void lookupAsync(tpctypes::DylibHandle H, const RemoteSymbolLookupSet &Lookup, + SymbolLookupCompleteFn Complete); private: ExecutorProcessControl &EPC; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h index 9e42d6dd615df..6468f2dfc11ad 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h @@ -290,8 +290,26 @@ class ExecutorProcessControl { /// that correspond to the lookup order. If a required symbol is not /// found then this method will return an error. If a weakly referenced /// symbol is not found then it be assigned a '0' value. - virtual Expected> - lookupSymbols(ArrayRef Request) = 0; + Expected> + lookupSymbols(ArrayRef Request) { + std::promise>> RP; + auto RF = RP.get_future(); + lookupSymbolsAsync(Request, + [&RP](auto Result) { RP.set_value(std::move(Result)); }); + return RF.get(); + } + + using SymbolLookupCompleteFn = + unique_function>)>; + + /// Search for symbols in the target process. + /// + /// The result of the lookup is a 2-dimensional array of target addresses + /// that correspond to the lookup order. If a required symbol is not + /// found then this method will return an error. If a weakly referenced + /// symbol is not found then it be assigned a '0' value. + virtual void lookupSymbolsAsync(ArrayRef Request, + SymbolLookupCompleteFn F) = 0; /// Run function with a main-like signature. virtual Expected runAsMain(ExecutorAddr MainFnAddr, @@ -462,8 +480,8 @@ class UnsupportedExecutorProcessControl : public ExecutorProcessControl, llvm_unreachable("Unsupported"); } - Expected> - lookupSymbols(ArrayRef Request) override { + void lookupSymbolsAsync(ArrayRef Request, + SymbolLookupCompleteFn F) override { llvm_unreachable("Unsupported"); } @@ -510,8 +528,8 @@ class SelfExecutorProcessControl : public ExecutorProcessControl, Expected loadDylib(const char *DylibPath) override; - Expected> - lookupSymbols(ArrayRef Request) override; + void lookupSymbolsAsync(ArrayRef Request, + SymbolLookupCompleteFn F) override; Expected runAsMain(ExecutorAddr MainFnAddr, ArrayRef Args) override; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h b/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h index 25b79be48810c..c10b8df01cc0a 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h @@ -71,8 +71,8 @@ class SimpleRemoteEPC : public ExecutorProcessControl, Expected loadDylib(const char *DylibPath) override; - Expected> - lookupSymbols(ArrayRef Request) override; + void lookupSymbolsAsync(ArrayRef Request, + SymbolLookupCompleteFn F) override; Expected runAsMain(ExecutorAddr MainFnAddr, ArrayRef Args) override; diff --git a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp index 460f4e1c448e6..88cc3b04fb642 100644 --- a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp +++ b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" +#include "llvm/Support/Error.h" namespace llvm { namespace orc { @@ -39,32 +40,38 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate( LookupSymbols.add(KV.first, SymbolLookupFlags::WeaklyReferencedSymbol); } - SymbolMap NewSymbols; - ExecutorProcessControl::LookupRequest Request(H, LookupSymbols); - auto Result = EPC.lookupSymbols(Request); - if (!Result) - return Result.takeError(); - - assert(Result->size() == 1 && "Results for more than one library returned"); - assert(Result->front().size() == LookupSymbols.size() && - "Result has incorrect number of elements"); - - auto ResultI = Result->front().begin(); - for (auto &KV : LookupSymbols) { - if (ResultI->getAddress()) - NewSymbols[KV.first] = *ResultI; - ++ResultI; - } + // Copy-capture LookupSymbols, since LookupRequest keeps a reference. + EPC.lookupSymbolsAsync(Request, [this, &JD, LS = std::move(LS), + LookupSymbols](auto Result) mutable { + if (!Result) + return LS.continueLookup(Result.takeError()); - // If there were no resolved symbols bail out. - if (NewSymbols.empty()) - return Error::success(); + assert(Result->size() == 1 && "Results for more than one library returned"); + assert(Result->front().size() == LookupSymbols.size() && + "Result has incorrect number of elements"); + + SymbolMap NewSymbols; + auto ResultI = Result->front().begin(); + for (auto &KV : LookupSymbols) { + if (ResultI->getAddress()) + NewSymbols[KV.first] = *ResultI; + ++ResultI; + } + + // If there were no resolved symbols bail out. + if (NewSymbols.empty()) + return LS.continueLookup(Error::success()); + + // Define resolved symbols. + Error Err = AddAbsoluteSymbols + ? AddAbsoluteSymbols(JD, std::move(NewSymbols)) + : JD.define(absoluteSymbols(std::move(NewSymbols))); + + LS.continueLookup(std::move(Err)); + }); - // Define resolved symbols. - if (AddAbsoluteSymbols) - return AddAbsoluteSymbols(JD, std::move(NewSymbols)); - return JD.define(absoluteSymbols(std::move(NewSymbols))); + return Error::success(); } } // end namespace orc diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp index da185c80c6c7d..6a7cab4a55100 100644 --- a/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp +++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp @@ -81,28 +81,38 @@ Expected EPCGenericDylibManager::open(StringRef Path, return H; } -Expected> -EPCGenericDylibManager::lookup(tpctypes::DylibHandle H, - const SymbolLookupSet &Lookup) { - Expected> Result( - (std::vector())); - if (auto Err = - EPC.callSPSWrapper( - SAs.Lookup, Result, SAs.Instance, H, Lookup)) - return std::move(Err); - return Result; +void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H, + const SymbolLookupSet &Lookup, + SymbolLookupCompleteFn Complete) { + EPC.callSPSWrapperAsync( + SAs.Lookup, + [Complete = std::move(Complete)]( + Error SerializationErr, + Expected> Result) mutable { + if (SerializationErr) { + cantFail(Result.takeError()); + Complete(std::move(SerializationErr)); + } + Complete(std::move(Result)); + }, + SAs.Instance, H, Lookup); } -Expected> -EPCGenericDylibManager::lookup(tpctypes::DylibHandle H, - const RemoteSymbolLookupSet &Lookup) { - Expected> Result( - (std::vector())); - if (auto Err = - EPC.callSPSWrapper( - SAs.Lookup, Result, SAs.Instance, H, Lookup)) - return std::move(Err); - return Result; +void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H, + const RemoteSymbolLookupSet &Lookup, + SymbolLookupCompleteFn Complete) { + EPC.callSPSWrapperAsync( + SAs.Lookup, + [Complete = std::move(Complete)]( + Error SerializationErr, + Expected> Result) mutable { + if (SerializationErr) { + cantFail(Result.takeError()); + Complete(std::move(SerializationErr)); + } + Complete(std::move(Result)); + }, + SAs.Instance, H, Lookup); } } // end namespace orc diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp index f0c551cd77804..efafca949e61e 100644 --- a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp @@ -89,8 +89,9 @@ SelfExecutorProcessControl::loadDylib(const char *DylibPath) { return ExecutorAddr::fromPtr(Dylib.getOSSpecificHandle()); } -Expected> -SelfExecutorProcessControl::lookupSymbols(ArrayRef Request) { +void SelfExecutorProcessControl::lookupSymbolsAsync( + ArrayRef Request, + ExecutorProcessControl::SymbolLookupCompleteFn Complete) { std::vector R; for (auto &Elem : Request) { @@ -105,7 +106,8 @@ SelfExecutorProcessControl::lookupSymbols(ArrayRef Request) { // FIXME: Collect all failing symbols before erroring out. SymbolNameVector MissingSymbols; MissingSymbols.push_back(Sym); - return make_error(SSP, std::move(MissingSymbols)); + return Complete( + make_error(SSP, std::move(MissingSymbols))); } // FIXME: determine accurate JITSymbolFlags. R.back().push_back( @@ -113,7 +115,7 @@ SelfExecutorProcessControl::lookupSymbols(ArrayRef Request) { } } - return R; + Complete(std::move(R)); } Expected diff --git a/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp b/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp index 3d3ca891d8810..a81019cb1dabb 100644 --- a/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp +++ b/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp @@ -29,20 +29,37 @@ SimpleRemoteEPC::loadDylib(const char *DylibPath) { return DylibMgr->open(DylibPath, 0); } -Expected> -SimpleRemoteEPC::lookupSymbols(ArrayRef Request) { - std::vector Result; - - for (auto &Element : Request) { - if (auto R = DylibMgr->lookup(Element.Handle, Element.Symbols)) { - Result.push_back({}); - Result.back().reserve(R->size()); - for (auto Addr : *R) - Result.back().push_back(Addr); - } else - return R.takeError(); - } - return std::move(Result); +/// Async helper to chain together calls to DylibMgr::lookupAsync to fulfill all +/// all the requests. +/// FIXME: The dylib manager should support multiple LookupRequests natively. +static void +lookupSymbolsAsyncHelper(EPCGenericDylibManager &DylibMgr, + ArrayRef Request, + std::vector Result, + SimpleRemoteEPC::SymbolLookupCompleteFn Complete) { + if (Request.empty()) + return Complete(std::move(Result)); + + auto &Element = Request.front(); + DylibMgr.lookupAsync(Element.Handle, Element.Symbols, + [&DylibMgr, Request, Complete = std::move(Complete), + Result = std::move(Result)](auto R) mutable { + if (!R) + return Complete(R.takeError()); + Result.push_back({}); + Result.back().reserve(R->size()); + for (auto Addr : *R) + Result.back().push_back(Addr); + + lookupSymbolsAsyncHelper( + DylibMgr, Request.drop_front(), std::move(Result), + std::move(Complete)); + }); +} + +void SimpleRemoteEPC::lookupSymbolsAsync(ArrayRef Request, + SymbolLookupCompleteFn Complete) { + lookupSymbolsAsyncHelper(*DylibMgr, Request, {}, std::move(Complete)); } Expected SimpleRemoteEPC::runAsMain(ExecutorAddr MainFnAddr, diff --git a/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp index edd12ebb62e1a..7ab3e40df7459 100644 --- a/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp @@ -189,8 +189,8 @@ TEST(ObjectLinkingLayerSearchGeneratorTest, AbsoluteSymbolsObjectLayer) { return ExecutorAddr::fromPtr((void *)nullptr); } - Expected> - lookupSymbols(ArrayRef Request) override { + void lookupSymbolsAsync(ArrayRef Request, + SymbolLookupCompleteFn Complete) override { std::vector Result; EXPECT_EQ(Request.size(), 1u); for (auto &LR : Request) { @@ -205,7 +205,7 @@ TEST(ObjectLinkingLayerSearchGeneratorTest, AbsoluteSymbolsObjectLayer) { } } } - return std::vector{1, Result}; + Complete(std::vector{1, Result}); } };