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