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
28namespace llvm {
29namespace orc {
30
31class SimpleRemoteEPC : public ExecutorProcessControl,
32 public SimpleRemoteEPCTransportClient {
33public:
34 /// A setup object containing callbacks to construct a memory manager and
35 /// memory access object. Both are optional. If not specified,
36 /// EPCGenericJITLinkMemoryManager and EPCGenericMemoryAccess will be used.
37 struct Setup {
38 using CreateMemoryManagerFn =
39 Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>(
40 SimpleRemoteEPC &);
41 using CreateMemoryAccessFn =
42 Expected<std::unique_ptr<MemoryAccess>>(SimpleRemoteEPC &);
43
44 unique_function<CreateMemoryManagerFn> CreateMemoryManager;
45 unique_function<CreateMemoryAccessFn> CreateMemoryAccess;
46 };
47
48 /// Create a SimpleRemoteEPC using the given transport type and args.
49 template <typename TransportT, typename... TransportTCtorArgTs>
50 static Expected<std::unique_ptr<SimpleRemoteEPC>>
51 Create(std::unique_ptr<TaskDispatcher> D, Setup S,
52 TransportTCtorArgTs &&...TransportTCtorArgs) {
53 std::unique_ptr<SimpleRemoteEPC> SREPC(
54 new SimpleRemoteEPC(std::make_shared<SymbolStringPool>(),
55 std::move(D)));
56 auto T = TransportT::Create(
57 *SREPC, std::forward<TransportTCtorArgTs>(TransportTCtorArgs)...);
58 if (!T)
59 return T.takeError();
60 SREPC->T = std::move(*T);
61 if (auto Err = SREPC->setup(std::move(S)))
62 return joinErrors(E1: std::move(Err), E2: SREPC->disconnect());
63 return std::move(SREPC);
64 }
65
66 SimpleRemoteEPC(const SimpleRemoteEPC &) = delete;
67 SimpleRemoteEPC &operator=(const SimpleRemoteEPC &) = delete;
68 SimpleRemoteEPC(SimpleRemoteEPC &&) = delete;
69 SimpleRemoteEPC &operator=(SimpleRemoteEPC &&) = delete;
70 ~SimpleRemoteEPC();
71
72 Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override;
73
74 void lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
75 SymbolLookupCompleteFn F) override;
76
77 Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
78 ArrayRef<std::string> Args) override;
79
80 Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) override;
81
82 Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override;
83
84 void callWrapperAsync(ExecutorAddr WrapperFnAddr,
85 IncomingWFRHandler OnComplete,
86 ArrayRef<char> ArgBuffer) override;
87
88 Error disconnect() override;
89
90 Expected<HandleMessageAction>
91 handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr,
92 SimpleRemoteEPCArgBytesVector ArgBytes) override;
93
94 void handleDisconnect(Error Err) override;
95
96private:
97 SimpleRemoteEPC(std::shared_ptr<SymbolStringPool> SSP,
98 std::unique_ptr<TaskDispatcher> D)
99 : ExecutorProcessControl(std::move(SSP), std::move(D)) {}
100
101 static Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
102 createDefaultMemoryManager(SimpleRemoteEPC &SREPC);
103 static Expected<std::unique_ptr<MemoryAccess>>
104 createDefaultMemoryAccess(SimpleRemoteEPC &SREPC);
105
106 Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
107 ExecutorAddr TagAddr, ArrayRef<char> ArgBytes);
108
109 Error handleSetup(uint64_t SeqNo, ExecutorAddr TagAddr,
110 SimpleRemoteEPCArgBytesVector ArgBytes);
111 Error setup(Setup S);
112
113 Error handleResult(uint64_t SeqNo, ExecutorAddr TagAddr,
114 SimpleRemoteEPCArgBytesVector ArgBytes);
115 void handleCallWrapper(uint64_t RemoteSeqNo, ExecutorAddr TagAddr,
116 SimpleRemoteEPCArgBytesVector ArgBytes);
117 Error handleHangup(SimpleRemoteEPCArgBytesVector ArgBytes);
118
119 uint64_t getNextSeqNo() { return NextSeqNo++; }
120 void releaseSeqNo(uint64_t SeqNo) {}
121
122 using PendingCallWrapperResultsMap =
123 DenseMap<uint64_t, IncomingWFRHandler>;
124
125 std::mutex SimpleRemoteEPCMutex;
126 std::condition_variable DisconnectCV;
127 bool Disconnected = false;
128 Error DisconnectErr = Error::success();
129
130 std::unique_ptr<SimpleRemoteEPCTransport> T;
131 std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
132 std::unique_ptr<MemoryAccess> OwnedMemAccess;
133
134 std::unique_ptr<EPCGenericDylibManager> DylibMgr;
135 ExecutorAddr RunAsMainAddr;
136 ExecutorAddr RunAsVoidFunctionAddr;
137 ExecutorAddr RunAsIntFunctionAddr;
138
139 uint64_t NextSeqNo = 0;
140 PendingCallWrapperResultsMap PendingCallWrapperResults;
141};
142
143} // end namespace orc
144} // end namespace llvm
145
146#endif // LLVM_EXECUTIONENGINE_ORC_SIMPLEREMOTEEPC_H
147

source code of llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h