| //===- OrcRemoteTargetRPCAPI.h - Orc Remote-target RPC API ------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the Orc remote-target RPC API. It should not be used |
| // directly, but is used by the RemoteTargetClient and RemoteTargetServer |
| // classes. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H |
| #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H |
| |
| #include "llvm/ExecutionEngine/JITSymbol.h" |
| #include "llvm/ExecutionEngine/Orc/RPCUtils.h" |
| #include "llvm/ExecutionEngine/Orc/RawByteChannel.h" |
| |
| namespace llvm { |
| namespace orc { |
| |
| namespace remote { |
| |
| /// Template error for missing resources. |
| template <typename ResourceIdT> |
| class ResourceNotFound |
| : public ErrorInfo<ResourceNotFound<ResourceIdT>> { |
| public: |
| static char ID; |
| |
| ResourceNotFound(ResourceIdT ResourceId, |
| std::string ResourceDescription = "") |
| : ResourceId(std::move(ResourceId)), |
| ResourceDescription(std::move(ResourceDescription)) {} |
| |
| std::error_code convertToErrorCode() const override { |
| return orcError(OrcErrorCode::UnknownResourceHandle); |
| } |
| |
| void log(raw_ostream &OS) const override { |
| OS << (ResourceDescription.empty() |
| ? "Remote resource with id " |
| : ResourceDescription) |
| << " " << ResourceId << " not found"; |
| } |
| |
| private: |
| ResourceIdT ResourceId; |
| std::string ResourceDescription; |
| }; |
| |
| template <typename ResourceIdT> |
| char ResourceNotFound<ResourceIdT>::ID = 0; |
| |
| class DirectBufferWriter { |
| public: |
| DirectBufferWriter() = default; |
| DirectBufferWriter(const char *Src, JITTargetAddress Dst, uint64_t Size) |
| : Src(Src), Dst(Dst), Size(Size) {} |
| |
| const char *getSrc() const { return Src; } |
| JITTargetAddress getDst() const { return Dst; } |
| uint64_t getSize() const { return Size; } |
| |
| private: |
| const char *Src; |
| JITTargetAddress Dst; |
| uint64_t Size; |
| }; |
| |
| } // end namespace remote |
| |
| namespace rpc { |
| |
| template <> |
| class RPCTypeName<JITSymbolFlags> { |
| public: |
| static const char *getName() { return "JITSymbolFlags"; } |
| }; |
| |
| template <typename ChannelT> |
| class SerializationTraits<ChannelT, JITSymbolFlags> { |
| public: |
| |
| static Error serialize(ChannelT &C, const JITSymbolFlags &Flags) { |
| return serializeSeq(C, static_cast<JITSymbolFlags::UnderlyingType>(Flags), |
| Flags.getTargetFlags()); |
| } |
| |
| static Error deserialize(ChannelT &C, JITSymbolFlags &Flags) { |
| JITSymbolFlags::UnderlyingType JITFlags; |
| JITSymbolFlags::TargetFlagsType TargetFlags; |
| if (auto Err = deserializeSeq(C, JITFlags, TargetFlags)) |
| return Err; |
| Flags = JITSymbolFlags(static_cast<JITSymbolFlags::FlagNames>(JITFlags), |
| TargetFlags); |
| return Error::success(); |
| } |
| }; |
| |
| template <> class RPCTypeName<remote::DirectBufferWriter> { |
| public: |
| static const char *getName() { return "DirectBufferWriter"; } |
| }; |
| |
| template <typename ChannelT> |
| class SerializationTraits< |
| ChannelT, remote::DirectBufferWriter, remote::DirectBufferWriter, |
| typename std::enable_if< |
| std::is_base_of<RawByteChannel, ChannelT>::value>::type> { |
| public: |
| static Error serialize(ChannelT &C, const remote::DirectBufferWriter &DBW) { |
| if (auto EC = serializeSeq(C, DBW.getDst())) |
| return EC; |
| if (auto EC = serializeSeq(C, DBW.getSize())) |
| return EC; |
| return C.appendBytes(DBW.getSrc(), DBW.getSize()); |
| } |
| |
| static Error deserialize(ChannelT &C, remote::DirectBufferWriter &DBW) { |
| JITTargetAddress Dst; |
| if (auto EC = deserializeSeq(C, Dst)) |
| return EC; |
| uint64_t Size; |
| if (auto EC = deserializeSeq(C, Size)) |
| return EC; |
| char *Addr = reinterpret_cast<char *>(static_cast<uintptr_t>(Dst)); |
| |
| DBW = remote::DirectBufferWriter(nullptr, Dst, Size); |
| |
| return C.readBytes(Addr, Size); |
| } |
| }; |
| |
| } // end namespace rpc |
| |
| namespace remote { |
| |
| class ResourceIdMgr { |
| public: |
| using ResourceId = uint64_t; |
| static const ResourceId InvalidId = ~0U; |
| |
| ResourceIdMgr() = default; |
| explicit ResourceIdMgr(ResourceId FirstValidId) |
| : NextId(std::move(FirstValidId)) {} |
| |
| ResourceId getNext() { |
| if (!FreeIds.empty()) { |
| ResourceId I = FreeIds.back(); |
| FreeIds.pop_back(); |
| return I; |
| } |
| assert(NextId + 1 != ~0ULL && "All ids allocated"); |
| return NextId++; |
| } |
| |
| void release(ResourceId I) { FreeIds.push_back(I); } |
| |
| private: |
| ResourceId NextId = 1; |
| std::vector<ResourceId> FreeIds; |
| }; |
| |
| /// Registers EH frames on the remote. |
| namespace eh { |
| |
| /// Registers EH frames on the remote. |
| class RegisterEHFrames |
| : public rpc::Function<RegisterEHFrames, |
| void(JITTargetAddress Addr, uint32_t Size)> { |
| public: |
| static const char *getName() { return "RegisterEHFrames"; } |
| }; |
| |
| /// Deregisters EH frames on the remote. |
| class DeregisterEHFrames |
| : public rpc::Function<DeregisterEHFrames, |
| void(JITTargetAddress Addr, uint32_t Size)> { |
| public: |
| static const char *getName() { return "DeregisterEHFrames"; } |
| }; |
| |
| } // end namespace eh |
| |
| /// RPC functions for executing remote code. |
| namespace exec { |
| |
| /// Call an 'int32_t()'-type function on the remote, returns the called |
| /// function's return value. |
| class CallIntVoid |
| : public rpc::Function<CallIntVoid, int32_t(JITTargetAddress Addr)> { |
| public: |
| static const char *getName() { return "CallIntVoid"; } |
| }; |
| |
| /// Call an 'int32_t(int32_t, char**)'-type function on the remote, returns the |
| /// called function's return value. |
| class CallMain |
| : public rpc::Function<CallMain, int32_t(JITTargetAddress Addr, |
| std::vector<std::string> Args)> { |
| public: |
| static const char *getName() { return "CallMain"; } |
| }; |
| |
| /// Calls a 'void()'-type function on the remote, returns when the called |
| /// function completes. |
| class CallVoidVoid |
| : public rpc::Function<CallVoidVoid, void(JITTargetAddress FnAddr)> { |
| public: |
| static const char *getName() { return "CallVoidVoid"; } |
| }; |
| |
| } // end namespace exec |
| |
| /// RPC functions for remote memory management / inspection / modification. |
| namespace mem { |
| |
| /// Creates a memory allocator on the remote. |
| class CreateRemoteAllocator |
| : public rpc::Function<CreateRemoteAllocator, |
| void(ResourceIdMgr::ResourceId AllocatorID)> { |
| public: |
| static const char *getName() { return "CreateRemoteAllocator"; } |
| }; |
| |
| /// Destroys a remote allocator, freeing any memory allocated by it. |
| class DestroyRemoteAllocator |
| : public rpc::Function<DestroyRemoteAllocator, |
| void(ResourceIdMgr::ResourceId AllocatorID)> { |
| public: |
| static const char *getName() { return "DestroyRemoteAllocator"; } |
| }; |
| |
| /// Read a remote memory block. |
| class ReadMem |
| : public rpc::Function<ReadMem, std::vector<uint8_t>(JITTargetAddress Src, |
| uint64_t Size)> { |
| public: |
| static const char *getName() { return "ReadMem"; } |
| }; |
| |
| /// Reserve a block of memory on the remote via the given allocator. |
| class ReserveMem |
| : public rpc::Function<ReserveMem, |
| JITTargetAddress(ResourceIdMgr::ResourceId AllocID, |
| uint64_t Size, uint32_t Align)> { |
| public: |
| static const char *getName() { return "ReserveMem"; } |
| }; |
| |
| /// Set the memory protection on a memory block. |
| class SetProtections |
| : public rpc::Function<SetProtections, |
| void(ResourceIdMgr::ResourceId AllocID, |
| JITTargetAddress Dst, uint32_t ProtFlags)> { |
| public: |
| static const char *getName() { return "SetProtections"; } |
| }; |
| |
| /// Write to a remote memory block. |
| class WriteMem |
| : public rpc::Function<WriteMem, void(remote::DirectBufferWriter DB)> { |
| public: |
| static const char *getName() { return "WriteMem"; } |
| }; |
| |
| /// Write to a remote pointer. |
| class WritePtr : public rpc::Function<WritePtr, void(JITTargetAddress Dst, |
| JITTargetAddress Val)> { |
| public: |
| static const char *getName() { return "WritePtr"; } |
| }; |
| |
| } // end namespace mem |
| |
| /// RPC functions for remote stub and trampoline management. |
| namespace stubs { |
| |
| /// Creates an indirect stub owner on the remote. |
| class CreateIndirectStubsOwner |
| : public rpc::Function<CreateIndirectStubsOwner, |
| void(ResourceIdMgr::ResourceId StubOwnerID)> { |
| public: |
| static const char *getName() { return "CreateIndirectStubsOwner"; } |
| }; |
| |
| /// RPC function for destroying an indirect stubs owner. |
| class DestroyIndirectStubsOwner |
| : public rpc::Function<DestroyIndirectStubsOwner, |
| void(ResourceIdMgr::ResourceId StubsOwnerID)> { |
| public: |
| static const char *getName() { return "DestroyIndirectStubsOwner"; } |
| }; |
| |
| /// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted). |
| class EmitIndirectStubs |
| : public rpc::Function< |
| EmitIndirectStubs, |
| std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>( |
| ResourceIdMgr::ResourceId StubsOwnerID, |
| uint32_t NumStubsRequired)> { |
| public: |
| static const char *getName() { return "EmitIndirectStubs"; } |
| }; |
| |
| /// RPC function to emit the resolver block and return its address. |
| class EmitResolverBlock : public rpc::Function<EmitResolverBlock, void()> { |
| public: |
| static const char *getName() { return "EmitResolverBlock"; } |
| }; |
| |
| /// EmitTrampolineBlock result is (BlockAddr, NumTrampolines). |
| class EmitTrampolineBlock |
| : public rpc::Function<EmitTrampolineBlock, |
| std::tuple<JITTargetAddress, uint32_t>()> { |
| public: |
| static const char *getName() { return "EmitTrampolineBlock"; } |
| }; |
| |
| } // end namespace stubs |
| |
| /// Miscelaneous RPC functions for dealing with remotes. |
| namespace utils { |
| |
| /// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize, |
| /// IndirectStubsSize). |
| class GetRemoteInfo |
| : public rpc::Function< |
| GetRemoteInfo, |
| std::tuple<std::string, uint32_t, uint32_t, uint32_t, uint32_t>()> { |
| public: |
| static const char *getName() { return "GetRemoteInfo"; } |
| }; |
| |
| /// Get the address of a remote symbol. |
| class GetSymbolAddress |
| : public rpc::Function<GetSymbolAddress, |
| JITTargetAddress(std::string SymbolName)> { |
| public: |
| static const char *getName() { return "GetSymbolAddress"; } |
| }; |
| |
| /// Request that the host execute a compile callback. |
| class RequestCompile |
| : public rpc::Function< |
| RequestCompile, JITTargetAddress(JITTargetAddress TrampolineAddr)> { |
| public: |
| static const char *getName() { return "RequestCompile"; } |
| }; |
| |
| /// Notify the remote and terminate the session. |
| class TerminateSession : public rpc::Function<TerminateSession, void()> { |
| public: |
| static const char *getName() { return "TerminateSession"; } |
| }; |
| |
| } // namespace utils |
| |
| class OrcRemoteTargetRPCAPI |
| : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> { |
| public: |
| // FIXME: Remove constructors once MSVC supports synthesizing move-ops. |
| OrcRemoteTargetRPCAPI(rpc::RawByteChannel &C) |
| : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(C, true) {} |
| }; |
| |
| } // end namespace remote |
| |
| } // end namespace orc |
| } // end namespace llvm |
| |
| #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H |