xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp (revision 8201ae2aa662a1bcba80751f3ef162f228f626f7)
1bb72f073SLang Hames //===------- SimpleRemoteEPC.cpp -- Simple remote executor control --------===//
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/SimpleRemoteEPC.h"
10bb72f073SLang Hames #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
112c8e7849SLang Hames #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12bb72f073SLang Hames #include "llvm/Support/FormatVariadic.h"
13bb72f073SLang Hames 
14bb72f073SLang Hames #define DEBUG_TYPE "orc"
15bb72f073SLang Hames 
16bb72f073SLang Hames namespace llvm {
17bb72f073SLang Hames namespace orc {
18bb72f073SLang Hames 
19bb72f073SLang Hames SimpleRemoteEPC::~SimpleRemoteEPC() {
20320832ccSLang Hames #ifndef NDEBUG
21320832ccSLang Hames   std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
22bb72f073SLang Hames   assert(Disconnected && "Destroyed without disconnection");
23320832ccSLang Hames #endif // NDEBUG
24bb72f073SLang Hames }
25bb72f073SLang Hames 
26bb72f073SLang Hames Expected<tpctypes::DylibHandle>
27bb72f073SLang Hames SimpleRemoteEPC::loadDylib(const char *DylibPath) {
28db21bd4fSLang Hames   return EPCDylibMgr->open(DylibPath, 0);
29bb72f073SLang Hames }
30bb72f073SLang Hames 
3154226e23SBen Langmuir /// Async helper to chain together calls to DylibMgr::lookupAsync to fulfill all
3254226e23SBen Langmuir /// all the requests.
3354226e23SBen Langmuir /// FIXME: The dylib manager should support multiple LookupRequests natively.
3454226e23SBen Langmuir static void
3554226e23SBen Langmuir lookupSymbolsAsyncHelper(EPCGenericDylibManager &DylibMgr,
36db21bd4fSLang Hames                          ArrayRef<DylibManager::LookupRequest> Request,
3754226e23SBen Langmuir                          std::vector<tpctypes::LookupResult> Result,
38db21bd4fSLang Hames                          DylibManager::SymbolLookupCompleteFn Complete) {
3954226e23SBen Langmuir   if (Request.empty())
4054226e23SBen Langmuir     return Complete(std::move(Result));
41bb72f073SLang Hames 
4254226e23SBen Langmuir   auto &Element = Request.front();
4354226e23SBen Langmuir   DylibMgr.lookupAsync(Element.Handle, Element.Symbols,
4454226e23SBen Langmuir                        [&DylibMgr, Request, Complete = std::move(Complete),
4554226e23SBen Langmuir                         Result = std::move(Result)](auto R) mutable {
4654226e23SBen Langmuir                          if (!R)
4754226e23SBen Langmuir                            return Complete(R.takeError());
48a2c1cf09SLang Hames                          Result.push_back({});
49a2c1cf09SLang Hames                          Result.back().reserve(R->size());
50a2c1cf09SLang Hames                          for (auto Addr : *R)
516613f4afSLang Hames                            Result.back().push_back(Addr);
5254226e23SBen Langmuir 
5354226e23SBen Langmuir                          lookupSymbolsAsyncHelper(
5454226e23SBen Langmuir                              DylibMgr, Request.drop_front(), std::move(Result),
5554226e23SBen Langmuir                              std::move(Complete));
5654226e23SBen Langmuir                        });
57a2c1cf09SLang Hames }
5854226e23SBen Langmuir 
5954226e23SBen Langmuir void SimpleRemoteEPC::lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
6054226e23SBen Langmuir                                          SymbolLookupCompleteFn Complete) {
61db21bd4fSLang Hames   lookupSymbolsAsyncHelper(*EPCDylibMgr, Request, {}, std::move(Complete));
62bb72f073SLang Hames }
63bb72f073SLang Hames 
6421a06254SLang Hames Expected<int32_t> SimpleRemoteEPC::runAsMain(ExecutorAddr MainFnAddr,
65bb72f073SLang Hames                                              ArrayRef<std::string> Args) {
66bb72f073SLang Hames   int64_t Result = 0;
672c8e7849SLang Hames   if (auto Err = callSPSWrapper<rt::SPSRunAsMainSignature>(
685baaf0c2SLang Hames           RunAsMainAddr, Result, MainFnAddr, Args))
69bb72f073SLang Hames     return std::move(Err);
70bb72f073SLang Hames   return Result;
71bb72f073SLang Hames }
72bb72f073SLang Hames 
737260cdd2SSunho Kim Expected<int32_t> SimpleRemoteEPC::runAsVoidFunction(ExecutorAddr VoidFnAddr) {
747260cdd2SSunho Kim   int32_t Result = 0;
757260cdd2SSunho Kim   if (auto Err = callSPSWrapper<rt::SPSRunAsVoidFunctionSignature>(
765baaf0c2SLang Hames           RunAsVoidFunctionAddr, Result, VoidFnAddr))
777260cdd2SSunho Kim     return std::move(Err);
787260cdd2SSunho Kim   return Result;
797260cdd2SSunho Kim }
807260cdd2SSunho Kim 
817260cdd2SSunho Kim Expected<int32_t> SimpleRemoteEPC::runAsIntFunction(ExecutorAddr IntFnAddr,
827260cdd2SSunho Kim                                                     int Arg) {
837260cdd2SSunho Kim   int32_t Result = 0;
847260cdd2SSunho Kim   if (auto Err = callSPSWrapper<rt::SPSRunAsIntFunctionSignature>(
855baaf0c2SLang Hames           RunAsIntFunctionAddr, Result, IntFnAddr, Arg))
867260cdd2SSunho Kim     return std::move(Err);
877260cdd2SSunho Kim   return Result;
887260cdd2SSunho Kim }
897260cdd2SSunho Kim 
90da7f993aSLang Hames void SimpleRemoteEPC::callWrapperAsync(ExecutorAddr WrapperFnAddr,
914d7cea3dSLang Hames                                        IncomingWFRHandler OnComplete,
92bb72f073SLang Hames                                        ArrayRef<char> ArgBuffer) {
93bb72f073SLang Hames   uint64_t SeqNo;
94bb72f073SLang Hames   {
95bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
96bb72f073SLang Hames     SeqNo = getNextSeqNo();
97bb72f073SLang Hames     assert(!PendingCallWrapperResults.count(SeqNo) && "SeqNo already in use");
98bb72f073SLang Hames     PendingCallWrapperResults[SeqNo] = std::move(OnComplete);
99bb72f073SLang Hames   }
100bb72f073SLang Hames 
101175c1a39SLang Hames   if (auto Err = sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo,
10221a06254SLang Hames                              WrapperFnAddr, ArgBuffer)) {
10317a0858fSLang Hames     IncomingWFRHandler H;
10417a0858fSLang Hames 
10517a0858fSLang Hames     // We just registered OnComplete, but there may be a race between this
10617a0858fSLang Hames     // thread returning from sendMessage and handleDisconnect being called from
10717a0858fSLang Hames     // the transport's listener thread. If handleDisconnect gets there first
10817a0858fSLang Hames     // then it will have failed 'H' for us. If we get there first (or if
10917a0858fSLang Hames     // handleDisconnect already ran) then we need to take care of it.
11017a0858fSLang Hames     {
11117a0858fSLang Hames       std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
11217a0858fSLang Hames       auto I = PendingCallWrapperResults.find(SeqNo);
11317a0858fSLang Hames       if (I != PendingCallWrapperResults.end()) {
11417a0858fSLang Hames         H = std::move(I->second);
11517a0858fSLang Hames         PendingCallWrapperResults.erase(I);
11617a0858fSLang Hames       }
11717a0858fSLang Hames     }
11817a0858fSLang Hames 
11917a0858fSLang Hames     if (H)
12017a0858fSLang Hames       H(shared::WrapperFunctionResult::createOutOfBandError("disconnecting"));
12117a0858fSLang Hames 
122bb72f073SLang Hames     getExecutionSession().reportError(std::move(Err));
123bb72f073SLang Hames   }
124bb72f073SLang Hames }
125bb72f073SLang Hames 
126bb72f073SLang Hames Error SimpleRemoteEPC::disconnect() {
127bb72f073SLang Hames   T->disconnect();
1282815ed57SLang Hames   D->shutdown();
129320832ccSLang Hames   std::unique_lock<std::mutex> Lock(SimpleRemoteEPCMutex);
130320832ccSLang Hames   DisconnectCV.wait(Lock, [this] { return Disconnected; });
131320832ccSLang Hames   return std::move(DisconnectErr);
132bb72f073SLang Hames }
133bb72f073SLang Hames 
134bb72f073SLang Hames Expected<SimpleRemoteEPCTransportClient::HandleMessageAction>
135bb72f073SLang Hames SimpleRemoteEPC::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
136ef391df2SLang Hames                                ExecutorAddr TagAddr,
137bb72f073SLang Hames                                SimpleRemoteEPCArgBytesVector ArgBytes) {
138175c1a39SLang Hames 
139175c1a39SLang Hames   LLVM_DEBUG({
140175c1a39SLang Hames     dbgs() << "SimpleRemoteEPC::handleMessage: opc = ";
141175c1a39SLang Hames     switch (OpC) {
142175c1a39SLang Hames     case SimpleRemoteEPCOpcode::Setup:
143175c1a39SLang Hames       dbgs() << "Setup";
144175c1a39SLang Hames       assert(SeqNo == 0 && "Non-zero SeqNo for Setup?");
145577f316cSLang Hames       assert(!TagAddr && "Non-zero TagAddr for Setup?");
146175c1a39SLang Hames       break;
147175c1a39SLang Hames     case SimpleRemoteEPCOpcode::Hangup:
148175c1a39SLang Hames       dbgs() << "Hangup";
149175c1a39SLang Hames       assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
150577f316cSLang Hames       assert(!TagAddr && "Non-zero TagAddr for Hangup?");
151175c1a39SLang Hames       break;
152175c1a39SLang Hames     case SimpleRemoteEPCOpcode::Result:
153175c1a39SLang Hames       dbgs() << "Result";
154577f316cSLang Hames       assert(!TagAddr && "Non-zero TagAddr for Result?");
155175c1a39SLang Hames       break;
156175c1a39SLang Hames     case SimpleRemoteEPCOpcode::CallWrapper:
157175c1a39SLang Hames       dbgs() << "CallWrapper";
158175c1a39SLang Hames       break;
159175c1a39SLang Hames     }
160577f316cSLang Hames     dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
161175c1a39SLang Hames            << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
162175c1a39SLang Hames            << " bytes\n";
163175c1a39SLang Hames   });
164175c1a39SLang Hames 
165bb72f073SLang Hames   using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;
166d11a0c5dSLang Hames   if (static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC))
167bb72f073SLang Hames     return make_error<StringError>("Unexpected opcode",
168bb72f073SLang Hames                                    inconvertibleErrorCode());
169bb72f073SLang Hames 
170bb72f073SLang Hames   switch (OpC) {
171bb72f073SLang Hames   case SimpleRemoteEPCOpcode::Setup:
172bb72f073SLang Hames     if (auto Err = handleSetup(SeqNo, TagAddr, std::move(ArgBytes)))
173bb72f073SLang Hames       return std::move(Err);
174bb72f073SLang Hames     break;
175bb72f073SLang Hames   case SimpleRemoteEPCOpcode::Hangup:
176a6c95063SStefan Gränitz     T->disconnect();
177a6c95063SStefan Gränitz     if (auto Err = handleHangup(std::move(ArgBytes)))
178a6c95063SStefan Gränitz       return std::move(Err);
179a6c95063SStefan Gränitz     return EndSession;
180bb72f073SLang Hames   case SimpleRemoteEPCOpcode::Result:
181bb72f073SLang Hames     if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))
182bb72f073SLang Hames       return std::move(Err);
183bb72f073SLang Hames     break;
184bb72f073SLang Hames   case SimpleRemoteEPCOpcode::CallWrapper:
185bb72f073SLang Hames     handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));
186bb72f073SLang Hames     break;
187bb72f073SLang Hames   }
188bb72f073SLang Hames   return ContinueSession;
189bb72f073SLang Hames }
190bb72f073SLang Hames 
191bb72f073SLang Hames void SimpleRemoteEPC::handleDisconnect(Error Err) {
192175c1a39SLang Hames   LLVM_DEBUG({
193175c1a39SLang Hames     dbgs() << "SimpleRemoteEPC::handleDisconnect: "
194175c1a39SLang Hames            << (Err ? "failure" : "success") << "\n";
195175c1a39SLang Hames   });
196175c1a39SLang Hames 
197bb72f073SLang Hames   PendingCallWrapperResultsMap TmpPending;
198bb72f073SLang Hames 
199bb72f073SLang Hames   {
200bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
201bb72f073SLang Hames     std::swap(TmpPending, PendingCallWrapperResults);
202bb72f073SLang Hames   }
203bb72f073SLang Hames 
204bb72f073SLang Hames   for (auto &KV : TmpPending)
205bb72f073SLang Hames     KV.second(
206bb72f073SLang Hames         shared::WrapperFunctionResult::createOutOfBandError("disconnecting"));
207bb72f073SLang Hames 
208320832ccSLang Hames   std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
209320832ccSLang Hames   DisconnectErr = joinErrors(std::move(DisconnectErr), std::move(Err));
210320832ccSLang Hames   Disconnected = true;
211320832ccSLang Hames   DisconnectCV.notify_all();
212bb72f073SLang Hames }
213bb72f073SLang Hames 
214b64fc0afSLang Hames Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
2154fcc0ac1SLang Hames SimpleRemoteEPC::createDefaultMemoryManager(SimpleRemoteEPC &SREPC) {
21678b083dbSLang Hames   EPCGenericJITLinkMemoryManager::SymbolAddrs SAs;
2174fcc0ac1SLang Hames   if (auto Err = SREPC.getBootstrapSymbols(
21878b083dbSLang Hames           {{SAs.Allocator, rt::SimpleExecutorMemoryManagerInstanceName},
21978b083dbSLang Hames            {SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName},
22078b083dbSLang Hames            {SAs.Finalize, rt::SimpleExecutorMemoryManagerFinalizeWrapperName},
22178b083dbSLang Hames            {SAs.Deallocate,
22278b083dbSLang Hames             rt::SimpleExecutorMemoryManagerDeallocateWrapperName}}))
223b64fc0afSLang Hames     return std::move(Err);
224bb72f073SLang Hames 
2254fcc0ac1SLang Hames   return std::make_unique<EPCGenericJITLinkMemoryManager>(SREPC, SAs);
226bb72f073SLang Hames }
227bb72f073SLang Hames 
228b64fc0afSLang Hames Expected<std::unique_ptr<ExecutorProcessControl::MemoryAccess>>
2294fcc0ac1SLang Hames SimpleRemoteEPC::createDefaultMemoryAccess(SimpleRemoteEPC &SREPC) {
230*8201ae2aSLang Hames   EPCGenericMemoryAccess::FuncAddrs FAs;
231*8201ae2aSLang Hames   if (auto Err = SREPC.getBootstrapSymbols(
232*8201ae2aSLang Hames           {{FAs.WriteUInt8s, rt::MemoryWriteUInt8sWrapperName},
233*8201ae2aSLang Hames            {FAs.WriteUInt16s, rt::MemoryWriteUInt16sWrapperName},
234*8201ae2aSLang Hames            {FAs.WriteUInt32s, rt::MemoryWriteUInt32sWrapperName},
235*8201ae2aSLang Hames            {FAs.WriteUInt64s, rt::MemoryWriteUInt64sWrapperName},
236*8201ae2aSLang Hames            {FAs.WriteBuffers, rt::MemoryWriteBuffersWrapperName},
237*8201ae2aSLang Hames            {FAs.WritePointers, rt::MemoryWritePointersWrapperName}}))
238*8201ae2aSLang Hames     return std::move(Err);
239*8201ae2aSLang Hames 
240*8201ae2aSLang Hames   return std::make_unique<EPCGenericMemoryAccess>(SREPC, FAs);
241bb72f073SLang Hames }
242bb72f073SLang Hames 
243175c1a39SLang Hames Error SimpleRemoteEPC::sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
244175c1a39SLang Hames                                    ExecutorAddr TagAddr,
245175c1a39SLang Hames                                    ArrayRef<char> ArgBytes) {
246175c1a39SLang Hames   assert(OpC != SimpleRemoteEPCOpcode::Setup &&
247175c1a39SLang Hames          "SimpleRemoteEPC sending Setup message? That's the wrong direction.");
248175c1a39SLang Hames 
249175c1a39SLang Hames   LLVM_DEBUG({
250175c1a39SLang Hames     dbgs() << "SimpleRemoteEPC::sendMessage: opc = ";
251175c1a39SLang Hames     switch (OpC) {
252175c1a39SLang Hames     case SimpleRemoteEPCOpcode::Hangup:
253175c1a39SLang Hames       dbgs() << "Hangup";
254175c1a39SLang Hames       assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
255577f316cSLang Hames       assert(!TagAddr && "Non-zero TagAddr for Hangup?");
256175c1a39SLang Hames       break;
257175c1a39SLang Hames     case SimpleRemoteEPCOpcode::Result:
258175c1a39SLang Hames       dbgs() << "Result";
259577f316cSLang Hames       assert(!TagAddr && "Non-zero TagAddr for Result?");
260175c1a39SLang Hames       break;
261175c1a39SLang Hames     case SimpleRemoteEPCOpcode::CallWrapper:
262175c1a39SLang Hames       dbgs() << "CallWrapper";
263175c1a39SLang Hames       break;
264175c1a39SLang Hames     default:
265175c1a39SLang Hames       llvm_unreachable("Invalid opcode");
266175c1a39SLang Hames     }
267577f316cSLang Hames     dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
268175c1a39SLang Hames            << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
269175c1a39SLang Hames            << " bytes\n";
270175c1a39SLang Hames   });
271175c1a39SLang Hames   auto Err = T->sendMessage(OpC, SeqNo, TagAddr, ArgBytes);
272175c1a39SLang Hames   LLVM_DEBUG({
273175c1a39SLang Hames     if (Err)
274175c1a39SLang Hames       dbgs() << "  \\--> SimpleRemoteEPC::sendMessage failed\n";
275175c1a39SLang Hames   });
276175c1a39SLang Hames   return Err;
277175c1a39SLang Hames }
278175c1a39SLang Hames 
279ef391df2SLang Hames Error SimpleRemoteEPC::handleSetup(uint64_t SeqNo, ExecutorAddr TagAddr,
280bb72f073SLang Hames                                    SimpleRemoteEPCArgBytesVector ArgBytes) {
281bb72f073SLang Hames   if (SeqNo != 0)
282bb72f073SLang Hames     return make_error<StringError>("Setup packet SeqNo not zero",
283bb72f073SLang Hames                                    inconvertibleErrorCode());
284bb72f073SLang Hames 
285bb72f073SLang Hames   if (TagAddr)
286bb72f073SLang Hames     return make_error<StringError>("Setup packet TagAddr not zero",
287bb72f073SLang Hames                                    inconvertibleErrorCode());
288bb72f073SLang Hames 
289bb72f073SLang Hames   std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
290bb72f073SLang Hames   auto I = PendingCallWrapperResults.find(0);
291bb72f073SLang Hames   assert(PendingCallWrapperResults.size() == 1 &&
292bb72f073SLang Hames          I != PendingCallWrapperResults.end() &&
293bb72f073SLang Hames          "Setup message handler not connectly set up");
294bb72f073SLang Hames   auto SetupMsgHandler = std::move(I->second);
295bb72f073SLang Hames   PendingCallWrapperResults.erase(I);
296bb72f073SLang Hames 
297bb72f073SLang Hames   auto WFR =
298bb72f073SLang Hames       shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
299bb72f073SLang Hames   SetupMsgHandler(std::move(WFR));
300bb72f073SLang Hames   return Error::success();
301bb72f073SLang Hames }
302bb72f073SLang Hames 
3034fcc0ac1SLang Hames Error SimpleRemoteEPC::setup(Setup S) {
3044b37462aSLang Hames   using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
3054b37462aSLang Hames 
3064b37462aSLang Hames   std::promise<MSVCPExpected<SimpleRemoteEPCExecutorInfo>> EIP;
3074b37462aSLang Hames   auto EIF = EIP.get_future();
3084b37462aSLang Hames 
3094b37462aSLang Hames   // Prepare a handler for the setup packet.
310bb72f073SLang Hames   PendingCallWrapperResults[0] =
3114d7cea3dSLang Hames     RunInPlace()(
312bb72f073SLang Hames       [&](shared::WrapperFunctionResult SetupMsgBytes) {
313bb72f073SLang Hames         if (const char *ErrMsg = SetupMsgBytes.getOutOfBandError()) {
3144b37462aSLang Hames           EIP.set_value(
315bb72f073SLang Hames               make_error<StringError>(ErrMsg, inconvertibleErrorCode()));
316bb72f073SLang Hames           return;
317bb72f073SLang Hames         }
318bb72f073SLang Hames         using SPSSerialize =
319bb72f073SLang Hames             shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;
320bb72f073SLang Hames         shared::SPSInputBuffer IB(SetupMsgBytes.data(), SetupMsgBytes.size());
321bb72f073SLang Hames         SimpleRemoteEPCExecutorInfo EI;
322bb72f073SLang Hames         if (SPSSerialize::deserialize(IB, EI))
3234b37462aSLang Hames           EIP.set_value(EI);
324bb72f073SLang Hames         else
3254b37462aSLang Hames           EIP.set_value(make_error<StringError>(
326bb72f073SLang Hames               "Could not deserialize setup message", inconvertibleErrorCode()));
3274d7cea3dSLang Hames       });
3284b37462aSLang Hames 
3294b37462aSLang Hames   // Start the transport.
3304b37462aSLang Hames   if (auto Err = T->start())
3314b37462aSLang Hames     return Err;
3324b37462aSLang Hames 
3334b37462aSLang Hames   // Wait for setup packet to arrive.
3344b37462aSLang Hames   auto EI = EIF.get();
3354b37462aSLang Hames   if (!EI) {
3364b37462aSLang Hames     T->disconnect();
3374b37462aSLang Hames     return EI.takeError();
338bb72f073SLang Hames   }
339bb72f073SLang Hames 
340b64fc0afSLang Hames   LLVM_DEBUG({
341b64fc0afSLang Hames     dbgs() << "SimpleRemoteEPC received setup message:\n"
3424b37462aSLang Hames            << "  Triple: " << EI->TargetTriple << "\n"
3434b37462aSLang Hames            << "  Page size: " << EI->PageSize << "\n"
344060319a2SLang Hames            << "  Bootstrap map" << (EI->BootstrapMap.empty() ? " empty" : ":")
345060319a2SLang Hames            << "\n";
346060319a2SLang Hames     for (const auto &KV : EI->BootstrapMap)
347060319a2SLang Hames       dbgs() << "    " << KV.first() << ": " << KV.second.size()
348060319a2SLang Hames              << "-byte SPS encoded buffer\n";
349060319a2SLang Hames     dbgs() << "  Bootstrap symbols"
350060319a2SLang Hames            << (EI->BootstrapSymbols.empty() ? " empty" : ":") << "\n";
3514b37462aSLang Hames     for (const auto &KV : EI->BootstrapSymbols)
352577f316cSLang Hames       dbgs() << "    " << KV.first() << ": " << KV.second << "\n";
353b64fc0afSLang Hames   });
3544b37462aSLang Hames   TargetTriple = Triple(EI->TargetTriple);
3554b37462aSLang Hames   PageSize = EI->PageSize;
356060319a2SLang Hames   BootstrapMap = std::move(EI->BootstrapMap);
3574b37462aSLang Hames   BootstrapSymbols = std::move(EI->BootstrapSymbols);
358b64fc0afSLang Hames 
359b64fc0afSLang Hames   if (auto Err = getBootstrapSymbols(
360ef391df2SLang Hames           {{JDI.JITDispatchContext, ExecutorSessionObjectName},
361ef391df2SLang Hames            {JDI.JITDispatchFunction, DispatchFnName},
3627260cdd2SSunho Kim            {RunAsMainAddr, rt::RunAsMainWrapperName},
3637260cdd2SSunho Kim            {RunAsVoidFunctionAddr, rt::RunAsVoidFunctionWrapperName},
3647260cdd2SSunho Kim            {RunAsIntFunctionAddr, rt::RunAsIntFunctionWrapperName}}))
365b64fc0afSLang Hames     return Err;
366b64fc0afSLang Hames 
367a2c1cf09SLang Hames   if (auto DM =
368a2c1cf09SLang Hames           EPCGenericDylibManager::CreateWithDefaultBootstrapSymbols(*this))
369db21bd4fSLang Hames     EPCDylibMgr = std::make_unique<EPCGenericDylibManager>(std::move(*DM));
370a2c1cf09SLang Hames   else
371a2c1cf09SLang Hames     return DM.takeError();
372a2c1cf09SLang Hames 
3734fcc0ac1SLang Hames   // Set a default CreateMemoryManager if none is specified.
3744fcc0ac1SLang Hames   if (!S.CreateMemoryManager)
3754fcc0ac1SLang Hames     S.CreateMemoryManager = createDefaultMemoryManager;
3764fcc0ac1SLang Hames 
3774fcc0ac1SLang Hames   if (auto MemMgr = S.CreateMemoryManager(*this)) {
378b64fc0afSLang Hames     OwnedMemMgr = std::move(*MemMgr);
379b64fc0afSLang Hames     this->MemMgr = OwnedMemMgr.get();
380b64fc0afSLang Hames   } else
381b64fc0afSLang Hames     return MemMgr.takeError();
382b64fc0afSLang Hames 
3834fcc0ac1SLang Hames   // Set a default CreateMemoryAccess if none is specified.
3844fcc0ac1SLang Hames   if (!S.CreateMemoryAccess)
3854fcc0ac1SLang Hames     S.CreateMemoryAccess = createDefaultMemoryAccess;
3864fcc0ac1SLang Hames 
3874fcc0ac1SLang Hames   if (auto MemAccess = S.CreateMemoryAccess(*this)) {
388b64fc0afSLang Hames     OwnedMemAccess = std::move(*MemAccess);
389b64fc0afSLang Hames     this->MemAccess = OwnedMemAccess.get();
390b64fc0afSLang Hames   } else
391b64fc0afSLang Hames     return MemAccess.takeError();
392b64fc0afSLang Hames 
393b64fc0afSLang Hames   return Error::success();
394b64fc0afSLang Hames }
395b64fc0afSLang Hames 
396ef391df2SLang Hames Error SimpleRemoteEPC::handleResult(uint64_t SeqNo, ExecutorAddr TagAddr,
397bb72f073SLang Hames                                     SimpleRemoteEPCArgBytesVector ArgBytes) {
3984d7cea3dSLang Hames   IncomingWFRHandler SendResult;
399bb72f073SLang Hames 
400bb72f073SLang Hames   if (TagAddr)
401bb72f073SLang Hames     return make_error<StringError>("Unexpected TagAddr in result message",
402bb72f073SLang Hames                                    inconvertibleErrorCode());
403bb72f073SLang Hames 
404bb72f073SLang Hames   {
405bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
406bb72f073SLang Hames     auto I = PendingCallWrapperResults.find(SeqNo);
407bb72f073SLang Hames     if (I == PendingCallWrapperResults.end())
408bb72f073SLang Hames       return make_error<StringError>("No call for sequence number " +
409bb72f073SLang Hames                                          Twine(SeqNo),
410bb72f073SLang Hames                                      inconvertibleErrorCode());
411bb72f073SLang Hames     SendResult = std::move(I->second);
412bb72f073SLang Hames     PendingCallWrapperResults.erase(I);
413bb72f073SLang Hames     releaseSeqNo(SeqNo);
414bb72f073SLang Hames   }
415bb72f073SLang Hames 
416bb72f073SLang Hames   auto WFR =
417bb72f073SLang Hames       shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
418bb72f073SLang Hames   SendResult(std::move(WFR));
419bb72f073SLang Hames   return Error::success();
420bb72f073SLang Hames }
421bb72f073SLang Hames 
422bb72f073SLang Hames void SimpleRemoteEPC::handleCallWrapper(
423ef391df2SLang Hames     uint64_t RemoteSeqNo, ExecutorAddr TagAddr,
424bb72f073SLang Hames     SimpleRemoteEPCArgBytesVector ArgBytes) {
425bb72f073SLang Hames   assert(ES && "No ExecutionSession attached");
426e9014d97SLang Hames   D->dispatch(makeGenericNamedTask(
427e9014d97SLang Hames       [this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() {
428bb72f073SLang Hames         ES->runJITDispatchHandler(
429bb72f073SLang Hames             [this, RemoteSeqNo](shared::WrapperFunctionResult WFR) {
430e9014d97SLang Hames               if (auto Err =
431e9014d97SLang Hames                       sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo,
432ef391df2SLang Hames                                   ExecutorAddr(), {WFR.data(), WFR.size()}))
433bb72f073SLang Hames                 getExecutionSession().reportError(std::move(Err));
434bb72f073SLang Hames             },
4358b1771bdSLang Hames             TagAddr, ArgBytes);
436e9014d97SLang Hames       },
437e9014d97SLang Hames       "callWrapper task"));
438bb72f073SLang Hames }
439bb72f073SLang Hames 
440a6c95063SStefan Gränitz Error SimpleRemoteEPC::handleHangup(SimpleRemoteEPCArgBytesVector ArgBytes) {
441a6c95063SStefan Gränitz   using namespace llvm::orc::shared;
442a6c95063SStefan Gränitz   auto WFR = WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
443a6c95063SStefan Gränitz   if (const char *ErrMsg = WFR.getOutOfBandError())
444a6c95063SStefan Gränitz     return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
445a6c95063SStefan Gränitz 
446a6c95063SStefan Gränitz   detail::SPSSerializableError Info;
447a6c95063SStefan Gränitz   SPSInputBuffer IB(WFR.data(), WFR.size());
448a6c95063SStefan Gränitz   if (!SPSArgList<SPSError>::deserialize(IB, Info))
449a6c95063SStefan Gränitz     return make_error<StringError>("Could not deserialize hangup info",
450a6c95063SStefan Gränitz                                    inconvertibleErrorCode());
451a6c95063SStefan Gränitz   return fromSPSSerializable(std::move(Info));
452a6c95063SStefan Gränitz }
453a6c95063SStefan Gränitz 
454bb72f073SLang Hames } // end namespace orc
455bb72f073SLang Hames } // end namespace llvm
456