1bb72f073SLang Hames //===------- SimpleEPCServer.cpp - EPC over simple abstract channel -------===//
2bb72f073SLang Hames //
3bb72f073SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bb72f073SLang Hames // See https://llvm.org/LICENSE.txt for license information.
5bb72f073SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bb72f073SLang Hames //
7bb72f073SLang Hames //===----------------------------------------------------------------------===//
8bb72f073SLang Hames 
9bb72f073SLang Hames #include "llvm/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.h"
10bb72f073SLang Hames 
11bb72f073SLang Hames #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
12bb72f073SLang Hames #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
13bb72f073SLang Hames #include "llvm/Support/FormatVariadic.h"
14bb72f073SLang Hames #include "llvm/Support/Host.h"
15bb72f073SLang Hames #include "llvm/Support/Process.h"
16bb72f073SLang Hames 
17bb72f073SLang Hames #define DEBUG_TYPE "orc"
18bb72f073SLang Hames 
19bb72f073SLang Hames using namespace llvm::orc::shared;
20bb72f073SLang Hames 
21bb72f073SLang Hames namespace llvm {
22bb72f073SLang Hames namespace orc {
23bb72f073SLang Hames 
24bb72f073SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult
25bb72f073SLang Hames reserveWrapper(const char *ArgData, size_t ArgSize) {
26bb72f073SLang Hames   return WrapperFunction<SPSOrcTargetProcessAllocate>::handle(
27bb72f073SLang Hames              ArgData, ArgSize,
28bb72f073SLang Hames              [](uint64_t Size) -> Expected<ExecutorAddress> {
29bb72f073SLang Hames                std::error_code EC;
30bb72f073SLang Hames                auto MB = sys::Memory::allocateMappedMemory(
31bb72f073SLang Hames                    Size, 0, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
32bb72f073SLang Hames                if (EC)
33bb72f073SLang Hames                  return errorCodeToError(EC);
34bb72f073SLang Hames                return ExecutorAddress::fromPtr(MB.base());
35bb72f073SLang Hames              })
36bb72f073SLang Hames       .release();
37bb72f073SLang Hames }
38bb72f073SLang Hames 
39bb72f073SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult
40bb72f073SLang Hames finalizeWrapper(const char *ArgData, size_t ArgSize) {
41bb72f073SLang Hames   return WrapperFunction<SPSOrcTargetProcessFinalize>::handle(
42bb72f073SLang Hames              ArgData, ArgSize,
43bb72f073SLang Hames              [](const tpctypes::FinalizeRequest &FR) -> Error {
44bb72f073SLang Hames                for (auto &Seg : FR) {
45bb72f073SLang Hames                  char *Mem = Seg.Addr.toPtr<char *>();
46bb72f073SLang Hames                  memcpy(Mem, Seg.Content.data(), Seg.Content.size());
47bb72f073SLang Hames                  memset(Mem + Seg.Content.size(), 0,
48bb72f073SLang Hames                         Seg.Size - Seg.Content.size());
49bb72f073SLang Hames                  assert(Seg.Size <= std::numeric_limits<size_t>::max());
50bb72f073SLang Hames                  if (auto EC = sys::Memory::protectMappedMemory(
51bb72f073SLang Hames                          {Mem, static_cast<size_t>(Seg.Size)},
52bb72f073SLang Hames                          tpctypes::fromWireProtectionFlags(Seg.Prot)))
53bb72f073SLang Hames                    return errorCodeToError(EC);
54bb72f073SLang Hames                  if (Seg.Prot & tpctypes::WPF_Exec)
55bb72f073SLang Hames                    sys::Memory::InvalidateInstructionCache(Mem, Seg.Size);
56bb72f073SLang Hames                }
57bb72f073SLang Hames                return Error::success();
58bb72f073SLang Hames              })
59bb72f073SLang Hames       .release();
60bb72f073SLang Hames }
61bb72f073SLang Hames 
62bb72f073SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult
63bb72f073SLang Hames deallocateWrapper(const char *ArgData, size_t ArgSize) {
64bb72f073SLang Hames   return WrapperFunction<SPSOrcTargetProcessDeallocate>::handle(
65bb72f073SLang Hames              ArgData, ArgSize,
66bb72f073SLang Hames              [](ExecutorAddress Base, uint64_t Size) -> Error {
67bb72f073SLang Hames                sys::MemoryBlock MB(Base.toPtr<void *>(), Size);
68bb72f073SLang Hames                if (auto EC = sys::Memory::releaseMappedMemory(MB))
69bb72f073SLang Hames                  return errorCodeToError(EC);
70bb72f073SLang Hames                return Error::success();
71bb72f073SLang Hames              })
72bb72f073SLang Hames       .release();
73bb72f073SLang Hames }
74bb72f073SLang Hames 
75bb72f073SLang Hames template <typename WriteT, typename SPSWriteT>
76bb72f073SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult
77bb72f073SLang Hames writeUIntsWrapper(const char *ArgData, size_t ArgSize) {
78bb72f073SLang Hames   return WrapperFunction<void(SPSSequence<SPSWriteT>)>::handle(
79bb72f073SLang Hames              ArgData, ArgSize,
80bb72f073SLang Hames              [](std::vector<WriteT> Ws) {
81bb72f073SLang Hames                for (auto &W : Ws)
82bb72f073SLang Hames                  *jitTargetAddressToPointer<decltype(W.Value) *>(W.Address) =
83bb72f073SLang Hames                      W.Value;
84bb72f073SLang Hames              })
85bb72f073SLang Hames       .release();
86bb72f073SLang Hames }
87bb72f073SLang Hames 
88bb72f073SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult
89bb72f073SLang Hames writeBuffersWrapper(const char *ArgData, size_t ArgSize) {
90bb72f073SLang Hames   return WrapperFunction<void(SPSSequence<SPSMemoryAccessBufferWrite>)>::handle(
91bb72f073SLang Hames              ArgData, ArgSize,
92bb72f073SLang Hames              [](std::vector<tpctypes::BufferWrite> Ws) {
93bb72f073SLang Hames                for (auto &W : Ws)
94bb72f073SLang Hames                  memcpy(jitTargetAddressToPointer<char *>(W.Address),
95bb72f073SLang Hames                         W.Buffer.data(), W.Buffer.size());
96bb72f073SLang Hames              })
97bb72f073SLang Hames       .release();
98bb72f073SLang Hames }
99bb72f073SLang Hames 
100bb72f073SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult
101bb72f073SLang Hames runAsMainWrapper(const char *ArgData, size_t ArgSize) {
102bb72f073SLang Hames   return WrapperFunction<SPSRunAsMainSignature>::handle(
103bb72f073SLang Hames              ArgData, ArgSize,
104bb72f073SLang Hames              [](ExecutorAddress MainAddr,
105bb72f073SLang Hames                 std::vector<std::string> Args) -> int64_t {
106bb72f073SLang Hames                return runAsMain(MainAddr.toPtr<int (*)(int, char *[])>(), Args);
107bb72f073SLang Hames              })
108bb72f073SLang Hames       .release();
109bb72f073SLang Hames }
110bb72f073SLang Hames 
111bb72f073SLang Hames SimpleRemoteEPCServer::Dispatcher::~Dispatcher() {}
112bb72f073SLang Hames 
113bb72f073SLang Hames #if LLVM_ENABLE_THREADS
114bb72f073SLang Hames void SimpleRemoteEPCServer::ThreadDispatcher::dispatch(
115bb72f073SLang Hames     unique_function<void()> Work) {
116bb72f073SLang Hames   {
117bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(DispatchMutex);
118bb72f073SLang Hames     if (!Running)
119bb72f073SLang Hames       return;
120bb72f073SLang Hames     ++Outstanding;
121bb72f073SLang Hames   }
122bb72f073SLang Hames 
123bb72f073SLang Hames   std::thread([this, Work = std::move(Work)]() mutable {
124bb72f073SLang Hames     Work();
125bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(DispatchMutex);
126bb72f073SLang Hames     --Outstanding;
127bb72f073SLang Hames     OutstandingCV.notify_all();
128bb72f073SLang Hames   }).detach();
129bb72f073SLang Hames }
130bb72f073SLang Hames 
131bb72f073SLang Hames void SimpleRemoteEPCServer::ThreadDispatcher::shutdown() {
132bb72f073SLang Hames   std::unique_lock<std::mutex> Lock(DispatchMutex);
133bb72f073SLang Hames   Running = false;
134bb72f073SLang Hames   OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; });
135bb72f073SLang Hames }
136bb72f073SLang Hames #endif
137bb72f073SLang Hames 
138bb72f073SLang Hames StringMap<ExecutorAddress> SimpleRemoteEPCServer::defaultBootstrapSymbols() {
139bb72f073SLang Hames   StringMap<ExecutorAddress> DBS;
140bb72f073SLang Hames 
141bb72f073SLang Hames   DBS["__llvm_orc_memory_reserve"] = ExecutorAddress::fromPtr(&reserveWrapper);
142bb72f073SLang Hames   DBS["__llvm_orc_memory_finalize"] =
143bb72f073SLang Hames       ExecutorAddress::fromPtr(&finalizeWrapper);
144bb72f073SLang Hames   DBS["__llvm_orc_memory_deallocate"] =
145bb72f073SLang Hames       ExecutorAddress::fromPtr(&deallocateWrapper);
146bb72f073SLang Hames   DBS["__llvm_orc_memory_write_uint8s"] = ExecutorAddress::fromPtr(
147bb72f073SLang Hames       &writeUIntsWrapper<tpctypes::UInt8Write,
148bb72f073SLang Hames                          shared::SPSMemoryAccessUInt8Write>);
149bb72f073SLang Hames   DBS["__llvm_orc_memory_write_uint16s"] = ExecutorAddress::fromPtr(
150bb72f073SLang Hames       &writeUIntsWrapper<tpctypes::UInt16Write,
151bb72f073SLang Hames                          shared::SPSMemoryAccessUInt16Write>);
152bb72f073SLang Hames   DBS["__llvm_orc_memory_write_uint32s"] = ExecutorAddress::fromPtr(
153bb72f073SLang Hames       &writeUIntsWrapper<tpctypes::UInt32Write,
154bb72f073SLang Hames                          shared::SPSMemoryAccessUInt32Write>);
155bb72f073SLang Hames   DBS["__llvm_orc_memory_write_uint64s"] = ExecutorAddress::fromPtr(
156bb72f073SLang Hames       &writeUIntsWrapper<tpctypes::UInt64Write,
157bb72f073SLang Hames                          shared::SPSMemoryAccessUInt64Write>);
158bb72f073SLang Hames   DBS["__llvm_orc_memory_write_buffers"] =
159bb72f073SLang Hames       ExecutorAddress::fromPtr(&writeBuffersWrapper);
160bb72f073SLang Hames   DBS["__llvm_orc_run_as_main"] = ExecutorAddress::fromPtr(&runAsMainWrapper);
161bb72f073SLang Hames   DBS["__llvm_orc_load_dylib"] = ExecutorAddress::fromPtr(&loadDylibWrapper);
162bb72f073SLang Hames   DBS["__llvm_orc_lookup_symbols"] =
163bb72f073SLang Hames       ExecutorAddress::fromPtr(&lookupSymbolsWrapper);
164bb72f073SLang Hames   return DBS;
165bb72f073SLang Hames }
166bb72f073SLang Hames 
167bb72f073SLang Hames Expected<SimpleRemoteEPCTransportClient::HandleMessageAction>
168bb72f073SLang Hames SimpleRemoteEPCServer::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
169bb72f073SLang Hames                                      ExecutorAddress TagAddr,
170bb72f073SLang Hames                                      SimpleRemoteEPCArgBytesVector ArgBytes) {
171bb72f073SLang Hames   using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;
172*d11a0c5dSLang Hames   if (static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC))
173bb72f073SLang Hames     return make_error<StringError>("Unexpected opcode",
174bb72f073SLang Hames                                    inconvertibleErrorCode());
175bb72f073SLang Hames 
176bb72f073SLang Hames   // TODO: Clean detach message?
177bb72f073SLang Hames   switch (OpC) {
178bb72f073SLang Hames   case SimpleRemoteEPCOpcode::Setup:
179bb72f073SLang Hames     return make_error<StringError>("Unexpected Setup opcode",
180bb72f073SLang Hames                                    inconvertibleErrorCode());
181bb72f073SLang Hames   case SimpleRemoteEPCOpcode::Hangup:
182bb72f073SLang Hames     return SimpleRemoteEPCTransportClient::EndSession;
183bb72f073SLang Hames   case SimpleRemoteEPCOpcode::Result:
184bb72f073SLang Hames     if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))
185bb72f073SLang Hames       return std::move(Err);
186bb72f073SLang Hames     break;
187bb72f073SLang Hames   case SimpleRemoteEPCOpcode::CallWrapper:
188bb72f073SLang Hames     handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));
189bb72f073SLang Hames     break;
190bb72f073SLang Hames   }
191bb72f073SLang Hames   return ContinueSession;
192bb72f073SLang Hames }
193bb72f073SLang Hames 
194bb72f073SLang Hames Error SimpleRemoteEPCServer::waitForDisconnect() {
195bb72f073SLang Hames   std::unique_lock<std::mutex> Lock(ServerStateMutex);
196bb72f073SLang Hames   ShutdownCV.wait(Lock, [this]() { return RunState == ServerShutDown; });
197bb72f073SLang Hames   return std::move(ShutdownErr);
198bb72f073SLang Hames }
199bb72f073SLang Hames 
200bb72f073SLang Hames void SimpleRemoteEPCServer::handleDisconnect(Error Err) {
201bb72f073SLang Hames   PendingJITDispatchResultsMap TmpPending;
202bb72f073SLang Hames 
203bb72f073SLang Hames   {
204bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(ServerStateMutex);
205bb72f073SLang Hames     std::swap(TmpPending, PendingJITDispatchResults);
206bb72f073SLang Hames     RunState = ServerShuttingDown;
207bb72f073SLang Hames   }
208bb72f073SLang Hames 
209bb72f073SLang Hames   // Send out-of-band errors to any waiting threads.
210bb72f073SLang Hames   for (auto &KV : TmpPending)
211bb72f073SLang Hames     KV.second->set_value(
212bb72f073SLang Hames         shared::WrapperFunctionResult::createOutOfBandError("disconnecting"));
213bb72f073SLang Hames 
214bb72f073SLang Hames   // TODO: Free attached resources.
215bb72f073SLang Hames   // 1. Close libraries in DylibHandles.
216bb72f073SLang Hames 
217bb72f073SLang Hames   // Wait for dispatcher to clear.
218bb72f073SLang Hames   D->shutdown();
219bb72f073SLang Hames 
220bb72f073SLang Hames   std::lock_guard<std::mutex> Lock(ServerStateMutex);
221bb72f073SLang Hames   ShutdownErr = joinErrors(std::move(ShutdownErr), std::move(Err));
222bb72f073SLang Hames   RunState = ServerShutDown;
223bb72f073SLang Hames   ShutdownCV.notify_all();
224bb72f073SLang Hames }
225bb72f073SLang Hames 
226bb72f073SLang Hames Error SimpleRemoteEPCServer::sendSetupMessage(
227bb72f073SLang Hames     StringMap<ExecutorAddress> BootstrapSymbols) {
228bb72f073SLang Hames 
229bb72f073SLang Hames   using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
230bb72f073SLang Hames 
231bb72f073SLang Hames   std::vector<char> SetupPacket;
232bb72f073SLang Hames   SimpleRemoteEPCExecutorInfo EI;
233bb72f073SLang Hames   EI.TargetTriple = sys::getProcessTriple();
234bb72f073SLang Hames   if (auto PageSize = sys::Process::getPageSize())
235bb72f073SLang Hames     EI.PageSize = *PageSize;
236bb72f073SLang Hames   else
237bb72f073SLang Hames     return PageSize.takeError();
238bb72f073SLang Hames   EI.BootstrapSymbols = std::move(BootstrapSymbols);
239bb72f073SLang Hames 
240bb72f073SLang Hames   assert(!EI.BootstrapSymbols.count(ExecutorSessionObjectName) &&
241bb72f073SLang Hames          "Dispatch context name should not be set");
242bb72f073SLang Hames   assert(!EI.BootstrapSymbols.count(DispatchFnName) &&
243bb72f073SLang Hames          "Dispatch function name should not be set");
244bb72f073SLang Hames   EI.BootstrapSymbols[ExecutorSessionObjectName] =
245bb72f073SLang Hames       ExecutorAddress::fromPtr(this);
246bb72f073SLang Hames   EI.BootstrapSymbols[DispatchFnName] =
247bb72f073SLang Hames       ExecutorAddress::fromPtr(jitDispatchEntry);
248bb72f073SLang Hames 
249bb72f073SLang Hames   using SPSSerialize =
250bb72f073SLang Hames       shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;
251bb72f073SLang Hames   auto SetupPacketBytes =
252bb72f073SLang Hames       shared::WrapperFunctionResult::allocate(SPSSerialize::size(EI));
253bb72f073SLang Hames   shared::SPSOutputBuffer OB(SetupPacketBytes.data(), SetupPacketBytes.size());
254bb72f073SLang Hames   if (!SPSSerialize::serialize(OB, EI))
255bb72f073SLang Hames     return make_error<StringError>("Could not send setup packet",
256bb72f073SLang Hames                                    inconvertibleErrorCode());
257bb72f073SLang Hames 
258bb72f073SLang Hames   return T->sendMessage(SimpleRemoteEPCOpcode::Setup, 0, ExecutorAddress(),
259bb72f073SLang Hames                         {SetupPacketBytes.data(), SetupPacketBytes.size()});
260bb72f073SLang Hames }
261bb72f073SLang Hames 
262bb72f073SLang Hames Error SimpleRemoteEPCServer::handleResult(
263bb72f073SLang Hames     uint64_t SeqNo, ExecutorAddress TagAddr,
264bb72f073SLang Hames     SimpleRemoteEPCArgBytesVector ArgBytes) {
265bb72f073SLang Hames   std::promise<shared::WrapperFunctionResult> *P = nullptr;
266bb72f073SLang Hames   {
267bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(ServerStateMutex);
268bb72f073SLang Hames     auto I = PendingJITDispatchResults.find(SeqNo);
269bb72f073SLang Hames     if (I == PendingJITDispatchResults.end())
270bb72f073SLang Hames       return make_error<StringError>("No call for sequence number " +
271bb72f073SLang Hames                                          Twine(SeqNo),
272bb72f073SLang Hames                                      inconvertibleErrorCode());
273bb72f073SLang Hames     P = I->second;
274bb72f073SLang Hames     PendingJITDispatchResults.erase(I);
275bb72f073SLang Hames     releaseSeqNo(SeqNo);
276bb72f073SLang Hames   }
277bb72f073SLang Hames   auto R = shared::WrapperFunctionResult::allocate(ArgBytes.size());
278bb72f073SLang Hames   memcpy(R.data(), ArgBytes.data(), ArgBytes.size());
279bb72f073SLang Hames   P->set_value(std::move(R));
280bb72f073SLang Hames   return Error::success();
281bb72f073SLang Hames }
282bb72f073SLang Hames 
283bb72f073SLang Hames void SimpleRemoteEPCServer::handleCallWrapper(
284bb72f073SLang Hames     uint64_t RemoteSeqNo, ExecutorAddress TagAddr,
285bb72f073SLang Hames     SimpleRemoteEPCArgBytesVector ArgBytes) {
286bb72f073SLang Hames   D->dispatch([this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() {
287bb72f073SLang Hames     using WrapperFnTy =
288bb72f073SLang Hames         shared::detail::CWrapperFunctionResult (*)(const char *, size_t);
289bb72f073SLang Hames     auto *Fn = TagAddr.toPtr<WrapperFnTy>();
290bb72f073SLang Hames     shared::WrapperFunctionResult ResultBytes(
291bb72f073SLang Hames         Fn(ArgBytes.data(), ArgBytes.size()));
292bb72f073SLang Hames     if (auto Err = T->sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo,
293bb72f073SLang Hames                                   ExecutorAddress(),
294bb72f073SLang Hames                                   {ResultBytes.data(), ResultBytes.size()}))
295bb72f073SLang Hames       ReportError(std::move(Err));
296bb72f073SLang Hames   });
297bb72f073SLang Hames }
298bb72f073SLang Hames 
299bb72f073SLang Hames shared::detail::CWrapperFunctionResult
300bb72f073SLang Hames SimpleRemoteEPCServer::loadDylibWrapper(const char *ArgData, size_t ArgSize) {
301bb72f073SLang Hames   return shared::WrapperFunction<shared::SPSLoadDylibSignature>::handle(
302bb72f073SLang Hames              ArgData, ArgSize,
303bb72f073SLang Hames              [](ExecutorAddress ExecutorSessionObj, std::string Path,
304bb72f073SLang Hames                 uint64_t Flags) -> Expected<uint64_t> {
305bb72f073SLang Hames                return ExecutorSessionObj.toPtr<SimpleRemoteEPCServer *>()
306bb72f073SLang Hames                    ->loadDylib(Path, Flags);
307bb72f073SLang Hames              })
308bb72f073SLang Hames       .release();
309bb72f073SLang Hames }
310bb72f073SLang Hames 
311bb72f073SLang Hames shared::detail::CWrapperFunctionResult
312bb72f073SLang Hames SimpleRemoteEPCServer::lookupSymbolsWrapper(const char *ArgData,
313bb72f073SLang Hames                                             size_t ArgSize) {
314bb72f073SLang Hames   return shared::WrapperFunction<shared::SPSLookupSymbolsSignature>::handle(
315bb72f073SLang Hames              ArgData, ArgSize,
316bb72f073SLang Hames              [](ExecutorAddress ExecutorSessionObj,
317bb72f073SLang Hames                 std::vector<RemoteSymbolLookup> Lookup) {
318bb72f073SLang Hames                return ExecutorSessionObj.toPtr<SimpleRemoteEPCServer *>()
319bb72f073SLang Hames                    ->lookupSymbols(Lookup);
320bb72f073SLang Hames              })
321bb72f073SLang Hames       .release();
322bb72f073SLang Hames }
323bb72f073SLang Hames 
324bb72f073SLang Hames Expected<tpctypes::DylibHandle>
325bb72f073SLang Hames SimpleRemoteEPCServer::loadDylib(const std::string &Path, uint64_t Mode) {
326bb72f073SLang Hames   std::string ErrMsg;
327bb72f073SLang Hames   const char *P = Path.empty() ? nullptr : Path.c_str();
328bb72f073SLang Hames   auto DL = sys::DynamicLibrary::getPermanentLibrary(P, &ErrMsg);
329bb72f073SLang Hames   if (!DL.isValid())
330bb72f073SLang Hames     return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
331bb72f073SLang Hames   std::lock_guard<std::mutex> Lock(ServerStateMutex);
332bb72f073SLang Hames   uint64_t Id = Dylibs.size();
333bb72f073SLang Hames   Dylibs.push_back(std::move(DL));
334bb72f073SLang Hames   return Id;
335bb72f073SLang Hames }
336bb72f073SLang Hames 
337bb72f073SLang Hames Expected<std::vector<std::vector<ExecutorAddress>>>
338bb72f073SLang Hames SimpleRemoteEPCServer::lookupSymbols(const std::vector<RemoteSymbolLookup> &L) {
339bb72f073SLang Hames   std::vector<std::vector<ExecutorAddress>> Result;
340bb72f073SLang Hames 
341bb72f073SLang Hames   for (const auto &E : L) {
342bb72f073SLang Hames     if (E.H >= Dylibs.size())
343bb72f073SLang Hames       return make_error<StringError>("Unrecognized handle",
344bb72f073SLang Hames                                      inconvertibleErrorCode());
345bb72f073SLang Hames     auto &DL = Dylibs[E.H];
346bb72f073SLang Hames     Result.push_back({});
347bb72f073SLang Hames 
348bb72f073SLang Hames     for (const auto &Sym : E.Symbols) {
349bb72f073SLang Hames 
350bb72f073SLang Hames       const char *DemangledSymName = Sym.Name.c_str();
351bb72f073SLang Hames #ifdef __APPLE__
352bb72f073SLang Hames       if (*DemangledSymName == '_')
353bb72f073SLang Hames         ++DemangledSymName;
354bb72f073SLang Hames #endif
355bb72f073SLang Hames 
356bb72f073SLang Hames       void *Addr = DL.getAddressOfSymbol(DemangledSymName);
357bb72f073SLang Hames       if (!Addr && Sym.Required)
358bb72f073SLang Hames         return make_error<StringError>(Twine("Missing definition for ") +
359bb72f073SLang Hames                                            DemangledSymName,
360bb72f073SLang Hames                                        inconvertibleErrorCode());
361bb72f073SLang Hames 
362bb72f073SLang Hames       Result.back().push_back(ExecutorAddress::fromPtr(Addr));
363bb72f073SLang Hames     }
364bb72f073SLang Hames   }
365bb72f073SLang Hames 
366bb72f073SLang Hames   return std::move(Result);
367bb72f073SLang Hames }
368bb72f073SLang Hames 
369bb72f073SLang Hames shared::WrapperFunctionResult
370bb72f073SLang Hames SimpleRemoteEPCServer::doJITDispatch(const void *FnTag, const char *ArgData,
371bb72f073SLang Hames                                      size_t ArgSize) {
372bb72f073SLang Hames   uint64_t SeqNo;
373bb72f073SLang Hames   std::promise<shared::WrapperFunctionResult> ResultP;
374bb72f073SLang Hames   auto ResultF = ResultP.get_future();
375bb72f073SLang Hames   {
376bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(ServerStateMutex);
377bb72f073SLang Hames     if (RunState != ServerRunning)
378bb72f073SLang Hames       return shared::WrapperFunctionResult::createOutOfBandError(
379bb72f073SLang Hames           "jit_dispatch not available (EPC server shut down)");
380bb72f073SLang Hames 
381bb72f073SLang Hames     SeqNo = getNextSeqNo();
382bb72f073SLang Hames     assert(!PendingJITDispatchResults.count(SeqNo) && "SeqNo already in use");
383bb72f073SLang Hames     PendingJITDispatchResults[SeqNo] = &ResultP;
384bb72f073SLang Hames   }
385bb72f073SLang Hames 
386bb72f073SLang Hames   if (auto Err =
387bb72f073SLang Hames           T->sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo,
388bb72f073SLang Hames                          ExecutorAddress::fromPtr(FnTag), {ArgData, ArgSize}))
389bb72f073SLang Hames     ReportError(std::move(Err));
390bb72f073SLang Hames 
391bb72f073SLang Hames   return ResultF.get();
392bb72f073SLang Hames }
393bb72f073SLang Hames 
394bb72f073SLang Hames shared::detail::CWrapperFunctionResult
395bb72f073SLang Hames SimpleRemoteEPCServer::jitDispatchEntry(void *DispatchCtx, const void *FnTag,
396bb72f073SLang Hames                                         const char *ArgData, size_t ArgSize) {
397bb72f073SLang Hames   return reinterpret_cast<SimpleRemoteEPCServer *>(DispatchCtx)
398bb72f073SLang Hames       ->doJITDispatch(FnTag, ArgData, ArgSize)
399bb72f073SLang Hames       .release();
400bb72f073SLang Hames }
401bb72f073SLang Hames 
402bb72f073SLang Hames } // end namespace orc
403bb72f073SLang Hames } // end namespace llvm
404