xref: /src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1c0981da4SDimitry Andric //===------- SimpleRemoteEPC.cpp -- Simple remote executor control --------===//
2c0981da4SDimitry Andric //
3c0981da4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c0981da4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5c0981da4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c0981da4SDimitry Andric //
7c0981da4SDimitry Andric //===----------------------------------------------------------------------===//
8c0981da4SDimitry Andric 
9c0981da4SDimitry Andric #include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"
10c0981da4SDimitry Andric #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
11c0981da4SDimitry Andric #include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h"
12c0981da4SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
13c0981da4SDimitry Andric #include "llvm/Support/FormatVariadic.h"
14c0981da4SDimitry Andric 
15c0981da4SDimitry Andric #define DEBUG_TYPE "orc"
16c0981da4SDimitry Andric 
17c0981da4SDimitry Andric namespace llvm {
18c0981da4SDimitry Andric namespace orc {
19c0981da4SDimitry Andric 
~SimpleRemoteEPC()20c0981da4SDimitry Andric SimpleRemoteEPC::~SimpleRemoteEPC() {
21c0981da4SDimitry Andric #ifndef NDEBUG
22c0981da4SDimitry Andric   std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
23c0981da4SDimitry Andric   assert(Disconnected && "Destroyed without disconnection");
24c0981da4SDimitry Andric #endif // NDEBUG
25c0981da4SDimitry Andric }
26c0981da4SDimitry Andric 
27c0981da4SDimitry Andric Expected<tpctypes::DylibHandle>
loadDylib(const char * DylibPath)28c0981da4SDimitry Andric SimpleRemoteEPC::loadDylib(const char *DylibPath) {
29c0981da4SDimitry Andric   return DylibMgr->open(DylibPath, 0);
30c0981da4SDimitry Andric }
31c0981da4SDimitry Andric 
32ac9a064cSDimitry Andric /// Async helper to chain together calls to DylibMgr::lookupAsync to fulfill all
33ac9a064cSDimitry Andric /// all the requests.
34ac9a064cSDimitry Andric /// FIXME: The dylib manager should support multiple LookupRequests natively.
35ac9a064cSDimitry Andric static void
lookupSymbolsAsyncHelper(EPCGenericDylibManager & DylibMgr,ArrayRef<SimpleRemoteEPC::LookupRequest> Request,std::vector<tpctypes::LookupResult> Result,SimpleRemoteEPC::SymbolLookupCompleteFn Complete)36ac9a064cSDimitry Andric lookupSymbolsAsyncHelper(EPCGenericDylibManager &DylibMgr,
37ac9a064cSDimitry Andric                          ArrayRef<SimpleRemoteEPC::LookupRequest> Request,
38ac9a064cSDimitry Andric                          std::vector<tpctypes::LookupResult> Result,
39ac9a064cSDimitry Andric                          SimpleRemoteEPC::SymbolLookupCompleteFn Complete) {
40ac9a064cSDimitry Andric   if (Request.empty())
41ac9a064cSDimitry Andric     return Complete(std::move(Result));
42c0981da4SDimitry Andric 
43ac9a064cSDimitry Andric   auto &Element = Request.front();
44ac9a064cSDimitry Andric   DylibMgr.lookupAsync(Element.Handle, Element.Symbols,
45ac9a064cSDimitry Andric                        [&DylibMgr, Request, Complete = std::move(Complete),
46ac9a064cSDimitry Andric                         Result = std::move(Result)](auto R) mutable {
47ac9a064cSDimitry Andric                          if (!R)
48ac9a064cSDimitry Andric                            return Complete(R.takeError());
49c0981da4SDimitry Andric                          Result.push_back({});
50c0981da4SDimitry Andric                          Result.back().reserve(R->size());
51c0981da4SDimitry Andric                          for (auto Addr : *R)
52e3b55780SDimitry Andric                            Result.back().push_back(Addr);
53ac9a064cSDimitry Andric 
54ac9a064cSDimitry Andric                          lookupSymbolsAsyncHelper(
55ac9a064cSDimitry Andric                              DylibMgr, Request.drop_front(), std::move(Result),
56ac9a064cSDimitry Andric                              std::move(Complete));
57ac9a064cSDimitry Andric                        });
58c0981da4SDimitry Andric }
59ac9a064cSDimitry Andric 
lookupSymbolsAsync(ArrayRef<LookupRequest> Request,SymbolLookupCompleteFn Complete)60ac9a064cSDimitry Andric void SimpleRemoteEPC::lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
61ac9a064cSDimitry Andric                                          SymbolLookupCompleteFn Complete) {
62ac9a064cSDimitry Andric   lookupSymbolsAsyncHelper(*DylibMgr, Request, {}, std::move(Complete));
63c0981da4SDimitry Andric }
64c0981da4SDimitry Andric 
runAsMain(ExecutorAddr MainFnAddr,ArrayRef<std::string> Args)65c0981da4SDimitry Andric Expected<int32_t> SimpleRemoteEPC::runAsMain(ExecutorAddr MainFnAddr,
66c0981da4SDimitry Andric                                              ArrayRef<std::string> Args) {
67c0981da4SDimitry Andric   int64_t Result = 0;
68c0981da4SDimitry Andric   if (auto Err = callSPSWrapper<rt::SPSRunAsMainSignature>(
697fa27ce4SDimitry Andric           RunAsMainAddr, Result, MainFnAddr, Args))
70c0981da4SDimitry Andric     return std::move(Err);
71c0981da4SDimitry Andric   return Result;
72c0981da4SDimitry Andric }
73c0981da4SDimitry Andric 
runAsVoidFunction(ExecutorAddr VoidFnAddr)74e3b55780SDimitry Andric Expected<int32_t> SimpleRemoteEPC::runAsVoidFunction(ExecutorAddr VoidFnAddr) {
75e3b55780SDimitry Andric   int32_t Result = 0;
76e3b55780SDimitry Andric   if (auto Err = callSPSWrapper<rt::SPSRunAsVoidFunctionSignature>(
777fa27ce4SDimitry Andric           RunAsVoidFunctionAddr, Result, VoidFnAddr))
78e3b55780SDimitry Andric     return std::move(Err);
79e3b55780SDimitry Andric   return Result;
80e3b55780SDimitry Andric }
81e3b55780SDimitry Andric 
runAsIntFunction(ExecutorAddr IntFnAddr,int Arg)82e3b55780SDimitry Andric Expected<int32_t> SimpleRemoteEPC::runAsIntFunction(ExecutorAddr IntFnAddr,
83e3b55780SDimitry Andric                                                     int Arg) {
84e3b55780SDimitry Andric   int32_t Result = 0;
85e3b55780SDimitry Andric   if (auto Err = callSPSWrapper<rt::SPSRunAsIntFunctionSignature>(
867fa27ce4SDimitry Andric           RunAsIntFunctionAddr, Result, IntFnAddr, Arg))
87e3b55780SDimitry Andric     return std::move(Err);
88e3b55780SDimitry Andric   return Result;
89e3b55780SDimitry Andric }
90e3b55780SDimitry Andric 
callWrapperAsync(ExecutorAddr WrapperFnAddr,IncomingWFRHandler OnComplete,ArrayRef<char> ArgBuffer)91c0981da4SDimitry Andric void SimpleRemoteEPC::callWrapperAsync(ExecutorAddr WrapperFnAddr,
92c0981da4SDimitry Andric                                        IncomingWFRHandler OnComplete,
93c0981da4SDimitry Andric                                        ArrayRef<char> ArgBuffer) {
94c0981da4SDimitry Andric   uint64_t SeqNo;
95c0981da4SDimitry Andric   {
96c0981da4SDimitry Andric     std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
97c0981da4SDimitry Andric     SeqNo = getNextSeqNo();
98c0981da4SDimitry Andric     assert(!PendingCallWrapperResults.count(SeqNo) && "SeqNo already in use");
99c0981da4SDimitry Andric     PendingCallWrapperResults[SeqNo] = std::move(OnComplete);
100c0981da4SDimitry Andric   }
101c0981da4SDimitry Andric 
102c0981da4SDimitry Andric   if (auto Err = sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo,
103c0981da4SDimitry Andric                              WrapperFnAddr, ArgBuffer)) {
104c0981da4SDimitry Andric     IncomingWFRHandler H;
105c0981da4SDimitry Andric 
106c0981da4SDimitry Andric     // We just registered OnComplete, but there may be a race between this
107c0981da4SDimitry Andric     // thread returning from sendMessage and handleDisconnect being called from
108c0981da4SDimitry Andric     // the transport's listener thread. If handleDisconnect gets there first
109c0981da4SDimitry Andric     // then it will have failed 'H' for us. If we get there first (or if
110c0981da4SDimitry Andric     // handleDisconnect already ran) then we need to take care of it.
111c0981da4SDimitry Andric     {
112c0981da4SDimitry Andric       std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
113c0981da4SDimitry Andric       auto I = PendingCallWrapperResults.find(SeqNo);
114c0981da4SDimitry Andric       if (I != PendingCallWrapperResults.end()) {
115c0981da4SDimitry Andric         H = std::move(I->second);
116c0981da4SDimitry Andric         PendingCallWrapperResults.erase(I);
117c0981da4SDimitry Andric       }
118c0981da4SDimitry Andric     }
119c0981da4SDimitry Andric 
120c0981da4SDimitry Andric     if (H)
121c0981da4SDimitry Andric       H(shared::WrapperFunctionResult::createOutOfBandError("disconnecting"));
122c0981da4SDimitry Andric 
123c0981da4SDimitry Andric     getExecutionSession().reportError(std::move(Err));
124c0981da4SDimitry Andric   }
125c0981da4SDimitry Andric }
126c0981da4SDimitry Andric 
disconnect()127c0981da4SDimitry Andric Error SimpleRemoteEPC::disconnect() {
128c0981da4SDimitry Andric   T->disconnect();
129c0981da4SDimitry Andric   D->shutdown();
130c0981da4SDimitry Andric   std::unique_lock<std::mutex> Lock(SimpleRemoteEPCMutex);
131c0981da4SDimitry Andric   DisconnectCV.wait(Lock, [this] { return Disconnected; });
132c0981da4SDimitry Andric   return std::move(DisconnectErr);
133c0981da4SDimitry Andric }
134c0981da4SDimitry Andric 
135c0981da4SDimitry Andric Expected<SimpleRemoteEPCTransportClient::HandleMessageAction>
handleMessage(SimpleRemoteEPCOpcode OpC,uint64_t SeqNo,ExecutorAddr TagAddr,SimpleRemoteEPCArgBytesVector ArgBytes)136c0981da4SDimitry Andric SimpleRemoteEPC::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
137c0981da4SDimitry Andric                                ExecutorAddr TagAddr,
138c0981da4SDimitry Andric                                SimpleRemoteEPCArgBytesVector ArgBytes) {
139c0981da4SDimitry Andric 
140c0981da4SDimitry Andric   LLVM_DEBUG({
141c0981da4SDimitry Andric     dbgs() << "SimpleRemoteEPC::handleMessage: opc = ";
142c0981da4SDimitry Andric     switch (OpC) {
143c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::Setup:
144c0981da4SDimitry Andric       dbgs() << "Setup";
145c0981da4SDimitry Andric       assert(SeqNo == 0 && "Non-zero SeqNo for Setup?");
1467fa27ce4SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Setup?");
147c0981da4SDimitry Andric       break;
148c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::Hangup:
149c0981da4SDimitry Andric       dbgs() << "Hangup";
150c0981da4SDimitry Andric       assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
1517fa27ce4SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Hangup?");
152c0981da4SDimitry Andric       break;
153c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::Result:
154c0981da4SDimitry Andric       dbgs() << "Result";
1557fa27ce4SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Result?");
156c0981da4SDimitry Andric       break;
157c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::CallWrapper:
158c0981da4SDimitry Andric       dbgs() << "CallWrapper";
159c0981da4SDimitry Andric       break;
160c0981da4SDimitry Andric     }
1617fa27ce4SDimitry Andric     dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
162c0981da4SDimitry Andric            << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
163c0981da4SDimitry Andric            << " bytes\n";
164c0981da4SDimitry Andric   });
165c0981da4SDimitry Andric 
166c0981da4SDimitry Andric   using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;
167c0981da4SDimitry Andric   if (static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC))
168c0981da4SDimitry Andric     return make_error<StringError>("Unexpected opcode",
169c0981da4SDimitry Andric                                    inconvertibleErrorCode());
170c0981da4SDimitry Andric 
171c0981da4SDimitry Andric   switch (OpC) {
172c0981da4SDimitry Andric   case SimpleRemoteEPCOpcode::Setup:
173c0981da4SDimitry Andric     if (auto Err = handleSetup(SeqNo, TagAddr, std::move(ArgBytes)))
174c0981da4SDimitry Andric       return std::move(Err);
175c0981da4SDimitry Andric     break;
176c0981da4SDimitry Andric   case SimpleRemoteEPCOpcode::Hangup:
177c0981da4SDimitry Andric     T->disconnect();
178c0981da4SDimitry Andric     if (auto Err = handleHangup(std::move(ArgBytes)))
179c0981da4SDimitry Andric       return std::move(Err);
180c0981da4SDimitry Andric     return EndSession;
181c0981da4SDimitry Andric   case SimpleRemoteEPCOpcode::Result:
182c0981da4SDimitry Andric     if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))
183c0981da4SDimitry Andric       return std::move(Err);
184c0981da4SDimitry Andric     break;
185c0981da4SDimitry Andric   case SimpleRemoteEPCOpcode::CallWrapper:
186c0981da4SDimitry Andric     handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));
187c0981da4SDimitry Andric     break;
188c0981da4SDimitry Andric   }
189c0981da4SDimitry Andric   return ContinueSession;
190c0981da4SDimitry Andric }
191c0981da4SDimitry Andric 
handleDisconnect(Error Err)192c0981da4SDimitry Andric void SimpleRemoteEPC::handleDisconnect(Error Err) {
193c0981da4SDimitry Andric   LLVM_DEBUG({
194c0981da4SDimitry Andric     dbgs() << "SimpleRemoteEPC::handleDisconnect: "
195c0981da4SDimitry Andric            << (Err ? "failure" : "success") << "\n";
196c0981da4SDimitry Andric   });
197c0981da4SDimitry Andric 
198c0981da4SDimitry Andric   PendingCallWrapperResultsMap TmpPending;
199c0981da4SDimitry Andric 
200c0981da4SDimitry Andric   {
201c0981da4SDimitry Andric     std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
202c0981da4SDimitry Andric     std::swap(TmpPending, PendingCallWrapperResults);
203c0981da4SDimitry Andric   }
204c0981da4SDimitry Andric 
205c0981da4SDimitry Andric   for (auto &KV : TmpPending)
206c0981da4SDimitry Andric     KV.second(
207c0981da4SDimitry Andric         shared::WrapperFunctionResult::createOutOfBandError("disconnecting"));
208c0981da4SDimitry Andric 
209c0981da4SDimitry Andric   std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
210c0981da4SDimitry Andric   DisconnectErr = joinErrors(std::move(DisconnectErr), std::move(Err));
211c0981da4SDimitry Andric   Disconnected = true;
212c0981da4SDimitry Andric   DisconnectCV.notify_all();
213c0981da4SDimitry Andric }
214c0981da4SDimitry Andric 
215c0981da4SDimitry Andric Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
createDefaultMemoryManager(SimpleRemoteEPC & SREPC)216c0981da4SDimitry Andric SimpleRemoteEPC::createDefaultMemoryManager(SimpleRemoteEPC &SREPC) {
217c0981da4SDimitry Andric   EPCGenericJITLinkMemoryManager::SymbolAddrs SAs;
218c0981da4SDimitry Andric   if (auto Err = SREPC.getBootstrapSymbols(
219c0981da4SDimitry Andric           {{SAs.Allocator, rt::SimpleExecutorMemoryManagerInstanceName},
220c0981da4SDimitry Andric            {SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName},
221c0981da4SDimitry Andric            {SAs.Finalize, rt::SimpleExecutorMemoryManagerFinalizeWrapperName},
222c0981da4SDimitry Andric            {SAs.Deallocate,
223c0981da4SDimitry Andric             rt::SimpleExecutorMemoryManagerDeallocateWrapperName}}))
224c0981da4SDimitry Andric     return std::move(Err);
225c0981da4SDimitry Andric 
226c0981da4SDimitry Andric   return std::make_unique<EPCGenericJITLinkMemoryManager>(SREPC, SAs);
227c0981da4SDimitry Andric }
228c0981da4SDimitry Andric 
229c0981da4SDimitry Andric Expected<std::unique_ptr<ExecutorProcessControl::MemoryAccess>>
createDefaultMemoryAccess(SimpleRemoteEPC & SREPC)230c0981da4SDimitry Andric SimpleRemoteEPC::createDefaultMemoryAccess(SimpleRemoteEPC &SREPC) {
231c0981da4SDimitry Andric   return nullptr;
232c0981da4SDimitry Andric }
233c0981da4SDimitry Andric 
sendMessage(SimpleRemoteEPCOpcode OpC,uint64_t SeqNo,ExecutorAddr TagAddr,ArrayRef<char> ArgBytes)234c0981da4SDimitry Andric Error SimpleRemoteEPC::sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
235c0981da4SDimitry Andric                                    ExecutorAddr TagAddr,
236c0981da4SDimitry Andric                                    ArrayRef<char> ArgBytes) {
237c0981da4SDimitry Andric   assert(OpC != SimpleRemoteEPCOpcode::Setup &&
238c0981da4SDimitry Andric          "SimpleRemoteEPC sending Setup message? That's the wrong direction.");
239c0981da4SDimitry Andric 
240c0981da4SDimitry Andric   LLVM_DEBUG({
241c0981da4SDimitry Andric     dbgs() << "SimpleRemoteEPC::sendMessage: opc = ";
242c0981da4SDimitry Andric     switch (OpC) {
243c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::Hangup:
244c0981da4SDimitry Andric       dbgs() << "Hangup";
245c0981da4SDimitry Andric       assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
2467fa27ce4SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Hangup?");
247c0981da4SDimitry Andric       break;
248c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::Result:
249c0981da4SDimitry Andric       dbgs() << "Result";
2507fa27ce4SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Result?");
251c0981da4SDimitry Andric       break;
252c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::CallWrapper:
253c0981da4SDimitry Andric       dbgs() << "CallWrapper";
254c0981da4SDimitry Andric       break;
255c0981da4SDimitry Andric     default:
256c0981da4SDimitry Andric       llvm_unreachable("Invalid opcode");
257c0981da4SDimitry Andric     }
2587fa27ce4SDimitry Andric     dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
259c0981da4SDimitry Andric            << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
260c0981da4SDimitry Andric            << " bytes\n";
261c0981da4SDimitry Andric   });
262c0981da4SDimitry Andric   auto Err = T->sendMessage(OpC, SeqNo, TagAddr, ArgBytes);
263c0981da4SDimitry Andric   LLVM_DEBUG({
264c0981da4SDimitry Andric     if (Err)
265c0981da4SDimitry Andric       dbgs() << "  \\--> SimpleRemoteEPC::sendMessage failed\n";
266c0981da4SDimitry Andric   });
267c0981da4SDimitry Andric   return Err;
268c0981da4SDimitry Andric }
269c0981da4SDimitry Andric 
handleSetup(uint64_t SeqNo,ExecutorAddr TagAddr,SimpleRemoteEPCArgBytesVector ArgBytes)270c0981da4SDimitry Andric Error SimpleRemoteEPC::handleSetup(uint64_t SeqNo, ExecutorAddr TagAddr,
271c0981da4SDimitry Andric                                    SimpleRemoteEPCArgBytesVector ArgBytes) {
272c0981da4SDimitry Andric   if (SeqNo != 0)
273c0981da4SDimitry Andric     return make_error<StringError>("Setup packet SeqNo not zero",
274c0981da4SDimitry Andric                                    inconvertibleErrorCode());
275c0981da4SDimitry Andric 
276c0981da4SDimitry Andric   if (TagAddr)
277c0981da4SDimitry Andric     return make_error<StringError>("Setup packet TagAddr not zero",
278c0981da4SDimitry Andric                                    inconvertibleErrorCode());
279c0981da4SDimitry Andric 
280c0981da4SDimitry Andric   std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
281c0981da4SDimitry Andric   auto I = PendingCallWrapperResults.find(0);
282c0981da4SDimitry Andric   assert(PendingCallWrapperResults.size() == 1 &&
283c0981da4SDimitry Andric          I != PendingCallWrapperResults.end() &&
284c0981da4SDimitry Andric          "Setup message handler not connectly set up");
285c0981da4SDimitry Andric   auto SetupMsgHandler = std::move(I->second);
286c0981da4SDimitry Andric   PendingCallWrapperResults.erase(I);
287c0981da4SDimitry Andric 
288c0981da4SDimitry Andric   auto WFR =
289c0981da4SDimitry Andric       shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
290c0981da4SDimitry Andric   SetupMsgHandler(std::move(WFR));
291c0981da4SDimitry Andric   return Error::success();
292c0981da4SDimitry Andric }
293c0981da4SDimitry Andric 
setup(Setup S)294c0981da4SDimitry Andric Error SimpleRemoteEPC::setup(Setup S) {
295c0981da4SDimitry Andric   using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
296c0981da4SDimitry Andric 
297c0981da4SDimitry Andric   std::promise<MSVCPExpected<SimpleRemoteEPCExecutorInfo>> EIP;
298c0981da4SDimitry Andric   auto EIF = EIP.get_future();
299c0981da4SDimitry Andric 
300c0981da4SDimitry Andric   // Prepare a handler for the setup packet.
301c0981da4SDimitry Andric   PendingCallWrapperResults[0] =
302c0981da4SDimitry Andric     RunInPlace()(
303c0981da4SDimitry Andric       [&](shared::WrapperFunctionResult SetupMsgBytes) {
304c0981da4SDimitry Andric         if (const char *ErrMsg = SetupMsgBytes.getOutOfBandError()) {
305c0981da4SDimitry Andric           EIP.set_value(
306c0981da4SDimitry Andric               make_error<StringError>(ErrMsg, inconvertibleErrorCode()));
307c0981da4SDimitry Andric           return;
308c0981da4SDimitry Andric         }
309c0981da4SDimitry Andric         using SPSSerialize =
310c0981da4SDimitry Andric             shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;
311c0981da4SDimitry Andric         shared::SPSInputBuffer IB(SetupMsgBytes.data(), SetupMsgBytes.size());
312c0981da4SDimitry Andric         SimpleRemoteEPCExecutorInfo EI;
313c0981da4SDimitry Andric         if (SPSSerialize::deserialize(IB, EI))
314c0981da4SDimitry Andric           EIP.set_value(EI);
315c0981da4SDimitry Andric         else
316c0981da4SDimitry Andric           EIP.set_value(make_error<StringError>(
317c0981da4SDimitry Andric               "Could not deserialize setup message", inconvertibleErrorCode()));
318c0981da4SDimitry Andric       });
319c0981da4SDimitry Andric 
320c0981da4SDimitry Andric   // Start the transport.
321c0981da4SDimitry Andric   if (auto Err = T->start())
322c0981da4SDimitry Andric     return Err;
323c0981da4SDimitry Andric 
324c0981da4SDimitry Andric   // Wait for setup packet to arrive.
325c0981da4SDimitry Andric   auto EI = EIF.get();
326c0981da4SDimitry Andric   if (!EI) {
327c0981da4SDimitry Andric     T->disconnect();
328c0981da4SDimitry Andric     return EI.takeError();
329c0981da4SDimitry Andric   }
330c0981da4SDimitry Andric 
331c0981da4SDimitry Andric   LLVM_DEBUG({
332c0981da4SDimitry Andric     dbgs() << "SimpleRemoteEPC received setup message:\n"
333c0981da4SDimitry Andric            << "  Triple: " << EI->TargetTriple << "\n"
334c0981da4SDimitry Andric            << "  Page size: " << EI->PageSize << "\n"
3357fa27ce4SDimitry Andric            << "  Bootstrap map" << (EI->BootstrapMap.empty() ? " empty" : ":")
3367fa27ce4SDimitry Andric            << "\n";
3377fa27ce4SDimitry Andric     for (const auto &KV : EI->BootstrapMap)
3387fa27ce4SDimitry Andric       dbgs() << "    " << KV.first() << ": " << KV.second.size()
3397fa27ce4SDimitry Andric              << "-byte SPS encoded buffer\n";
3407fa27ce4SDimitry Andric     dbgs() << "  Bootstrap symbols"
3417fa27ce4SDimitry Andric            << (EI->BootstrapSymbols.empty() ? " empty" : ":") << "\n";
342c0981da4SDimitry Andric     for (const auto &KV : EI->BootstrapSymbols)
3437fa27ce4SDimitry Andric       dbgs() << "    " << KV.first() << ": " << KV.second << "\n";
344c0981da4SDimitry Andric   });
345c0981da4SDimitry Andric   TargetTriple = Triple(EI->TargetTriple);
346c0981da4SDimitry Andric   PageSize = EI->PageSize;
3477fa27ce4SDimitry Andric   BootstrapMap = std::move(EI->BootstrapMap);
348c0981da4SDimitry Andric   BootstrapSymbols = std::move(EI->BootstrapSymbols);
349c0981da4SDimitry Andric 
350c0981da4SDimitry Andric   if (auto Err = getBootstrapSymbols(
351c0981da4SDimitry Andric           {{JDI.JITDispatchContext, ExecutorSessionObjectName},
352c0981da4SDimitry Andric            {JDI.JITDispatchFunction, DispatchFnName},
353e3b55780SDimitry Andric            {RunAsMainAddr, rt::RunAsMainWrapperName},
354e3b55780SDimitry Andric            {RunAsVoidFunctionAddr, rt::RunAsVoidFunctionWrapperName},
355e3b55780SDimitry Andric            {RunAsIntFunctionAddr, rt::RunAsIntFunctionWrapperName}}))
356c0981da4SDimitry Andric     return Err;
357c0981da4SDimitry Andric 
358c0981da4SDimitry Andric   if (auto DM =
359c0981da4SDimitry Andric           EPCGenericDylibManager::CreateWithDefaultBootstrapSymbols(*this))
360c0981da4SDimitry Andric     DylibMgr = std::make_unique<EPCGenericDylibManager>(std::move(*DM));
361c0981da4SDimitry Andric   else
362c0981da4SDimitry Andric     return DM.takeError();
363c0981da4SDimitry Andric 
364c0981da4SDimitry Andric   // Set a default CreateMemoryManager if none is specified.
365c0981da4SDimitry Andric   if (!S.CreateMemoryManager)
366c0981da4SDimitry Andric     S.CreateMemoryManager = createDefaultMemoryManager;
367c0981da4SDimitry Andric 
368c0981da4SDimitry Andric   if (auto MemMgr = S.CreateMemoryManager(*this)) {
369c0981da4SDimitry Andric     OwnedMemMgr = std::move(*MemMgr);
370c0981da4SDimitry Andric     this->MemMgr = OwnedMemMgr.get();
371c0981da4SDimitry Andric   } else
372c0981da4SDimitry Andric     return MemMgr.takeError();
373c0981da4SDimitry Andric 
374c0981da4SDimitry Andric   // Set a default CreateMemoryAccess if none is specified.
375c0981da4SDimitry Andric   if (!S.CreateMemoryAccess)
376c0981da4SDimitry Andric     S.CreateMemoryAccess = createDefaultMemoryAccess;
377c0981da4SDimitry Andric 
378c0981da4SDimitry Andric   if (auto MemAccess = S.CreateMemoryAccess(*this)) {
379c0981da4SDimitry Andric     OwnedMemAccess = std::move(*MemAccess);
380c0981da4SDimitry Andric     this->MemAccess = OwnedMemAccess.get();
381c0981da4SDimitry Andric   } else
382c0981da4SDimitry Andric     return MemAccess.takeError();
383c0981da4SDimitry Andric 
384c0981da4SDimitry Andric   return Error::success();
385c0981da4SDimitry Andric }
386c0981da4SDimitry Andric 
handleResult(uint64_t SeqNo,ExecutorAddr TagAddr,SimpleRemoteEPCArgBytesVector ArgBytes)387c0981da4SDimitry Andric Error SimpleRemoteEPC::handleResult(uint64_t SeqNo, ExecutorAddr TagAddr,
388c0981da4SDimitry Andric                                     SimpleRemoteEPCArgBytesVector ArgBytes) {
389c0981da4SDimitry Andric   IncomingWFRHandler SendResult;
390c0981da4SDimitry Andric 
391c0981da4SDimitry Andric   if (TagAddr)
392c0981da4SDimitry Andric     return make_error<StringError>("Unexpected TagAddr in result message",
393c0981da4SDimitry Andric                                    inconvertibleErrorCode());
394c0981da4SDimitry Andric 
395c0981da4SDimitry Andric   {
396c0981da4SDimitry Andric     std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
397c0981da4SDimitry Andric     auto I = PendingCallWrapperResults.find(SeqNo);
398c0981da4SDimitry Andric     if (I == PendingCallWrapperResults.end())
399c0981da4SDimitry Andric       return make_error<StringError>("No call for sequence number " +
400c0981da4SDimitry Andric                                          Twine(SeqNo),
401c0981da4SDimitry Andric                                      inconvertibleErrorCode());
402c0981da4SDimitry Andric     SendResult = std::move(I->second);
403c0981da4SDimitry Andric     PendingCallWrapperResults.erase(I);
404c0981da4SDimitry Andric     releaseSeqNo(SeqNo);
405c0981da4SDimitry Andric   }
406c0981da4SDimitry Andric 
407c0981da4SDimitry Andric   auto WFR =
408c0981da4SDimitry Andric       shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
409c0981da4SDimitry Andric   SendResult(std::move(WFR));
410c0981da4SDimitry Andric   return Error::success();
411c0981da4SDimitry Andric }
412c0981da4SDimitry Andric 
handleCallWrapper(uint64_t RemoteSeqNo,ExecutorAddr TagAddr,SimpleRemoteEPCArgBytesVector ArgBytes)413c0981da4SDimitry Andric void SimpleRemoteEPC::handleCallWrapper(
414c0981da4SDimitry Andric     uint64_t RemoteSeqNo, ExecutorAddr TagAddr,
415c0981da4SDimitry Andric     SimpleRemoteEPCArgBytesVector ArgBytes) {
416c0981da4SDimitry Andric   assert(ES && "No ExecutionSession attached");
417c0981da4SDimitry Andric   D->dispatch(makeGenericNamedTask(
418c0981da4SDimitry Andric       [this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() {
419c0981da4SDimitry Andric         ES->runJITDispatchHandler(
420c0981da4SDimitry Andric             [this, RemoteSeqNo](shared::WrapperFunctionResult WFR) {
421c0981da4SDimitry Andric               if (auto Err =
422c0981da4SDimitry Andric                       sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo,
423c0981da4SDimitry Andric                                   ExecutorAddr(), {WFR.data(), WFR.size()}))
424c0981da4SDimitry Andric                 getExecutionSession().reportError(std::move(Err));
425c0981da4SDimitry Andric             },
4267fa27ce4SDimitry Andric             TagAddr, ArgBytes);
427c0981da4SDimitry Andric       },
428c0981da4SDimitry Andric       "callWrapper task"));
429c0981da4SDimitry Andric }
430c0981da4SDimitry Andric 
handleHangup(SimpleRemoteEPCArgBytesVector ArgBytes)431c0981da4SDimitry Andric Error SimpleRemoteEPC::handleHangup(SimpleRemoteEPCArgBytesVector ArgBytes) {
432c0981da4SDimitry Andric   using namespace llvm::orc::shared;
433c0981da4SDimitry Andric   auto WFR = WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
434c0981da4SDimitry Andric   if (const char *ErrMsg = WFR.getOutOfBandError())
435c0981da4SDimitry Andric     return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
436c0981da4SDimitry Andric 
437c0981da4SDimitry Andric   detail::SPSSerializableError Info;
438c0981da4SDimitry Andric   SPSInputBuffer IB(WFR.data(), WFR.size());
439c0981da4SDimitry Andric   if (!SPSArgList<SPSError>::deserialize(IB, Info))
440c0981da4SDimitry Andric     return make_error<StringError>("Could not deserialize hangup info",
441c0981da4SDimitry Andric                                    inconvertibleErrorCode());
442c0981da4SDimitry Andric   return fromSPSSerializable(std::move(Info));
443c0981da4SDimitry Andric }
444c0981da4SDimitry Andric 
445c0981da4SDimitry Andric } // end namespace orc
446c0981da4SDimitry Andric } // end namespace llvm
447