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