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