1*bb72f073SLang Hames //===------- SimpleRemoteEPC.cpp -- Simple remote executor control --------===//
2*bb72f073SLang Hames //
3*bb72f073SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*bb72f073SLang Hames // See https://llvm.org/LICENSE.txt for license information.
5*bb72f073SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*bb72f073SLang Hames //
7*bb72f073SLang Hames //===----------------------------------------------------------------------===//
8*bb72f073SLang Hames 
9*bb72f073SLang Hames #include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"
10*bb72f073SLang Hames #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
11*bb72f073SLang Hames #include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h"
12*bb72f073SLang Hames #include "llvm/Support/FormatVariadic.h"
13*bb72f073SLang Hames 
14*bb72f073SLang Hames #define DEBUG_TYPE "orc"
15*bb72f073SLang Hames 
16*bb72f073SLang Hames namespace llvm {
17*bb72f073SLang Hames namespace orc {
18*bb72f073SLang Hames namespace shared {
19*bb72f073SLang Hames 
20*bb72f073SLang Hames template <>
21*bb72f073SLang Hames class SPSSerializationTraits<SPSRemoteSymbolLookupSetElement,
22*bb72f073SLang Hames                              SymbolLookupSet::value_type> {
23*bb72f073SLang Hames public:
24*bb72f073SLang Hames   static size_t size(const SymbolLookupSet::value_type &V) {
25*bb72f073SLang Hames     return SPSArgList<SPSString, bool>::size(
26*bb72f073SLang Hames         *V.first, V.second == SymbolLookupFlags::RequiredSymbol);
27*bb72f073SLang Hames   }
28*bb72f073SLang Hames 
29*bb72f073SLang Hames   static bool serialize(SPSOutputBuffer &OB,
30*bb72f073SLang Hames                         const SymbolLookupSet::value_type &V) {
31*bb72f073SLang Hames     return SPSArgList<SPSString, bool>::serialize(
32*bb72f073SLang Hames         OB, *V.first, V.second == SymbolLookupFlags::RequiredSymbol);
33*bb72f073SLang Hames   }
34*bb72f073SLang Hames };
35*bb72f073SLang Hames 
36*bb72f073SLang Hames template <>
37*bb72f073SLang Hames class TrivialSPSSequenceSerialization<SPSRemoteSymbolLookupSetElement,
38*bb72f073SLang Hames                                       SymbolLookupSet> {
39*bb72f073SLang Hames public:
40*bb72f073SLang Hames   static constexpr bool available = true;
41*bb72f073SLang Hames };
42*bb72f073SLang Hames 
43*bb72f073SLang Hames template <>
44*bb72f073SLang Hames class SPSSerializationTraits<SPSRemoteSymbolLookup,
45*bb72f073SLang Hames                              ExecutorProcessControl::LookupRequest> {
46*bb72f073SLang Hames   using MemberSerialization =
47*bb72f073SLang Hames       SPSArgList<SPSExecutorAddress, SPSRemoteSymbolLookupSet>;
48*bb72f073SLang Hames 
49*bb72f073SLang Hames public:
50*bb72f073SLang Hames   static size_t size(const ExecutorProcessControl::LookupRequest &LR) {
51*bb72f073SLang Hames     return MemberSerialization::size(ExecutorAddress(LR.Handle), LR.Symbols);
52*bb72f073SLang Hames   }
53*bb72f073SLang Hames 
54*bb72f073SLang Hames   static bool serialize(SPSOutputBuffer &OB,
55*bb72f073SLang Hames                         const ExecutorProcessControl::LookupRequest &LR) {
56*bb72f073SLang Hames     return MemberSerialization::serialize(OB, ExecutorAddress(LR.Handle),
57*bb72f073SLang Hames                                           LR.Symbols);
58*bb72f073SLang Hames   }
59*bb72f073SLang Hames };
60*bb72f073SLang Hames 
61*bb72f073SLang Hames } // end namespace shared
62*bb72f073SLang Hames 
63*bb72f073SLang Hames SimpleRemoteEPC::~SimpleRemoteEPC() {
64*bb72f073SLang Hames   assert(Disconnected && "Destroyed without disconnection");
65*bb72f073SLang Hames }
66*bb72f073SLang Hames 
67*bb72f073SLang Hames Error SimpleRemoteEPC::setup(std::unique_ptr<SimpleRemoteEPCTransport> T,
68*bb72f073SLang Hames                              const SimpleRemoteEPCExecutorInfo &EI) {
69*bb72f073SLang Hames   using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
70*bb72f073SLang Hames   LLVM_DEBUG({
71*bb72f073SLang Hames     dbgs() << "SimpleRemoteEPC received setup message:\n"
72*bb72f073SLang Hames            << "  Triple: " << EI.TargetTriple << "\n"
73*bb72f073SLang Hames            << "  Page size: " << EI.PageSize << "\n"
74*bb72f073SLang Hames            << "  Bootstrap symbols:\n";
75*bb72f073SLang Hames     for (const auto &KV : EI.BootstrapSymbols)
76*bb72f073SLang Hames       dbgs() << "    " << KV.first() << ": "
77*bb72f073SLang Hames              << formatv("{0:x16}", KV.second.getValue()) << "\n";
78*bb72f073SLang Hames   });
79*bb72f073SLang Hames   this->T = std::move(T);
80*bb72f073SLang Hames   TargetTriple = Triple(EI.TargetTriple);
81*bb72f073SLang Hames   PageSize = EI.PageSize;
82*bb72f073SLang Hames 
83*bb72f073SLang Hames   if (auto Err = EI.getBootstrapSymbols(
84*bb72f073SLang Hames           {{JDI.JITDispatchContextAddress, ExecutorSessionObjectName},
85*bb72f073SLang Hames            {JDI.JITDispatchFunctionAddress, DispatchFnName},
86*bb72f073SLang Hames            {LoadDylibAddr, "__llvm_orc_load_dylib"},
87*bb72f073SLang Hames            {LookupSymbolsAddr, "__llvm_orc_lookup_symbols"},
88*bb72f073SLang Hames            {RunAsMainAddr, "__llvm_orc_run_as_main"}}))
89*bb72f073SLang Hames     return Err;
90*bb72f073SLang Hames 
91*bb72f073SLang Hames   if (!MemMgr)
92*bb72f073SLang Hames     if (auto Err = setupDefaultMemoryManager(EI))
93*bb72f073SLang Hames       return Err;
94*bb72f073SLang Hames   if (!MemAccess)
95*bb72f073SLang Hames     if (auto Err = setupDefaultMemoryAccess(EI))
96*bb72f073SLang Hames       return Err;
97*bb72f073SLang Hames 
98*bb72f073SLang Hames   return Error::success();
99*bb72f073SLang Hames }
100*bb72f073SLang Hames 
101*bb72f073SLang Hames Expected<tpctypes::DylibHandle>
102*bb72f073SLang Hames SimpleRemoteEPC::loadDylib(const char *DylibPath) {
103*bb72f073SLang Hames   Expected<tpctypes::DylibHandle> H((tpctypes::DylibHandle()));
104*bb72f073SLang Hames   if (auto Err = callSPSWrapper<shared::SPSLoadDylibSignature>(
105*bb72f073SLang Hames           LoadDylibAddr.getValue(), H, JDI.JITDispatchContextAddress,
106*bb72f073SLang Hames           StringRef(DylibPath), (uint64_t)0))
107*bb72f073SLang Hames     return std::move(Err);
108*bb72f073SLang Hames   return H;
109*bb72f073SLang Hames }
110*bb72f073SLang Hames 
111*bb72f073SLang Hames Expected<std::vector<tpctypes::LookupResult>>
112*bb72f073SLang Hames SimpleRemoteEPC::lookupSymbols(ArrayRef<LookupRequest> Request) {
113*bb72f073SLang Hames   Expected<std::vector<tpctypes::LookupResult>> R(
114*bb72f073SLang Hames       (std::vector<tpctypes::LookupResult>()));
115*bb72f073SLang Hames 
116*bb72f073SLang Hames   if (auto Err = callSPSWrapper<shared::SPSLookupSymbolsSignature>(
117*bb72f073SLang Hames           LookupSymbolsAddr.getValue(), R, JDI.JITDispatchContextAddress,
118*bb72f073SLang Hames           Request))
119*bb72f073SLang Hames     return std::move(Err);
120*bb72f073SLang Hames   return R;
121*bb72f073SLang Hames }
122*bb72f073SLang Hames 
123*bb72f073SLang Hames Expected<int32_t> SimpleRemoteEPC::runAsMain(JITTargetAddress MainFnAddr,
124*bb72f073SLang Hames                                              ArrayRef<std::string> Args) {
125*bb72f073SLang Hames   int64_t Result = 0;
126*bb72f073SLang Hames   if (auto Err = callSPSWrapper<shared::SPSRunAsMainSignature>(
127*bb72f073SLang Hames           RunAsMainAddr.getValue(), Result, ExecutorAddress(MainFnAddr), Args))
128*bb72f073SLang Hames     return std::move(Err);
129*bb72f073SLang Hames   return Result;
130*bb72f073SLang Hames }
131*bb72f073SLang Hames 
132*bb72f073SLang Hames void SimpleRemoteEPC::callWrapperAsync(SendResultFunction OnComplete,
133*bb72f073SLang Hames                                        JITTargetAddress WrapperFnAddr,
134*bb72f073SLang Hames                                        ArrayRef<char> ArgBuffer) {
135*bb72f073SLang Hames   uint64_t SeqNo;
136*bb72f073SLang Hames   {
137*bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
138*bb72f073SLang Hames     SeqNo = getNextSeqNo();
139*bb72f073SLang Hames     assert(!PendingCallWrapperResults.count(SeqNo) && "SeqNo already in use");
140*bb72f073SLang Hames     PendingCallWrapperResults[SeqNo] = std::move(OnComplete);
141*bb72f073SLang Hames   }
142*bb72f073SLang Hames 
143*bb72f073SLang Hames   if (auto Err = T->sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo,
144*bb72f073SLang Hames                                 ExecutorAddress(WrapperFnAddr), ArgBuffer)) {
145*bb72f073SLang Hames     getExecutionSession().reportError(std::move(Err));
146*bb72f073SLang Hames   }
147*bb72f073SLang Hames }
148*bb72f073SLang Hames 
149*bb72f073SLang Hames Error SimpleRemoteEPC::disconnect() {
150*bb72f073SLang Hames   Disconnected = true;
151*bb72f073SLang Hames   T->disconnect();
152*bb72f073SLang Hames   return Error::success();
153*bb72f073SLang Hames }
154*bb72f073SLang Hames 
155*bb72f073SLang Hames Expected<SimpleRemoteEPCTransportClient::HandleMessageAction>
156*bb72f073SLang Hames SimpleRemoteEPC::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
157*bb72f073SLang Hames                                ExecutorAddress TagAddr,
158*bb72f073SLang Hames                                SimpleRemoteEPCArgBytesVector ArgBytes) {
159*bb72f073SLang Hames   using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;
160*bb72f073SLang Hames   if (static_cast<UT>(OpC) < static_cast<UT>(SimpleRemoteEPCOpcode::FirstOpC) ||
161*bb72f073SLang Hames       static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC))
162*bb72f073SLang Hames     return make_error<StringError>("Unexpected opcode",
163*bb72f073SLang Hames                                    inconvertibleErrorCode());
164*bb72f073SLang Hames 
165*bb72f073SLang Hames   switch (OpC) {
166*bb72f073SLang Hames   case SimpleRemoteEPCOpcode::Setup:
167*bb72f073SLang Hames     if (auto Err = handleSetup(SeqNo, TagAddr, std::move(ArgBytes)))
168*bb72f073SLang Hames       return std::move(Err);
169*bb72f073SLang Hames     break;
170*bb72f073SLang Hames   case SimpleRemoteEPCOpcode::Hangup:
171*bb72f073SLang Hames     // FIXME: Put EPC into 'detached' state.
172*bb72f073SLang Hames     return SimpleRemoteEPCTransportClient::EndSession;
173*bb72f073SLang Hames   case SimpleRemoteEPCOpcode::Result:
174*bb72f073SLang Hames     if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))
175*bb72f073SLang Hames       return std::move(Err);
176*bb72f073SLang Hames     break;
177*bb72f073SLang Hames   case SimpleRemoteEPCOpcode::CallWrapper:
178*bb72f073SLang Hames     handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));
179*bb72f073SLang Hames     break;
180*bb72f073SLang Hames   }
181*bb72f073SLang Hames   return ContinueSession;
182*bb72f073SLang Hames }
183*bb72f073SLang Hames 
184*bb72f073SLang Hames void SimpleRemoteEPC::handleDisconnect(Error Err) {
185*bb72f073SLang Hames   PendingCallWrapperResultsMap TmpPending;
186*bb72f073SLang Hames 
187*bb72f073SLang Hames   {
188*bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
189*bb72f073SLang Hames     std::swap(TmpPending, PendingCallWrapperResults);
190*bb72f073SLang Hames   }
191*bb72f073SLang Hames 
192*bb72f073SLang Hames   for (auto &KV : TmpPending)
193*bb72f073SLang Hames     KV.second(
194*bb72f073SLang Hames         shared::WrapperFunctionResult::createOutOfBandError("disconnecting"));
195*bb72f073SLang Hames 
196*bb72f073SLang Hames   if (Err) {
197*bb72f073SLang Hames     // FIXME: Move ReportError to EPC.
198*bb72f073SLang Hames     if (ES)
199*bb72f073SLang Hames       ES->reportError(std::move(Err));
200*bb72f073SLang Hames     else
201*bb72f073SLang Hames       logAllUnhandledErrors(std::move(Err), errs(), "SimpleRemoteEPC: ");
202*bb72f073SLang Hames   }
203*bb72f073SLang Hames }
204*bb72f073SLang Hames 
205*bb72f073SLang Hames void SimpleRemoteEPC::setMemoryManager(
206*bb72f073SLang Hames     std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
207*bb72f073SLang Hames   OwnedMemMgr = std::move(MemMgr);
208*bb72f073SLang Hames   this->MemMgr = OwnedMemMgr.get();
209*bb72f073SLang Hames }
210*bb72f073SLang Hames 
211*bb72f073SLang Hames void SimpleRemoteEPC::setMemoryAccess(std::unique_ptr<MemoryAccess> MemAccess) {
212*bb72f073SLang Hames   OwnedMemAccess = std::move(MemAccess);
213*bb72f073SLang Hames   this->MemAccess = OwnedMemAccess.get();
214*bb72f073SLang Hames }
215*bb72f073SLang Hames 
216*bb72f073SLang Hames Error SimpleRemoteEPC::setupDefaultMemoryManager(
217*bb72f073SLang Hames     const SimpleRemoteEPCExecutorInfo &EI) {
218*bb72f073SLang Hames 
219*bb72f073SLang Hames   EPCGenericJITLinkMemoryManager::FuncAddrs FAs;
220*bb72f073SLang Hames 
221*bb72f073SLang Hames   if (auto Err = EI.getBootstrapSymbols(
222*bb72f073SLang Hames           {{FAs.Reserve, "__llvm_orc_memory_reserve"},
223*bb72f073SLang Hames            {FAs.Finalize, "__llvm_orc_memory_finalize"},
224*bb72f073SLang Hames            {FAs.Deallocate, "__llvm_orc_memory_deallocate"}}))
225*bb72f073SLang Hames     return Err;
226*bb72f073SLang Hames 
227*bb72f073SLang Hames   setMemoryManager(
228*bb72f073SLang Hames       std::make_unique<EPCGenericJITLinkMemoryManager>(*this, FAs));
229*bb72f073SLang Hames   return Error::success();
230*bb72f073SLang Hames }
231*bb72f073SLang Hames 
232*bb72f073SLang Hames Error SimpleRemoteEPC::setupDefaultMemoryAccess(
233*bb72f073SLang Hames     const SimpleRemoteEPCExecutorInfo &EI) {
234*bb72f073SLang Hames 
235*bb72f073SLang Hames   return Error::success();
236*bb72f073SLang Hames }
237*bb72f073SLang Hames 
238*bb72f073SLang Hames Error SimpleRemoteEPC::handleSetup(uint64_t SeqNo, ExecutorAddress TagAddr,
239*bb72f073SLang Hames                                    SimpleRemoteEPCArgBytesVector ArgBytes) {
240*bb72f073SLang Hames   if (SeqNo != 0)
241*bb72f073SLang Hames     return make_error<StringError>("Setup packet SeqNo not zero",
242*bb72f073SLang Hames                                    inconvertibleErrorCode());
243*bb72f073SLang Hames 
244*bb72f073SLang Hames   if (TagAddr)
245*bb72f073SLang Hames     return make_error<StringError>("Setup packet TagAddr not zero",
246*bb72f073SLang Hames                                    inconvertibleErrorCode());
247*bb72f073SLang Hames 
248*bb72f073SLang Hames   std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
249*bb72f073SLang Hames   auto I = PendingCallWrapperResults.find(0);
250*bb72f073SLang Hames   assert(PendingCallWrapperResults.size() == 1 &&
251*bb72f073SLang Hames          I != PendingCallWrapperResults.end() &&
252*bb72f073SLang Hames          "Setup message handler not connectly set up");
253*bb72f073SLang Hames   auto SetupMsgHandler = std::move(I->second);
254*bb72f073SLang Hames   PendingCallWrapperResults.erase(I);
255*bb72f073SLang Hames 
256*bb72f073SLang Hames   auto WFR =
257*bb72f073SLang Hames       shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
258*bb72f073SLang Hames   SetupMsgHandler(std::move(WFR));
259*bb72f073SLang Hames   return Error::success();
260*bb72f073SLang Hames }
261*bb72f073SLang Hames 
262*bb72f073SLang Hames void SimpleRemoteEPC::prepareToReceiveSetupMessage(
263*bb72f073SLang Hames     std::promise<MSVCPExpected<SimpleRemoteEPCExecutorInfo>> &ExecInfoP) {
264*bb72f073SLang Hames   PendingCallWrapperResults[0] =
265*bb72f073SLang Hames       [&](shared::WrapperFunctionResult SetupMsgBytes) {
266*bb72f073SLang Hames         if (const char *ErrMsg = SetupMsgBytes.getOutOfBandError()) {
267*bb72f073SLang Hames           ExecInfoP.set_value(
268*bb72f073SLang Hames               make_error<StringError>(ErrMsg, inconvertibleErrorCode()));
269*bb72f073SLang Hames           return;
270*bb72f073SLang Hames         }
271*bb72f073SLang Hames         using SPSSerialize =
272*bb72f073SLang Hames             shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;
273*bb72f073SLang Hames         shared::SPSInputBuffer IB(SetupMsgBytes.data(), SetupMsgBytes.size());
274*bb72f073SLang Hames         SimpleRemoteEPCExecutorInfo EI;
275*bb72f073SLang Hames         if (SPSSerialize::deserialize(IB, EI))
276*bb72f073SLang Hames           ExecInfoP.set_value(EI);
277*bb72f073SLang Hames         else
278*bb72f073SLang Hames           ExecInfoP.set_value(make_error<StringError>(
279*bb72f073SLang Hames               "Could not deserialize setup message", inconvertibleErrorCode()));
280*bb72f073SLang Hames       };
281*bb72f073SLang Hames }
282*bb72f073SLang Hames 
283*bb72f073SLang Hames Error SimpleRemoteEPC::handleResult(uint64_t SeqNo, ExecutorAddress TagAddr,
284*bb72f073SLang Hames                                     SimpleRemoteEPCArgBytesVector ArgBytes) {
285*bb72f073SLang Hames   SendResultFunction SendResult;
286*bb72f073SLang Hames 
287*bb72f073SLang Hames   if (TagAddr)
288*bb72f073SLang Hames     return make_error<StringError>("Unexpected TagAddr in result message",
289*bb72f073SLang Hames                                    inconvertibleErrorCode());
290*bb72f073SLang Hames 
291*bb72f073SLang Hames   {
292*bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
293*bb72f073SLang Hames     auto I = PendingCallWrapperResults.find(SeqNo);
294*bb72f073SLang Hames     if (I == PendingCallWrapperResults.end())
295*bb72f073SLang Hames       return make_error<StringError>("No call for sequence number " +
296*bb72f073SLang Hames                                          Twine(SeqNo),
297*bb72f073SLang Hames                                      inconvertibleErrorCode());
298*bb72f073SLang Hames     SendResult = std::move(I->second);
299*bb72f073SLang Hames     PendingCallWrapperResults.erase(I);
300*bb72f073SLang Hames     releaseSeqNo(SeqNo);
301*bb72f073SLang Hames   }
302*bb72f073SLang Hames 
303*bb72f073SLang Hames   auto WFR =
304*bb72f073SLang Hames       shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
305*bb72f073SLang Hames   SendResult(std::move(WFR));
306*bb72f073SLang Hames   return Error::success();
307*bb72f073SLang Hames }
308*bb72f073SLang Hames 
309*bb72f073SLang Hames void SimpleRemoteEPC::handleCallWrapper(
310*bb72f073SLang Hames     uint64_t RemoteSeqNo, ExecutorAddress TagAddr,
311*bb72f073SLang Hames     SimpleRemoteEPCArgBytesVector ArgBytes) {
312*bb72f073SLang Hames   assert(ES && "No ExecutionSession attached");
313*bb72f073SLang Hames   ES->runJITDispatchHandler(
314*bb72f073SLang Hames       [this, RemoteSeqNo](shared::WrapperFunctionResult WFR) {
315*bb72f073SLang Hames         if (auto Err =
316*bb72f073SLang Hames                 T->sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo,
317*bb72f073SLang Hames                                ExecutorAddress(), {WFR.data(), WFR.size()}))
318*bb72f073SLang Hames           getExecutionSession().reportError(std::move(Err));
319*bb72f073SLang Hames       },
320*bb72f073SLang Hames       TagAddr.getValue(), ArgBytes);
321*bb72f073SLang Hames }
322*bb72f073SLang Hames 
323*bb72f073SLang Hames } // end namespace orc
324*bb72f073SLang Hames } // end namespace llvm
325