1 //===---- SimpleRemoteEPC.h - Simple remote executor control ----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Simple remote executor process control.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_EXECUTIONENGINE_ORC_SIMPLEREMOTEEPC_H
14 #define LLVM_EXECUTIONENGINE_ORC_SIMPLEREMOTEEPC_H
15 
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/FunctionExtras.h"
18 #include "llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h"
19 #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
20 #include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h"
21 #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
22 #include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
23 #include "llvm/Support/Error.h"
24 #include "llvm/Support/MSVCErrorWorkarounds.h"
25 
26 #include <future>
27 
28 namespace llvm {
29 namespace orc {
30 
31 class SimpleRemoteEPC : public ExecutorProcessControl,
32                         public SimpleRemoteEPCTransportClient {
33 public:
34   /// Create a SimpleRemoteEPC using the given transport type and args.
35   template <typename TransportT, typename... TransportTCtorArgTs>
36   static Expected<std::unique_ptr<SimpleRemoteEPC>>
Create(std::unique_ptr<TaskDispatcher> D,TransportTCtorArgTs &&...TransportTCtorArgs)37   Create(std::unique_ptr<TaskDispatcher> D,
38          TransportTCtorArgTs &&...TransportTCtorArgs) {
39     std::unique_ptr<SimpleRemoteEPC> SREPC(
40         new SimpleRemoteEPC(std::make_shared<SymbolStringPool>(),
41                             std::move(D)));
42     auto T = TransportT::Create(
43         *SREPC, std::forward<TransportTCtorArgTs>(TransportTCtorArgs)...);
44     if (!T)
45       return T.takeError();
46     SREPC->T = std::move(*T);
47     if (auto Err = SREPC->setup())
48       return joinErrors(std::move(Err), SREPC->disconnect());
49     return std::move(SREPC);
50   }
51 
52   SimpleRemoteEPC(const SimpleRemoteEPC &) = delete;
53   SimpleRemoteEPC &operator=(const SimpleRemoteEPC &) = delete;
54   SimpleRemoteEPC(SimpleRemoteEPC &&) = delete;
55   SimpleRemoteEPC &operator=(SimpleRemoteEPC &&) = delete;
56   ~SimpleRemoteEPC();
57 
58   Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override;
59 
60   Expected<std::vector<tpctypes::LookupResult>>
61   lookupSymbols(ArrayRef<LookupRequest> Request) override;
62 
63   Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
64                               ArrayRef<std::string> Args) override;
65 
66   void callWrapperAsync(ExecutorAddr WrapperFnAddr,
67                         IncomingWFRHandler OnComplete,
68                         ArrayRef<char> ArgBuffer) override;
69 
70   Error disconnect() override;
71 
72   Expected<HandleMessageAction>
73   handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr,
74                 SimpleRemoteEPCArgBytesVector ArgBytes) override;
75 
76   void handleDisconnect(Error Err) override;
77 
78 protected:
79   virtual Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
80   createMemoryManager();
81   virtual Expected<std::unique_ptr<MemoryAccess>> createMemoryAccess();
82 
83 private:
SimpleRemoteEPC(std::shared_ptr<SymbolStringPool> SSP,std::unique_ptr<TaskDispatcher> D)84   SimpleRemoteEPC(std::shared_ptr<SymbolStringPool> SSP,
85                   std::unique_ptr<TaskDispatcher> D)
86     : ExecutorProcessControl(std::move(SSP), std::move(D)) {}
87 
88   Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
89                     ExecutorAddr TagAddr, ArrayRef<char> ArgBytes);
90 
91   Error handleSetup(uint64_t SeqNo, ExecutorAddr TagAddr,
92                     SimpleRemoteEPCArgBytesVector ArgBytes);
93   Error setup();
94 
95   Error handleResult(uint64_t SeqNo, ExecutorAddr TagAddr,
96                      SimpleRemoteEPCArgBytesVector ArgBytes);
97   void handleCallWrapper(uint64_t RemoteSeqNo, ExecutorAddr TagAddr,
98                          SimpleRemoteEPCArgBytesVector ArgBytes);
99   Error handleHangup(SimpleRemoteEPCArgBytesVector ArgBytes);
100 
getNextSeqNo()101   uint64_t getNextSeqNo() { return NextSeqNo++; }
releaseSeqNo(uint64_t SeqNo)102   void releaseSeqNo(uint64_t SeqNo) {}
103 
104   using PendingCallWrapperResultsMap =
105     DenseMap<uint64_t, IncomingWFRHandler>;
106 
107   std::mutex SimpleRemoteEPCMutex;
108   std::condition_variable DisconnectCV;
109   bool Disconnected = false;
110   Error DisconnectErr = Error::success();
111 
112   std::unique_ptr<SimpleRemoteEPCTransport> T;
113   std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
114   std::unique_ptr<MemoryAccess> OwnedMemAccess;
115 
116   std::unique_ptr<EPCGenericDylibManager> DylibMgr;
117   ExecutorAddr RunAsMainAddr;
118 
119   uint64_t NextSeqNo = 0;
120   PendingCallWrapperResultsMap PendingCallWrapperResults;
121 };
122 
123 } // end namespace orc
124 } // end namespace llvm
125 
126 #endif // LLVM_EXECUTIONENGINE_ORC_SIMPLEREMOTEEPC_H
127