| //===--- SimpleRemoteEPCUtils.h - Utils for Simple Remote EPC ---*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // Message definitions and other utilities for SimpleRemoteEPC and |
| // SimpleRemoteEPCServer. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H |
| #define LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H |
| |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/StringMap.h" |
| #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" |
| #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h" |
| #include "llvm/Support/Error.h" |
| |
| #include <atomic> |
| #include <mutex> |
| #include <string> |
| #include <thread> |
| |
| namespace llvm { |
| namespace orc { |
| |
| namespace SimpleRemoteEPCDefaultBootstrapSymbolNames { |
| extern const char *ExecutorSessionObjectName; |
| extern const char *DispatchFnName; |
| } // end namespace SimpleRemoteEPCDefaultBootstrapSymbolNames |
| |
| enum class SimpleRemoteEPCOpcode : uint8_t { |
| Setup, |
| Hangup, |
| Result, |
| CallWrapper, |
| LastOpC = CallWrapper |
| }; |
| |
| struct SimpleRemoteEPCExecutorInfo { |
| std::string TargetTriple; |
| uint64_t PageSize; |
| StringMap<ExecutorAddr> BootstrapSymbols; |
| }; |
| |
| using SimpleRemoteEPCArgBytesVector = SmallVector<char, 128>; |
| |
| class SimpleRemoteEPCTransportClient { |
| public: |
| enum HandleMessageAction { ContinueSession, EndSession }; |
| |
| virtual ~SimpleRemoteEPCTransportClient(); |
| |
| /// Handle receipt of a message. |
| /// |
| /// Returns an Error if the message cannot be handled, 'EndSession' if the |
| /// client will not accept any further messages, and 'ContinueSession' |
| /// otherwise. |
| virtual Expected<HandleMessageAction> |
| handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr, |
| SimpleRemoteEPCArgBytesVector ArgBytes) = 0; |
| |
| /// Handle a disconnection from the underlying transport. No further messages |
| /// should be sent to handleMessage after this is called. |
| /// Err may contain an Error value indicating unexpected disconnection. This |
| /// allows clients to log such errors, but no attempt should be made at |
| /// recovery (which should be handled inside the transport class, if it is |
| /// supported at all). |
| virtual void handleDisconnect(Error Err) = 0; |
| }; |
| |
| class SimpleRemoteEPCTransport { |
| public: |
| virtual ~SimpleRemoteEPCTransport(); |
| |
| /// Called during setup of the client to indicate that the client is ready |
| /// to receive messages. |
| /// |
| /// Transport objects should not access the client until this method is |
| /// called. |
| virtual Error start() = 0; |
| |
| /// Send a SimpleRemoteEPC message. |
| /// |
| /// This function may be called concurrently. Subclasses should implement |
| /// locking if required for the underlying transport. |
| virtual Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, |
| ExecutorAddr TagAddr, ArrayRef<char> ArgBytes) = 0; |
| |
| /// Trigger disconnection from the transport. The implementation should |
| /// respond by calling handleDisconnect on the client once disconnection |
| /// is complete. May be called more than once and from different threads. |
| virtual void disconnect() = 0; |
| }; |
| |
| /// Uses read/write on FileDescriptors for transport. |
| class FDSimpleRemoteEPCTransport : public SimpleRemoteEPCTransport { |
| public: |
| /// Create a FDSimpleRemoteEPCTransport using the given FDs for |
| /// reading (InFD) and writing (OutFD). |
| static Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>> |
| Create(SimpleRemoteEPCTransportClient &C, int InFD, int OutFD); |
| |
| /// Create a FDSimpleRemoteEPCTransport using the given FD for both |
| /// reading and writing. |
| static Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>> |
| Create(SimpleRemoteEPCTransportClient &C, int FD) { |
| return Create(C, FD, FD); |
| } |
| |
| ~FDSimpleRemoteEPCTransport() override; |
| |
| Error start() override; |
| |
| Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, |
| ExecutorAddr TagAddr, ArrayRef<char> ArgBytes) override; |
| |
| void disconnect() override; |
| |
| private: |
| FDSimpleRemoteEPCTransport(SimpleRemoteEPCTransportClient &C, int InFD, |
| int OutFD) |
| : C(C), InFD(InFD), OutFD(OutFD) {} |
| |
| Error readBytes(char *Dst, size_t Size, bool *IsEOF = nullptr); |
| int writeBytes(const char *Src, size_t Size); |
| void listenLoop(); |
| |
| std::mutex M; |
| SimpleRemoteEPCTransportClient &C; |
| std::thread ListenerThread; |
| int InFD, OutFD; |
| std::atomic<bool> Disconnected{false}; |
| }; |
| |
| struct RemoteSymbolLookupSetElement { |
| std::string Name; |
| bool Required; |
| }; |
| |
| using RemoteSymbolLookupSet = std::vector<RemoteSymbolLookupSetElement>; |
| |
| struct RemoteSymbolLookup { |
| uint64_t H; |
| RemoteSymbolLookupSet Symbols; |
| }; |
| |
| namespace shared { |
| |
| using SPSRemoteSymbolLookupSetElement = SPSTuple<SPSString, bool>; |
| |
| using SPSRemoteSymbolLookupSet = SPSSequence<SPSRemoteSymbolLookupSetElement>; |
| |
| using SPSRemoteSymbolLookup = SPSTuple<uint64_t, SPSRemoteSymbolLookupSet>; |
| |
| /// Tuple containing target triple, page size, and bootstrap symbols. |
| using SPSSimpleRemoteEPCExecutorInfo = |
| SPSTuple<SPSString, uint64_t, |
| SPSSequence<SPSTuple<SPSString, SPSExecutorAddr>>>; |
| |
| template <> |
| class SPSSerializationTraits<SPSRemoteSymbolLookupSetElement, |
| RemoteSymbolLookupSetElement> { |
| public: |
| static size_t size(const RemoteSymbolLookupSetElement &V) { |
| return SPSArgList<SPSString, bool>::size(V.Name, V.Required); |
| } |
| |
| static size_t serialize(SPSOutputBuffer &OB, |
| const RemoteSymbolLookupSetElement &V) { |
| return SPSArgList<SPSString, bool>::serialize(OB, V.Name, V.Required); |
| } |
| |
| static size_t deserialize(SPSInputBuffer &IB, |
| RemoteSymbolLookupSetElement &V) { |
| return SPSArgList<SPSString, bool>::deserialize(IB, V.Name, V.Required); |
| } |
| }; |
| |
| template <> |
| class SPSSerializationTraits<SPSRemoteSymbolLookup, RemoteSymbolLookup> { |
| public: |
| static size_t size(const RemoteSymbolLookup &V) { |
| return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::size(V.H, V.Symbols); |
| } |
| |
| static size_t serialize(SPSOutputBuffer &OB, const RemoteSymbolLookup &V) { |
| return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::serialize(OB, V.H, |
| V.Symbols); |
| } |
| |
| static size_t deserialize(SPSInputBuffer &IB, RemoteSymbolLookup &V) { |
| return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::deserialize( |
| IB, V.H, V.Symbols); |
| } |
| }; |
| |
| template <> |
| class SPSSerializationTraits<SPSSimpleRemoteEPCExecutorInfo, |
| SimpleRemoteEPCExecutorInfo> { |
| public: |
| static size_t size(const SimpleRemoteEPCExecutorInfo &SI) { |
| return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::size( |
| SI.TargetTriple, SI.PageSize, SI.BootstrapSymbols); |
| } |
| |
| static bool serialize(SPSOutputBuffer &OB, |
| const SimpleRemoteEPCExecutorInfo &SI) { |
| return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::serialize( |
| OB, SI.TargetTriple, SI.PageSize, SI.BootstrapSymbols); |
| } |
| |
| static bool deserialize(SPSInputBuffer &IB, SimpleRemoteEPCExecutorInfo &SI) { |
| return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::deserialize( |
| IB, SI.TargetTriple, SI.PageSize, SI.BootstrapSymbols); |
| } |
| }; |
| |
| using SPSLoadDylibSignature = SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, |
| SPSString, uint64_t); |
| |
| using SPSLookupSymbolsSignature = |
| SPSExpected<SPSSequence<SPSSequence<SPSExecutorAddr>>>( |
| SPSExecutorAddr, SPSSequence<SPSRemoteSymbolLookup>); |
| |
| } // end namespace shared |
| } // end namespace orc |
| } // end namespace llvm |
| |
| #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H |