xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1349cc55cSDimitry Andric //===------- SimpleRemoteEPC.cpp -- Simple remote executor control --------===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric 
9349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"
10349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
11349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h"
12349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
13349cc55cSDimitry Andric #include "llvm/Support/FormatVariadic.h"
14349cc55cSDimitry Andric 
15349cc55cSDimitry Andric #define DEBUG_TYPE "orc"
16349cc55cSDimitry Andric 
17349cc55cSDimitry Andric namespace llvm {
18349cc55cSDimitry Andric namespace orc {
19349cc55cSDimitry Andric 
20349cc55cSDimitry Andric SimpleRemoteEPC::~SimpleRemoteEPC() {
21349cc55cSDimitry Andric #ifndef NDEBUG
22349cc55cSDimitry Andric   std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
23349cc55cSDimitry Andric   assert(Disconnected && "Destroyed without disconnection");
24349cc55cSDimitry Andric #endif // NDEBUG
25349cc55cSDimitry Andric }
26349cc55cSDimitry Andric 
27349cc55cSDimitry Andric Expected<tpctypes::DylibHandle>
28349cc55cSDimitry Andric SimpleRemoteEPC::loadDylib(const char *DylibPath) {
29349cc55cSDimitry Andric   return DylibMgr->open(DylibPath, 0);
30349cc55cSDimitry Andric }
31349cc55cSDimitry Andric 
32*0fca6ea1SDimitry Andric /// Async helper to chain together calls to DylibMgr::lookupAsync to fulfill all
33*0fca6ea1SDimitry Andric /// all the requests.
34*0fca6ea1SDimitry Andric /// FIXME: The dylib manager should support multiple LookupRequests natively.
35*0fca6ea1SDimitry Andric static void
36*0fca6ea1SDimitry Andric lookupSymbolsAsyncHelper(EPCGenericDylibManager &DylibMgr,
37*0fca6ea1SDimitry Andric                          ArrayRef<SimpleRemoteEPC::LookupRequest> Request,
38*0fca6ea1SDimitry Andric                          std::vector<tpctypes::LookupResult> Result,
39*0fca6ea1SDimitry Andric                          SimpleRemoteEPC::SymbolLookupCompleteFn Complete) {
40*0fca6ea1SDimitry Andric   if (Request.empty())
41*0fca6ea1SDimitry Andric     return Complete(std::move(Result));
42349cc55cSDimitry Andric 
43*0fca6ea1SDimitry Andric   auto &Element = Request.front();
44*0fca6ea1SDimitry Andric   DylibMgr.lookupAsync(Element.Handle, Element.Symbols,
45*0fca6ea1SDimitry Andric                        [&DylibMgr, Request, Complete = std::move(Complete),
46*0fca6ea1SDimitry Andric                         Result = std::move(Result)](auto R) mutable {
47*0fca6ea1SDimitry Andric                          if (!R)
48*0fca6ea1SDimitry Andric                            return Complete(R.takeError());
49349cc55cSDimitry Andric                          Result.push_back({});
50349cc55cSDimitry Andric                          Result.back().reserve(R->size());
51349cc55cSDimitry Andric                          for (auto Addr : *R)
52bdd1243dSDimitry Andric                            Result.back().push_back(Addr);
53*0fca6ea1SDimitry Andric 
54*0fca6ea1SDimitry Andric                          lookupSymbolsAsyncHelper(
55*0fca6ea1SDimitry Andric                              DylibMgr, Request.drop_front(), std::move(Result),
56*0fca6ea1SDimitry Andric                              std::move(Complete));
57*0fca6ea1SDimitry Andric                        });
58349cc55cSDimitry Andric }
59*0fca6ea1SDimitry Andric 
60*0fca6ea1SDimitry Andric void SimpleRemoteEPC::lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
61*0fca6ea1SDimitry Andric                                          SymbolLookupCompleteFn Complete) {
62*0fca6ea1SDimitry Andric   lookupSymbolsAsyncHelper(*DylibMgr, Request, {}, std::move(Complete));
63349cc55cSDimitry Andric }
64349cc55cSDimitry Andric 
65349cc55cSDimitry Andric Expected<int32_t> SimpleRemoteEPC::runAsMain(ExecutorAddr MainFnAddr,
66349cc55cSDimitry Andric                                              ArrayRef<std::string> Args) {
67349cc55cSDimitry Andric   int64_t Result = 0;
68349cc55cSDimitry Andric   if (auto Err = callSPSWrapper<rt::SPSRunAsMainSignature>(
6906c3fb27SDimitry Andric           RunAsMainAddr, Result, MainFnAddr, Args))
70349cc55cSDimitry Andric     return std::move(Err);
71349cc55cSDimitry Andric   return Result;
72349cc55cSDimitry Andric }
73349cc55cSDimitry Andric 
74bdd1243dSDimitry Andric Expected<int32_t> SimpleRemoteEPC::runAsVoidFunction(ExecutorAddr VoidFnAddr) {
75bdd1243dSDimitry Andric   int32_t Result = 0;
76bdd1243dSDimitry Andric   if (auto Err = callSPSWrapper<rt::SPSRunAsVoidFunctionSignature>(
7706c3fb27SDimitry Andric           RunAsVoidFunctionAddr, Result, VoidFnAddr))
78bdd1243dSDimitry Andric     return std::move(Err);
79bdd1243dSDimitry Andric   return Result;
80bdd1243dSDimitry Andric }
81bdd1243dSDimitry Andric 
82bdd1243dSDimitry Andric Expected<int32_t> SimpleRemoteEPC::runAsIntFunction(ExecutorAddr IntFnAddr,
83bdd1243dSDimitry Andric                                                     int Arg) {
84bdd1243dSDimitry Andric   int32_t Result = 0;
85bdd1243dSDimitry Andric   if (auto Err = callSPSWrapper<rt::SPSRunAsIntFunctionSignature>(
8606c3fb27SDimitry Andric           RunAsIntFunctionAddr, Result, IntFnAddr, Arg))
87bdd1243dSDimitry Andric     return std::move(Err);
88bdd1243dSDimitry Andric   return Result;
89bdd1243dSDimitry Andric }
90bdd1243dSDimitry Andric 
91349cc55cSDimitry Andric void SimpleRemoteEPC::callWrapperAsync(ExecutorAddr WrapperFnAddr,
92349cc55cSDimitry Andric                                        IncomingWFRHandler OnComplete,
93349cc55cSDimitry Andric                                        ArrayRef<char> ArgBuffer) {
94349cc55cSDimitry Andric   uint64_t SeqNo;
95349cc55cSDimitry Andric   {
96349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
97349cc55cSDimitry Andric     SeqNo = getNextSeqNo();
98349cc55cSDimitry Andric     assert(!PendingCallWrapperResults.count(SeqNo) && "SeqNo already in use");
99349cc55cSDimitry Andric     PendingCallWrapperResults[SeqNo] = std::move(OnComplete);
100349cc55cSDimitry Andric   }
101349cc55cSDimitry Andric 
102349cc55cSDimitry Andric   if (auto Err = sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo,
103349cc55cSDimitry Andric                              WrapperFnAddr, ArgBuffer)) {
104349cc55cSDimitry Andric     IncomingWFRHandler H;
105349cc55cSDimitry Andric 
106349cc55cSDimitry Andric     // We just registered OnComplete, but there may be a race between this
107349cc55cSDimitry Andric     // thread returning from sendMessage and handleDisconnect being called from
108349cc55cSDimitry Andric     // the transport's listener thread. If handleDisconnect gets there first
109349cc55cSDimitry Andric     // then it will have failed 'H' for us. If we get there first (or if
110349cc55cSDimitry Andric     // handleDisconnect already ran) then we need to take care of it.
111349cc55cSDimitry Andric     {
112349cc55cSDimitry Andric       std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
113349cc55cSDimitry Andric       auto I = PendingCallWrapperResults.find(SeqNo);
114349cc55cSDimitry Andric       if (I != PendingCallWrapperResults.end()) {
115349cc55cSDimitry Andric         H = std::move(I->second);
116349cc55cSDimitry Andric         PendingCallWrapperResults.erase(I);
117349cc55cSDimitry Andric       }
118349cc55cSDimitry Andric     }
119349cc55cSDimitry Andric 
120349cc55cSDimitry Andric     if (H)
121349cc55cSDimitry Andric       H(shared::WrapperFunctionResult::createOutOfBandError("disconnecting"));
122349cc55cSDimitry Andric 
123349cc55cSDimitry Andric     getExecutionSession().reportError(std::move(Err));
124349cc55cSDimitry Andric   }
125349cc55cSDimitry Andric }
126349cc55cSDimitry Andric 
127349cc55cSDimitry Andric Error SimpleRemoteEPC::disconnect() {
128349cc55cSDimitry Andric   T->disconnect();
129349cc55cSDimitry Andric   D->shutdown();
130349cc55cSDimitry Andric   std::unique_lock<std::mutex> Lock(SimpleRemoteEPCMutex);
131349cc55cSDimitry Andric   DisconnectCV.wait(Lock, [this] { return Disconnected; });
132349cc55cSDimitry Andric   return std::move(DisconnectErr);
133349cc55cSDimitry Andric }
134349cc55cSDimitry Andric 
135349cc55cSDimitry Andric Expected<SimpleRemoteEPCTransportClient::HandleMessageAction>
136349cc55cSDimitry Andric SimpleRemoteEPC::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
137349cc55cSDimitry Andric                                ExecutorAddr TagAddr,
138349cc55cSDimitry Andric                                SimpleRemoteEPCArgBytesVector ArgBytes) {
139349cc55cSDimitry Andric 
140349cc55cSDimitry Andric   LLVM_DEBUG({
141349cc55cSDimitry Andric     dbgs() << "SimpleRemoteEPC::handleMessage: opc = ";
142349cc55cSDimitry Andric     switch (OpC) {
143349cc55cSDimitry Andric     case SimpleRemoteEPCOpcode::Setup:
144349cc55cSDimitry Andric       dbgs() << "Setup";
145349cc55cSDimitry Andric       assert(SeqNo == 0 && "Non-zero SeqNo for Setup?");
14606c3fb27SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Setup?");
147349cc55cSDimitry Andric       break;
148349cc55cSDimitry Andric     case SimpleRemoteEPCOpcode::Hangup:
149349cc55cSDimitry Andric       dbgs() << "Hangup";
150349cc55cSDimitry Andric       assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
15106c3fb27SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Hangup?");
152349cc55cSDimitry Andric       break;
153349cc55cSDimitry Andric     case SimpleRemoteEPCOpcode::Result:
154349cc55cSDimitry Andric       dbgs() << "Result";
15506c3fb27SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Result?");
156349cc55cSDimitry Andric       break;
157349cc55cSDimitry Andric     case SimpleRemoteEPCOpcode::CallWrapper:
158349cc55cSDimitry Andric       dbgs() << "CallWrapper";
159349cc55cSDimitry Andric       break;
160349cc55cSDimitry Andric     }
16106c3fb27SDimitry Andric     dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
162349cc55cSDimitry Andric            << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
163349cc55cSDimitry Andric            << " bytes\n";
164349cc55cSDimitry Andric   });
165349cc55cSDimitry Andric 
166349cc55cSDimitry Andric   using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;
167349cc55cSDimitry Andric   if (static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC))
168349cc55cSDimitry Andric     return make_error<StringError>("Unexpected opcode",
169349cc55cSDimitry Andric                                    inconvertibleErrorCode());
170349cc55cSDimitry Andric 
171349cc55cSDimitry Andric   switch (OpC) {
172349cc55cSDimitry Andric   case SimpleRemoteEPCOpcode::Setup:
173349cc55cSDimitry Andric     if (auto Err = handleSetup(SeqNo, TagAddr, std::move(ArgBytes)))
174349cc55cSDimitry Andric       return std::move(Err);
175349cc55cSDimitry Andric     break;
176349cc55cSDimitry Andric   case SimpleRemoteEPCOpcode::Hangup:
177349cc55cSDimitry Andric     T->disconnect();
178349cc55cSDimitry Andric     if (auto Err = handleHangup(std::move(ArgBytes)))
179349cc55cSDimitry Andric       return std::move(Err);
180349cc55cSDimitry Andric     return EndSession;
181349cc55cSDimitry Andric   case SimpleRemoteEPCOpcode::Result:
182349cc55cSDimitry Andric     if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))
183349cc55cSDimitry Andric       return std::move(Err);
184349cc55cSDimitry Andric     break;
185349cc55cSDimitry Andric   case SimpleRemoteEPCOpcode::CallWrapper:
186349cc55cSDimitry Andric     handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));
187349cc55cSDimitry Andric     break;
188349cc55cSDimitry Andric   }
189349cc55cSDimitry Andric   return ContinueSession;
190349cc55cSDimitry Andric }
191349cc55cSDimitry Andric 
192349cc55cSDimitry Andric void SimpleRemoteEPC::handleDisconnect(Error Err) {
193349cc55cSDimitry Andric   LLVM_DEBUG({
194349cc55cSDimitry Andric     dbgs() << "SimpleRemoteEPC::handleDisconnect: "
195349cc55cSDimitry Andric            << (Err ? "failure" : "success") << "\n";
196349cc55cSDimitry Andric   });
197349cc55cSDimitry Andric 
198349cc55cSDimitry Andric   PendingCallWrapperResultsMap TmpPending;
199349cc55cSDimitry Andric 
200349cc55cSDimitry Andric   {
201349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
202349cc55cSDimitry Andric     std::swap(TmpPending, PendingCallWrapperResults);
203349cc55cSDimitry Andric   }
204349cc55cSDimitry Andric 
205349cc55cSDimitry Andric   for (auto &KV : TmpPending)
206349cc55cSDimitry Andric     KV.second(
207349cc55cSDimitry Andric         shared::WrapperFunctionResult::createOutOfBandError("disconnecting"));
208349cc55cSDimitry Andric 
209349cc55cSDimitry Andric   std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
210349cc55cSDimitry Andric   DisconnectErr = joinErrors(std::move(DisconnectErr), std::move(Err));
211349cc55cSDimitry Andric   Disconnected = true;
212349cc55cSDimitry Andric   DisconnectCV.notify_all();
213349cc55cSDimitry Andric }
214349cc55cSDimitry Andric 
215349cc55cSDimitry Andric Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
216349cc55cSDimitry Andric SimpleRemoteEPC::createDefaultMemoryManager(SimpleRemoteEPC &SREPC) {
217349cc55cSDimitry Andric   EPCGenericJITLinkMemoryManager::SymbolAddrs SAs;
218349cc55cSDimitry Andric   if (auto Err = SREPC.getBootstrapSymbols(
219349cc55cSDimitry Andric           {{SAs.Allocator, rt::SimpleExecutorMemoryManagerInstanceName},
220349cc55cSDimitry Andric            {SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName},
221349cc55cSDimitry Andric            {SAs.Finalize, rt::SimpleExecutorMemoryManagerFinalizeWrapperName},
222349cc55cSDimitry Andric            {SAs.Deallocate,
223349cc55cSDimitry Andric             rt::SimpleExecutorMemoryManagerDeallocateWrapperName}}))
224349cc55cSDimitry Andric     return std::move(Err);
225349cc55cSDimitry Andric 
226349cc55cSDimitry Andric   return std::make_unique<EPCGenericJITLinkMemoryManager>(SREPC, SAs);
227349cc55cSDimitry Andric }
228349cc55cSDimitry Andric 
229349cc55cSDimitry Andric Expected<std::unique_ptr<ExecutorProcessControl::MemoryAccess>>
230349cc55cSDimitry Andric SimpleRemoteEPC::createDefaultMemoryAccess(SimpleRemoteEPC &SREPC) {
231349cc55cSDimitry Andric   return nullptr;
232349cc55cSDimitry Andric }
233349cc55cSDimitry Andric 
234349cc55cSDimitry Andric Error SimpleRemoteEPC::sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
235349cc55cSDimitry Andric                                    ExecutorAddr TagAddr,
236349cc55cSDimitry Andric                                    ArrayRef<char> ArgBytes) {
237349cc55cSDimitry Andric   assert(OpC != SimpleRemoteEPCOpcode::Setup &&
238349cc55cSDimitry Andric          "SimpleRemoteEPC sending Setup message? That's the wrong direction.");
239349cc55cSDimitry Andric 
240349cc55cSDimitry Andric   LLVM_DEBUG({
241349cc55cSDimitry Andric     dbgs() << "SimpleRemoteEPC::sendMessage: opc = ";
242349cc55cSDimitry Andric     switch (OpC) {
243349cc55cSDimitry Andric     case SimpleRemoteEPCOpcode::Hangup:
244349cc55cSDimitry Andric       dbgs() << "Hangup";
245349cc55cSDimitry Andric       assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
24606c3fb27SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Hangup?");
247349cc55cSDimitry Andric       break;
248349cc55cSDimitry Andric     case SimpleRemoteEPCOpcode::Result:
249349cc55cSDimitry Andric       dbgs() << "Result";
25006c3fb27SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Result?");
251349cc55cSDimitry Andric       break;
252349cc55cSDimitry Andric     case SimpleRemoteEPCOpcode::CallWrapper:
253349cc55cSDimitry Andric       dbgs() << "CallWrapper";
254349cc55cSDimitry Andric       break;
255349cc55cSDimitry Andric     default:
256349cc55cSDimitry Andric       llvm_unreachable("Invalid opcode");
257349cc55cSDimitry Andric     }
25806c3fb27SDimitry Andric     dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
259349cc55cSDimitry Andric            << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
260349cc55cSDimitry Andric            << " bytes\n";
261349cc55cSDimitry Andric   });
262349cc55cSDimitry Andric   auto Err = T->sendMessage(OpC, SeqNo, TagAddr, ArgBytes);
263349cc55cSDimitry Andric   LLVM_DEBUG({
264349cc55cSDimitry Andric     if (Err)
265349cc55cSDimitry Andric       dbgs() << "  \\--> SimpleRemoteEPC::sendMessage failed\n";
266349cc55cSDimitry Andric   });
267349cc55cSDimitry Andric   return Err;
268349cc55cSDimitry Andric }
269349cc55cSDimitry Andric 
270349cc55cSDimitry Andric Error SimpleRemoteEPC::handleSetup(uint64_t SeqNo, ExecutorAddr TagAddr,
271349cc55cSDimitry Andric                                    SimpleRemoteEPCArgBytesVector ArgBytes) {
272349cc55cSDimitry Andric   if (SeqNo != 0)
273349cc55cSDimitry Andric     return make_error<StringError>("Setup packet SeqNo not zero",
274349cc55cSDimitry Andric                                    inconvertibleErrorCode());
275349cc55cSDimitry Andric 
276349cc55cSDimitry Andric   if (TagAddr)
277349cc55cSDimitry Andric     return make_error<StringError>("Setup packet TagAddr not zero",
278349cc55cSDimitry Andric                                    inconvertibleErrorCode());
279349cc55cSDimitry Andric 
280349cc55cSDimitry Andric   std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
281349cc55cSDimitry Andric   auto I = PendingCallWrapperResults.find(0);
282349cc55cSDimitry Andric   assert(PendingCallWrapperResults.size() == 1 &&
283349cc55cSDimitry Andric          I != PendingCallWrapperResults.end() &&
284349cc55cSDimitry Andric          "Setup message handler not connectly set up");
285349cc55cSDimitry Andric   auto SetupMsgHandler = std::move(I->second);
286349cc55cSDimitry Andric   PendingCallWrapperResults.erase(I);
287349cc55cSDimitry Andric 
288349cc55cSDimitry Andric   auto WFR =
289349cc55cSDimitry Andric       shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
290349cc55cSDimitry Andric   SetupMsgHandler(std::move(WFR));
291349cc55cSDimitry Andric   return Error::success();
292349cc55cSDimitry Andric }
293349cc55cSDimitry Andric 
294349cc55cSDimitry Andric Error SimpleRemoteEPC::setup(Setup S) {
295349cc55cSDimitry Andric   using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
296349cc55cSDimitry Andric 
297349cc55cSDimitry Andric   std::promise<MSVCPExpected<SimpleRemoteEPCExecutorInfo>> EIP;
298349cc55cSDimitry Andric   auto EIF = EIP.get_future();
299349cc55cSDimitry Andric 
300349cc55cSDimitry Andric   // Prepare a handler for the setup packet.
301349cc55cSDimitry Andric   PendingCallWrapperResults[0] =
302349cc55cSDimitry Andric     RunInPlace()(
303349cc55cSDimitry Andric       [&](shared::WrapperFunctionResult SetupMsgBytes) {
304349cc55cSDimitry Andric         if (const char *ErrMsg = SetupMsgBytes.getOutOfBandError()) {
305349cc55cSDimitry Andric           EIP.set_value(
306349cc55cSDimitry Andric               make_error<StringError>(ErrMsg, inconvertibleErrorCode()));
307349cc55cSDimitry Andric           return;
308349cc55cSDimitry Andric         }
309349cc55cSDimitry Andric         using SPSSerialize =
310349cc55cSDimitry Andric             shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;
311349cc55cSDimitry Andric         shared::SPSInputBuffer IB(SetupMsgBytes.data(), SetupMsgBytes.size());
312349cc55cSDimitry Andric         SimpleRemoteEPCExecutorInfo EI;
313349cc55cSDimitry Andric         if (SPSSerialize::deserialize(IB, EI))
314349cc55cSDimitry Andric           EIP.set_value(EI);
315349cc55cSDimitry Andric         else
316349cc55cSDimitry Andric           EIP.set_value(make_error<StringError>(
317349cc55cSDimitry Andric               "Could not deserialize setup message", inconvertibleErrorCode()));
318349cc55cSDimitry Andric       });
319349cc55cSDimitry Andric 
320349cc55cSDimitry Andric   // Start the transport.
321349cc55cSDimitry Andric   if (auto Err = T->start())
322349cc55cSDimitry Andric     return Err;
323349cc55cSDimitry Andric 
324349cc55cSDimitry Andric   // Wait for setup packet to arrive.
325349cc55cSDimitry Andric   auto EI = EIF.get();
326349cc55cSDimitry Andric   if (!EI) {
327349cc55cSDimitry Andric     T->disconnect();
328349cc55cSDimitry Andric     return EI.takeError();
329349cc55cSDimitry Andric   }
330349cc55cSDimitry Andric 
331349cc55cSDimitry Andric   LLVM_DEBUG({
332349cc55cSDimitry Andric     dbgs() << "SimpleRemoteEPC received setup message:\n"
333349cc55cSDimitry Andric            << "  Triple: " << EI->TargetTriple << "\n"
334349cc55cSDimitry Andric            << "  Page size: " << EI->PageSize << "\n"
33506c3fb27SDimitry Andric            << "  Bootstrap map" << (EI->BootstrapMap.empty() ? " empty" : ":")
33606c3fb27SDimitry Andric            << "\n";
33706c3fb27SDimitry Andric     for (const auto &KV : EI->BootstrapMap)
33806c3fb27SDimitry Andric       dbgs() << "    " << KV.first() << ": " << KV.second.size()
33906c3fb27SDimitry Andric              << "-byte SPS encoded buffer\n";
34006c3fb27SDimitry Andric     dbgs() << "  Bootstrap symbols"
34106c3fb27SDimitry Andric            << (EI->BootstrapSymbols.empty() ? " empty" : ":") << "\n";
342349cc55cSDimitry Andric     for (const auto &KV : EI->BootstrapSymbols)
34306c3fb27SDimitry Andric       dbgs() << "    " << KV.first() << ": " << KV.second << "\n";
344349cc55cSDimitry Andric   });
345349cc55cSDimitry Andric   TargetTriple = Triple(EI->TargetTriple);
346349cc55cSDimitry Andric   PageSize = EI->PageSize;
34706c3fb27SDimitry Andric   BootstrapMap = std::move(EI->BootstrapMap);
348349cc55cSDimitry Andric   BootstrapSymbols = std::move(EI->BootstrapSymbols);
349349cc55cSDimitry Andric 
350349cc55cSDimitry Andric   if (auto Err = getBootstrapSymbols(
351349cc55cSDimitry Andric           {{JDI.JITDispatchContext, ExecutorSessionObjectName},
352349cc55cSDimitry Andric            {JDI.JITDispatchFunction, DispatchFnName},
353bdd1243dSDimitry Andric            {RunAsMainAddr, rt::RunAsMainWrapperName},
354bdd1243dSDimitry Andric            {RunAsVoidFunctionAddr, rt::RunAsVoidFunctionWrapperName},
355bdd1243dSDimitry Andric            {RunAsIntFunctionAddr, rt::RunAsIntFunctionWrapperName}}))
356349cc55cSDimitry Andric     return Err;
357349cc55cSDimitry Andric 
358349cc55cSDimitry Andric   if (auto DM =
359349cc55cSDimitry Andric           EPCGenericDylibManager::CreateWithDefaultBootstrapSymbols(*this))
360349cc55cSDimitry Andric     DylibMgr = std::make_unique<EPCGenericDylibManager>(std::move(*DM));
361349cc55cSDimitry Andric   else
362349cc55cSDimitry Andric     return DM.takeError();
363349cc55cSDimitry Andric 
364349cc55cSDimitry Andric   // Set a default CreateMemoryManager if none is specified.
365349cc55cSDimitry Andric   if (!S.CreateMemoryManager)
366349cc55cSDimitry Andric     S.CreateMemoryManager = createDefaultMemoryManager;
367349cc55cSDimitry Andric 
368349cc55cSDimitry Andric   if (auto MemMgr = S.CreateMemoryManager(*this)) {
369349cc55cSDimitry Andric     OwnedMemMgr = std::move(*MemMgr);
370349cc55cSDimitry Andric     this->MemMgr = OwnedMemMgr.get();
371349cc55cSDimitry Andric   } else
372349cc55cSDimitry Andric     return MemMgr.takeError();
373349cc55cSDimitry Andric 
374349cc55cSDimitry Andric   // Set a default CreateMemoryAccess if none is specified.
375349cc55cSDimitry Andric   if (!S.CreateMemoryAccess)
376349cc55cSDimitry Andric     S.CreateMemoryAccess = createDefaultMemoryAccess;
377349cc55cSDimitry Andric 
378349cc55cSDimitry Andric   if (auto MemAccess = S.CreateMemoryAccess(*this)) {
379349cc55cSDimitry Andric     OwnedMemAccess = std::move(*MemAccess);
380349cc55cSDimitry Andric     this->MemAccess = OwnedMemAccess.get();
381349cc55cSDimitry Andric   } else
382349cc55cSDimitry Andric     return MemAccess.takeError();
383349cc55cSDimitry Andric 
384349cc55cSDimitry Andric   return Error::success();
385349cc55cSDimitry Andric }
386349cc55cSDimitry Andric 
387349cc55cSDimitry Andric Error SimpleRemoteEPC::handleResult(uint64_t SeqNo, ExecutorAddr TagAddr,
388349cc55cSDimitry Andric                                     SimpleRemoteEPCArgBytesVector ArgBytes) {
389349cc55cSDimitry Andric   IncomingWFRHandler SendResult;
390349cc55cSDimitry Andric 
391349cc55cSDimitry Andric   if (TagAddr)
392349cc55cSDimitry Andric     return make_error<StringError>("Unexpected TagAddr in result message",
393349cc55cSDimitry Andric                                    inconvertibleErrorCode());
394349cc55cSDimitry Andric 
395349cc55cSDimitry Andric   {
396349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
397349cc55cSDimitry Andric     auto I = PendingCallWrapperResults.find(SeqNo);
398349cc55cSDimitry Andric     if (I == PendingCallWrapperResults.end())
399349cc55cSDimitry Andric       return make_error<StringError>("No call for sequence number " +
400349cc55cSDimitry Andric                                          Twine(SeqNo),
401349cc55cSDimitry Andric                                      inconvertibleErrorCode());
402349cc55cSDimitry Andric     SendResult = std::move(I->second);
403349cc55cSDimitry Andric     PendingCallWrapperResults.erase(I);
404349cc55cSDimitry Andric     releaseSeqNo(SeqNo);
405349cc55cSDimitry Andric   }
406349cc55cSDimitry Andric 
407349cc55cSDimitry Andric   auto WFR =
408349cc55cSDimitry Andric       shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
409349cc55cSDimitry Andric   SendResult(std::move(WFR));
410349cc55cSDimitry Andric   return Error::success();
411349cc55cSDimitry Andric }
412349cc55cSDimitry Andric 
413349cc55cSDimitry Andric void SimpleRemoteEPC::handleCallWrapper(
414349cc55cSDimitry Andric     uint64_t RemoteSeqNo, ExecutorAddr TagAddr,
415349cc55cSDimitry Andric     SimpleRemoteEPCArgBytesVector ArgBytes) {
416349cc55cSDimitry Andric   assert(ES && "No ExecutionSession attached");
417349cc55cSDimitry Andric   D->dispatch(makeGenericNamedTask(
418349cc55cSDimitry Andric       [this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() {
419349cc55cSDimitry Andric         ES->runJITDispatchHandler(
420349cc55cSDimitry Andric             [this, RemoteSeqNo](shared::WrapperFunctionResult WFR) {
421349cc55cSDimitry Andric               if (auto Err =
422349cc55cSDimitry Andric                       sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo,
423349cc55cSDimitry Andric                                   ExecutorAddr(), {WFR.data(), WFR.size()}))
424349cc55cSDimitry Andric                 getExecutionSession().reportError(std::move(Err));
425349cc55cSDimitry Andric             },
42606c3fb27SDimitry Andric             TagAddr, ArgBytes);
427349cc55cSDimitry Andric       },
428349cc55cSDimitry Andric       "callWrapper task"));
429349cc55cSDimitry Andric }
430349cc55cSDimitry Andric 
431349cc55cSDimitry Andric Error SimpleRemoteEPC::handleHangup(SimpleRemoteEPCArgBytesVector ArgBytes) {
432349cc55cSDimitry Andric   using namespace llvm::orc::shared;
433349cc55cSDimitry Andric   auto WFR = WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
434349cc55cSDimitry Andric   if (const char *ErrMsg = WFR.getOutOfBandError())
435349cc55cSDimitry Andric     return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
436349cc55cSDimitry Andric 
437349cc55cSDimitry Andric   detail::SPSSerializableError Info;
438349cc55cSDimitry Andric   SPSInputBuffer IB(WFR.data(), WFR.size());
439349cc55cSDimitry Andric   if (!SPSArgList<SPSError>::deserialize(IB, Info))
440349cc55cSDimitry Andric     return make_error<StringError>("Could not deserialize hangup info",
441349cc55cSDimitry Andric                                    inconvertibleErrorCode());
442349cc55cSDimitry Andric   return fromSPSSerializable(std::move(Info));
443349cc55cSDimitry Andric }
444349cc55cSDimitry Andric 
445349cc55cSDimitry Andric } // end namespace orc
446349cc55cSDimitry Andric } // end namespace llvm
447