//===- OrcRemoteTargetRPCAPI.h - Orc Remote-target RPC API ------*- 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 // //===----------------------------------------------------------------------===// // // 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/RPC/RPCUtils.h" #include "llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h" namespace llvm { namespace orc { namespace remote { /// Template error for missing resources. template class ResourceNotFound : public ErrorInfo> { 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 char ResourceNotFound::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 { public: static const char *getName() { return "JITSymbolFlags"; } }; template class SerializationTraits { public: static Error serialize(ChannelT &C, const JITSymbolFlags &Flags) { return serializeSeq(C, Flags.getRawFlagsValue(), 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(JITFlags), TargetFlags); return Error::success(); } }; template <> class RPCTypeName { public: static const char *getName() { return "DirectBufferWriter"; } }; template class SerializationTraits< ChannelT, remote::DirectBufferWriter, remote::DirectBufferWriter, std::enable_if_t::value>> { 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(static_cast(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 FreeIds; }; /// Registers EH frames on the remote. namespace eh { /// Registers EH frames on the remote. class RegisterEHFrames : public rpc::Function { public: static const char *getName() { return "RegisterEHFrames"; } }; /// Deregisters EH frames on the remote. class DeregisterEHFrames : public rpc::Function { 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 { 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 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 { 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 { public: static const char *getName() { return "CreateRemoteAllocator"; } }; /// Destroys a remote allocator, freeing any memory allocated by it. class DestroyRemoteAllocator : public rpc::Function { public: static const char *getName() { return "DestroyRemoteAllocator"; } }; /// Read a remote memory block. class ReadMem : public rpc::Function(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 { public: static const char *getName() { return "ReserveMem"; } }; /// Set the memory protection on a memory block. class SetProtections : public rpc::Function { public: static const char *getName() { return "SetProtections"; } }; /// Write to a remote memory block. class WriteMem : public rpc::Function { public: static const char *getName() { return "WriteMem"; } }; /// Write to a remote pointer. class WritePtr : public rpc::Function { 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 { public: static const char *getName() { return "CreateIndirectStubsOwner"; } }; /// RPC function for destroying an indirect stubs owner. class DestroyIndirectStubsOwner : public rpc::Function { public: static const char *getName() { return "DestroyIndirectStubsOwner"; } }; /// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted). class EmitIndirectStubs : public rpc::Function< EmitIndirectStubs, std::tuple( 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 { public: static const char *getName() { return "EmitResolverBlock"; } }; /// EmitTrampolineBlock result is (BlockAddr, NumTrampolines). class EmitTrampolineBlock : public rpc::Function()> { 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()> { public: static const char *getName() { return "GetRemoteInfo"; } }; /// Get the address of a remote symbol. class GetSymbolAddress : public rpc::Function { 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 { public: static const char *getName() { return "TerminateSession"; } }; } // namespace utils class OrcRemoteTargetRPCAPI : public rpc::SingleThreadedRPCEndpoint { public: // FIXME: Remove constructors once MSVC supports synthesizing move-ops. OrcRemoteTargetRPCAPI(rpc::RawByteChannel &C) : rpc::SingleThreadedRPCEndpoint(C, true) {} }; } // end namespace remote } // end namespace orc } // end namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H