1349cc55cSDimitry Andric //===--- SimpleRemoteEPCUtils.h - Utils for Simple Remote EPC ---*- C++ -*-===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric // 9349cc55cSDimitry Andric // Message definitions and other utilities for SimpleRemoteEPC and 10349cc55cSDimitry Andric // SimpleRemoteEPCServer. 11349cc55cSDimitry Andric // 12349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 13349cc55cSDimitry Andric 14349cc55cSDimitry Andric #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H 15349cc55cSDimitry Andric #define LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H 16349cc55cSDimitry Andric 17349cc55cSDimitry Andric #include "llvm/ADT/ArrayRef.h" 18349cc55cSDimitry Andric #include "llvm/ADT/SmallVector.h" 19349cc55cSDimitry Andric #include "llvm/ADT/StringMap.h" 20349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" 21349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h" 22349cc55cSDimitry Andric #include "llvm/Support/Error.h" 23349cc55cSDimitry Andric 24349cc55cSDimitry Andric #include <atomic> 25349cc55cSDimitry Andric #include <mutex> 26349cc55cSDimitry Andric #include <string> 27349cc55cSDimitry Andric #include <thread> 28349cc55cSDimitry Andric 29349cc55cSDimitry Andric namespace llvm { 30349cc55cSDimitry Andric namespace orc { 31349cc55cSDimitry Andric 32349cc55cSDimitry Andric namespace SimpleRemoteEPCDefaultBootstrapSymbolNames { 33349cc55cSDimitry Andric extern const char *ExecutorSessionObjectName; 34349cc55cSDimitry Andric extern const char *DispatchFnName; 35349cc55cSDimitry Andric } // end namespace SimpleRemoteEPCDefaultBootstrapSymbolNames 36349cc55cSDimitry Andric 37349cc55cSDimitry Andric enum class SimpleRemoteEPCOpcode : uint8_t { 38349cc55cSDimitry Andric Setup, 39349cc55cSDimitry Andric Hangup, 40349cc55cSDimitry Andric Result, 41349cc55cSDimitry Andric CallWrapper, 42349cc55cSDimitry Andric LastOpC = CallWrapper 43349cc55cSDimitry Andric }; 44349cc55cSDimitry Andric 45349cc55cSDimitry Andric struct SimpleRemoteEPCExecutorInfo { 46349cc55cSDimitry Andric std::string TargetTriple; 47349cc55cSDimitry Andric uint64_t PageSize; 48*06c3fb27SDimitry Andric StringMap<std::vector<char>> BootstrapMap; 49349cc55cSDimitry Andric StringMap<ExecutorAddr> BootstrapSymbols; 50349cc55cSDimitry Andric }; 51349cc55cSDimitry Andric 52349cc55cSDimitry Andric using SimpleRemoteEPCArgBytesVector = SmallVector<char, 128>; 53349cc55cSDimitry Andric 54349cc55cSDimitry Andric class SimpleRemoteEPCTransportClient { 55349cc55cSDimitry Andric public: 56349cc55cSDimitry Andric enum HandleMessageAction { ContinueSession, EndSession }; 57349cc55cSDimitry Andric 58349cc55cSDimitry Andric virtual ~SimpleRemoteEPCTransportClient(); 59349cc55cSDimitry Andric 60349cc55cSDimitry Andric /// Handle receipt of a message. 61349cc55cSDimitry Andric /// 62349cc55cSDimitry Andric /// Returns an Error if the message cannot be handled, 'EndSession' if the 63349cc55cSDimitry Andric /// client will not accept any further messages, and 'ContinueSession' 64349cc55cSDimitry Andric /// otherwise. 65349cc55cSDimitry Andric virtual Expected<HandleMessageAction> 66349cc55cSDimitry Andric handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr, 67349cc55cSDimitry Andric SimpleRemoteEPCArgBytesVector ArgBytes) = 0; 68349cc55cSDimitry Andric 69349cc55cSDimitry Andric /// Handle a disconnection from the underlying transport. No further messages 70349cc55cSDimitry Andric /// should be sent to handleMessage after this is called. 71349cc55cSDimitry Andric /// Err may contain an Error value indicating unexpected disconnection. This 72349cc55cSDimitry Andric /// allows clients to log such errors, but no attempt should be made at 73349cc55cSDimitry Andric /// recovery (which should be handled inside the transport class, if it is 74349cc55cSDimitry Andric /// supported at all). 75349cc55cSDimitry Andric virtual void handleDisconnect(Error Err) = 0; 76349cc55cSDimitry Andric }; 77349cc55cSDimitry Andric 78349cc55cSDimitry Andric class SimpleRemoteEPCTransport { 79349cc55cSDimitry Andric public: 80349cc55cSDimitry Andric virtual ~SimpleRemoteEPCTransport(); 81349cc55cSDimitry Andric 82349cc55cSDimitry Andric /// Called during setup of the client to indicate that the client is ready 83349cc55cSDimitry Andric /// to receive messages. 84349cc55cSDimitry Andric /// 85349cc55cSDimitry Andric /// Transport objects should not access the client until this method is 86349cc55cSDimitry Andric /// called. 87349cc55cSDimitry Andric virtual Error start() = 0; 88349cc55cSDimitry Andric 89349cc55cSDimitry Andric /// Send a SimpleRemoteEPC message. 90349cc55cSDimitry Andric /// 91349cc55cSDimitry Andric /// This function may be called concurrently. Subclasses should implement 92349cc55cSDimitry Andric /// locking if required for the underlying transport. 93349cc55cSDimitry Andric virtual Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, 94349cc55cSDimitry Andric ExecutorAddr TagAddr, ArrayRef<char> ArgBytes) = 0; 95349cc55cSDimitry Andric 96349cc55cSDimitry Andric /// Trigger disconnection from the transport. The implementation should 97349cc55cSDimitry Andric /// respond by calling handleDisconnect on the client once disconnection 98349cc55cSDimitry Andric /// is complete. May be called more than once and from different threads. 99349cc55cSDimitry Andric virtual void disconnect() = 0; 100349cc55cSDimitry Andric }; 101349cc55cSDimitry Andric 102349cc55cSDimitry Andric /// Uses read/write on FileDescriptors for transport. 103349cc55cSDimitry Andric class FDSimpleRemoteEPCTransport : public SimpleRemoteEPCTransport { 104349cc55cSDimitry Andric public: 105349cc55cSDimitry Andric /// Create a FDSimpleRemoteEPCTransport using the given FDs for 106349cc55cSDimitry Andric /// reading (InFD) and writing (OutFD). 107349cc55cSDimitry Andric static Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>> 108349cc55cSDimitry Andric Create(SimpleRemoteEPCTransportClient &C, int InFD, int OutFD); 109349cc55cSDimitry Andric 110349cc55cSDimitry Andric /// Create a FDSimpleRemoteEPCTransport using the given FD for both 111349cc55cSDimitry Andric /// reading and writing. 112349cc55cSDimitry Andric static Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>> Create(SimpleRemoteEPCTransportClient & C,int FD)113349cc55cSDimitry Andric Create(SimpleRemoteEPCTransportClient &C, int FD) { 114349cc55cSDimitry Andric return Create(C, FD, FD); 115349cc55cSDimitry Andric } 116349cc55cSDimitry Andric 117349cc55cSDimitry Andric ~FDSimpleRemoteEPCTransport() override; 118349cc55cSDimitry Andric 119349cc55cSDimitry Andric Error start() override; 120349cc55cSDimitry Andric 121349cc55cSDimitry Andric Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, 122349cc55cSDimitry Andric ExecutorAddr TagAddr, ArrayRef<char> ArgBytes) override; 123349cc55cSDimitry Andric 124349cc55cSDimitry Andric void disconnect() override; 125349cc55cSDimitry Andric 126349cc55cSDimitry Andric private: FDSimpleRemoteEPCTransport(SimpleRemoteEPCTransportClient & C,int InFD,int OutFD)127349cc55cSDimitry Andric FDSimpleRemoteEPCTransport(SimpleRemoteEPCTransportClient &C, int InFD, 128349cc55cSDimitry Andric int OutFD) 129349cc55cSDimitry Andric : C(C), InFD(InFD), OutFD(OutFD) {} 130349cc55cSDimitry Andric 131349cc55cSDimitry Andric Error readBytes(char *Dst, size_t Size, bool *IsEOF = nullptr); 132349cc55cSDimitry Andric int writeBytes(const char *Src, size_t Size); 133349cc55cSDimitry Andric void listenLoop(); 134349cc55cSDimitry Andric 135349cc55cSDimitry Andric std::mutex M; 136349cc55cSDimitry Andric SimpleRemoteEPCTransportClient &C; 137349cc55cSDimitry Andric std::thread ListenerThread; 138349cc55cSDimitry Andric int InFD, OutFD; 139349cc55cSDimitry Andric std::atomic<bool> Disconnected{false}; 140349cc55cSDimitry Andric }; 141349cc55cSDimitry Andric 142349cc55cSDimitry Andric struct RemoteSymbolLookupSetElement { 143349cc55cSDimitry Andric std::string Name; 144349cc55cSDimitry Andric bool Required; 145349cc55cSDimitry Andric }; 146349cc55cSDimitry Andric 147349cc55cSDimitry Andric using RemoteSymbolLookupSet = std::vector<RemoteSymbolLookupSetElement>; 148349cc55cSDimitry Andric 149349cc55cSDimitry Andric struct RemoteSymbolLookup { 150349cc55cSDimitry Andric uint64_t H; 151349cc55cSDimitry Andric RemoteSymbolLookupSet Symbols; 152349cc55cSDimitry Andric }; 153349cc55cSDimitry Andric 154349cc55cSDimitry Andric namespace shared { 155349cc55cSDimitry Andric 156349cc55cSDimitry Andric using SPSRemoteSymbolLookupSetElement = SPSTuple<SPSString, bool>; 157349cc55cSDimitry Andric 158349cc55cSDimitry Andric using SPSRemoteSymbolLookupSet = SPSSequence<SPSRemoteSymbolLookupSetElement>; 159349cc55cSDimitry Andric 160349cc55cSDimitry Andric using SPSRemoteSymbolLookup = SPSTuple<uint64_t, SPSRemoteSymbolLookupSet>; 161349cc55cSDimitry Andric 162349cc55cSDimitry Andric /// Tuple containing target triple, page size, and bootstrap symbols. 163349cc55cSDimitry Andric using SPSSimpleRemoteEPCExecutorInfo = 164349cc55cSDimitry Andric SPSTuple<SPSString, uint64_t, 165*06c3fb27SDimitry Andric SPSSequence<SPSTuple<SPSString, SPSSequence<char>>>, 166349cc55cSDimitry Andric SPSSequence<SPSTuple<SPSString, SPSExecutorAddr>>>; 167349cc55cSDimitry Andric 168349cc55cSDimitry Andric template <> 169349cc55cSDimitry Andric class SPSSerializationTraits<SPSRemoteSymbolLookupSetElement, 170349cc55cSDimitry Andric RemoteSymbolLookupSetElement> { 171349cc55cSDimitry Andric public: size(const RemoteSymbolLookupSetElement & V)172349cc55cSDimitry Andric static size_t size(const RemoteSymbolLookupSetElement &V) { 173349cc55cSDimitry Andric return SPSArgList<SPSString, bool>::size(V.Name, V.Required); 174349cc55cSDimitry Andric } 175349cc55cSDimitry Andric serialize(SPSOutputBuffer & OB,const RemoteSymbolLookupSetElement & V)176349cc55cSDimitry Andric static size_t serialize(SPSOutputBuffer &OB, 177349cc55cSDimitry Andric const RemoteSymbolLookupSetElement &V) { 178349cc55cSDimitry Andric return SPSArgList<SPSString, bool>::serialize(OB, V.Name, V.Required); 179349cc55cSDimitry Andric } 180349cc55cSDimitry Andric deserialize(SPSInputBuffer & IB,RemoteSymbolLookupSetElement & V)181349cc55cSDimitry Andric static size_t deserialize(SPSInputBuffer &IB, 182349cc55cSDimitry Andric RemoteSymbolLookupSetElement &V) { 183349cc55cSDimitry Andric return SPSArgList<SPSString, bool>::deserialize(IB, V.Name, V.Required); 184349cc55cSDimitry Andric } 185349cc55cSDimitry Andric }; 186349cc55cSDimitry Andric 187349cc55cSDimitry Andric template <> 188349cc55cSDimitry Andric class SPSSerializationTraits<SPSRemoteSymbolLookup, RemoteSymbolLookup> { 189349cc55cSDimitry Andric public: size(const RemoteSymbolLookup & V)190349cc55cSDimitry Andric static size_t size(const RemoteSymbolLookup &V) { 191349cc55cSDimitry Andric return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::size(V.H, V.Symbols); 192349cc55cSDimitry Andric } 193349cc55cSDimitry Andric serialize(SPSOutputBuffer & OB,const RemoteSymbolLookup & V)194349cc55cSDimitry Andric static size_t serialize(SPSOutputBuffer &OB, const RemoteSymbolLookup &V) { 195349cc55cSDimitry Andric return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::serialize(OB, V.H, 196349cc55cSDimitry Andric V.Symbols); 197349cc55cSDimitry Andric } 198349cc55cSDimitry Andric deserialize(SPSInputBuffer & IB,RemoteSymbolLookup & V)199349cc55cSDimitry Andric static size_t deserialize(SPSInputBuffer &IB, RemoteSymbolLookup &V) { 200349cc55cSDimitry Andric return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::deserialize( 201349cc55cSDimitry Andric IB, V.H, V.Symbols); 202349cc55cSDimitry Andric } 203349cc55cSDimitry Andric }; 204349cc55cSDimitry Andric 205349cc55cSDimitry Andric template <> 206349cc55cSDimitry Andric class SPSSerializationTraits<SPSSimpleRemoteEPCExecutorInfo, 207349cc55cSDimitry Andric SimpleRemoteEPCExecutorInfo> { 208349cc55cSDimitry Andric public: size(const SimpleRemoteEPCExecutorInfo & SI)209349cc55cSDimitry Andric static size_t size(const SimpleRemoteEPCExecutorInfo &SI) { 210349cc55cSDimitry Andric return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::size( 211*06c3fb27SDimitry Andric SI.TargetTriple, SI.PageSize, SI.BootstrapMap, SI.BootstrapSymbols); 212349cc55cSDimitry Andric } 213349cc55cSDimitry Andric serialize(SPSOutputBuffer & OB,const SimpleRemoteEPCExecutorInfo & SI)214349cc55cSDimitry Andric static bool serialize(SPSOutputBuffer &OB, 215349cc55cSDimitry Andric const SimpleRemoteEPCExecutorInfo &SI) { 216349cc55cSDimitry Andric return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::serialize( 217*06c3fb27SDimitry Andric OB, SI.TargetTriple, SI.PageSize, SI.BootstrapMap, SI.BootstrapSymbols); 218349cc55cSDimitry Andric } 219349cc55cSDimitry Andric deserialize(SPSInputBuffer & IB,SimpleRemoteEPCExecutorInfo & SI)220349cc55cSDimitry Andric static bool deserialize(SPSInputBuffer &IB, SimpleRemoteEPCExecutorInfo &SI) { 221349cc55cSDimitry Andric return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::deserialize( 222*06c3fb27SDimitry Andric IB, SI.TargetTriple, SI.PageSize, SI.BootstrapMap, SI.BootstrapSymbols); 223349cc55cSDimitry Andric } 224349cc55cSDimitry Andric }; 225349cc55cSDimitry Andric 226349cc55cSDimitry Andric using SPSLoadDylibSignature = SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, 227349cc55cSDimitry Andric SPSString, uint64_t); 228349cc55cSDimitry Andric 229349cc55cSDimitry Andric using SPSLookupSymbolsSignature = 230349cc55cSDimitry Andric SPSExpected<SPSSequence<SPSSequence<SPSExecutorAddr>>>( 231349cc55cSDimitry Andric SPSExecutorAddr, SPSSequence<SPSRemoteSymbolLookup>); 232349cc55cSDimitry Andric 233349cc55cSDimitry Andric } // end namespace shared 234349cc55cSDimitry Andric } // end namespace orc 235349cc55cSDimitry Andric } // end namespace llvm 236349cc55cSDimitry Andric 237349cc55cSDimitry Andric #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H 238