xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===--- SimpleRemoteEPCUtils.h - Utils for Simple Remote EPC ---*- 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 // Message definitions and other utilities for SimpleRemoteEPC and
10 // SimpleRemoteEPCServer.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H
15 #define LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H
16 
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
21 #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
22 #include "llvm/Support/Compiler.h"
23 #include "llvm/Support/Error.h"
24 
25 #include <atomic>
26 #include <mutex>
27 #include <string>
28 #include <thread>
29 
30 namespace llvm {
31 namespace orc {
32 
33 namespace SimpleRemoteEPCDefaultBootstrapSymbolNames {
34 LLVM_ABI extern const char *ExecutorSessionObjectName;
35 LLVM_ABI extern const char *DispatchFnName;
36 } // end namespace SimpleRemoteEPCDefaultBootstrapSymbolNames
37 
38 enum class SimpleRemoteEPCOpcode : uint8_t {
39   Setup,
40   Hangup,
41   Result,
42   CallWrapper,
43   LastOpC = CallWrapper
44 };
45 
46 struct SimpleRemoteEPCExecutorInfo {
47   std::string TargetTriple;
48   uint64_t PageSize;
49   StringMap<std::vector<char>> BootstrapMap;
50   StringMap<ExecutorAddr> BootstrapSymbols;
51 };
52 
53 using SimpleRemoteEPCArgBytesVector = SmallVector<char, 128>;
54 
55 class LLVM_ABI SimpleRemoteEPCTransportClient {
56 public:
57   enum HandleMessageAction { ContinueSession, EndSession };
58 
59   virtual ~SimpleRemoteEPCTransportClient();
60 
61   /// Handle receipt of a message.
62   ///
63   /// Returns an Error if the message cannot be handled, 'EndSession' if the
64   /// client will not accept any further messages, and 'ContinueSession'
65   /// otherwise.
66   virtual Expected<HandleMessageAction>
67   handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr,
68                 SimpleRemoteEPCArgBytesVector ArgBytes) = 0;
69 
70   /// Handle a disconnection from the underlying transport. No further messages
71   /// should be sent to handleMessage after this is called.
72   /// Err may contain an Error value indicating unexpected disconnection. This
73   /// allows clients to log such errors, but no attempt should be made at
74   /// recovery (which should be handled inside the transport class, if it is
75   /// supported at all).
76   virtual void handleDisconnect(Error Err) = 0;
77 };
78 
79 class LLVM_ABI SimpleRemoteEPCTransport {
80 public:
81   virtual ~SimpleRemoteEPCTransport();
82 
83   /// Called during setup of the client to indicate that the client is ready
84   /// to receive messages.
85   ///
86   /// Transport objects should not access the client until this method is
87   /// called.
88   virtual Error start() = 0;
89 
90   /// Send a SimpleRemoteEPC message.
91   ///
92   /// This function may be called concurrently. Subclasses should implement
93   /// locking if required for the underlying transport.
94   virtual Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
95                             ExecutorAddr TagAddr, ArrayRef<char> ArgBytes) = 0;
96 
97   /// Trigger disconnection from the transport. The implementation should
98   /// respond by calling handleDisconnect on the client once disconnection
99   /// is complete. May be called more than once and from different threads.
100   virtual void disconnect() = 0;
101 };
102 
103 /// Uses read/write on FileDescriptors for transport.
104 class LLVM_ABI FDSimpleRemoteEPCTransport : public SimpleRemoteEPCTransport {
105 public:
106   /// Create a FDSimpleRemoteEPCTransport using the given FDs for
107   /// reading (InFD) and writing (OutFD).
108   static Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>>
109   Create(SimpleRemoteEPCTransportClient &C, int InFD, int OutFD);
110 
111   /// Create a FDSimpleRemoteEPCTransport using the given FD for both
112   /// reading and writing.
113   static Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>>
Create(SimpleRemoteEPCTransportClient & C,int FD)114   Create(SimpleRemoteEPCTransportClient &C, int FD) {
115     return Create(C, FD, FD);
116   }
117 
118   ~FDSimpleRemoteEPCTransport() override;
119 
120   Error start() override;
121 
122   Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
123                     ExecutorAddr TagAddr, ArrayRef<char> ArgBytes) override;
124 
125   void disconnect() override;
126 
127 private:
FDSimpleRemoteEPCTransport(SimpleRemoteEPCTransportClient & C,int InFD,int OutFD)128   FDSimpleRemoteEPCTransport(SimpleRemoteEPCTransportClient &C, int InFD,
129                              int OutFD)
130       : C(C), InFD(InFD), OutFD(OutFD) {}
131 
132   Error readBytes(char *Dst, size_t Size, bool *IsEOF = nullptr);
133   int writeBytes(const char *Src, size_t Size);
134   void listenLoop();
135 
136   std::mutex M;
137   SimpleRemoteEPCTransportClient &C;
138   std::thread ListenerThread;
139   int InFD, OutFD;
140   std::atomic<bool> Disconnected{false};
141 };
142 
143 struct RemoteSymbolLookupSetElement {
144   std::string Name;
145   bool Required;
146 };
147 
148 using RemoteSymbolLookupSet = std::vector<RemoteSymbolLookupSetElement>;
149 
150 struct RemoteSymbolLookup {
151   uint64_t H;
152   RemoteSymbolLookupSet Symbols;
153 };
154 
155 namespace shared {
156 
157 using SPSRemoteSymbolLookupSetElement = SPSTuple<SPSString, bool>;
158 
159 using SPSRemoteSymbolLookupSet = SPSSequence<SPSRemoteSymbolLookupSetElement>;
160 
161 using SPSRemoteSymbolLookup = SPSTuple<uint64_t, SPSRemoteSymbolLookupSet>;
162 
163 /// Tuple containing target triple, page size, and bootstrap symbols.
164 using SPSSimpleRemoteEPCExecutorInfo =
165     SPSTuple<SPSString, uint64_t,
166              SPSSequence<SPSTuple<SPSString, SPSSequence<char>>>,
167              SPSSequence<SPSTuple<SPSString, SPSExecutorAddr>>>;
168 
169 template <>
170 class SPSSerializationTraits<SPSRemoteSymbolLookupSetElement,
171                              RemoteSymbolLookupSetElement> {
172 public:
size(const RemoteSymbolLookupSetElement & V)173   static size_t size(const RemoteSymbolLookupSetElement &V) {
174     return SPSArgList<SPSString, bool>::size(V.Name, V.Required);
175   }
176 
serialize(SPSOutputBuffer & OB,const RemoteSymbolLookupSetElement & V)177   static size_t serialize(SPSOutputBuffer &OB,
178                           const RemoteSymbolLookupSetElement &V) {
179     return SPSArgList<SPSString, bool>::serialize(OB, V.Name, V.Required);
180   }
181 
deserialize(SPSInputBuffer & IB,RemoteSymbolLookupSetElement & V)182   static size_t deserialize(SPSInputBuffer &IB,
183                             RemoteSymbolLookupSetElement &V) {
184     return SPSArgList<SPSString, bool>::deserialize(IB, V.Name, V.Required);
185   }
186 };
187 
188 template <>
189 class SPSSerializationTraits<SPSRemoteSymbolLookup, RemoteSymbolLookup> {
190 public:
size(const RemoteSymbolLookup & V)191   static size_t size(const RemoteSymbolLookup &V) {
192     return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::size(V.H, V.Symbols);
193   }
194 
serialize(SPSOutputBuffer & OB,const RemoteSymbolLookup & V)195   static size_t serialize(SPSOutputBuffer &OB, const RemoteSymbolLookup &V) {
196     return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::serialize(OB, V.H,
197                                                                      V.Symbols);
198   }
199 
deserialize(SPSInputBuffer & IB,RemoteSymbolLookup & V)200   static size_t deserialize(SPSInputBuffer &IB, RemoteSymbolLookup &V) {
201     return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::deserialize(
202         IB, V.H, V.Symbols);
203   }
204 };
205 
206 template <>
207 class SPSSerializationTraits<SPSSimpleRemoteEPCExecutorInfo,
208                              SimpleRemoteEPCExecutorInfo> {
209 public:
size(const SimpleRemoteEPCExecutorInfo & SI)210   static size_t size(const SimpleRemoteEPCExecutorInfo &SI) {
211     return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::size(
212         SI.TargetTriple, SI.PageSize, SI.BootstrapMap, SI.BootstrapSymbols);
213   }
214 
serialize(SPSOutputBuffer & OB,const SimpleRemoteEPCExecutorInfo & SI)215   static bool serialize(SPSOutputBuffer &OB,
216                         const SimpleRemoteEPCExecutorInfo &SI) {
217     return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::serialize(
218         OB, SI.TargetTriple, SI.PageSize, SI.BootstrapMap, SI.BootstrapSymbols);
219   }
220 
deserialize(SPSInputBuffer & IB,SimpleRemoteEPCExecutorInfo & SI)221   static bool deserialize(SPSInputBuffer &IB, SimpleRemoteEPCExecutorInfo &SI) {
222     return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::deserialize(
223         IB, SI.TargetTriple, SI.PageSize, SI.BootstrapMap, SI.BootstrapSymbols);
224   }
225 };
226 
227 using SPSLoadDylibSignature = SPSExpected<SPSExecutorAddr>(SPSExecutorAddr,
228                                                            SPSString, uint64_t);
229 
230 using SPSLookupSymbolsSignature =
231     SPSExpected<SPSSequence<SPSSequence<SPSExecutorAddr>>>(
232         SPSExecutorAddr, SPSSequence<SPSRemoteSymbolLookup>);
233 
234 } // end namespace shared
235 } // end namespace orc
236 } // end namespace llvm
237 
238 #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H
239