Home | History | Annotate | Line # | Download | only in Orc
      1 //===- OrcRemoteTargetRPCAPI.h - Orc Remote-target RPC API ------*- 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 // This file defines the Orc remote-target RPC API. It should not be used
     10 // directly, but is used by the RemoteTargetClient and RemoteTargetServer
     11 // classes.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H
     16 #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H
     17 
     18 #include "llvm/ExecutionEngine/JITSymbol.h"
     19 #include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h"
     20 #include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h"
     21 
     22 namespace llvm {
     23 namespace orc {
     24 
     25 namespace remote {
     26 
     27 /// Template error for missing resources.
     28 template <typename ResourceIdT>
     29 class ResourceNotFound
     30   : public ErrorInfo<ResourceNotFound<ResourceIdT>> {
     31 public:
     32   static char ID;
     33 
     34   ResourceNotFound(ResourceIdT ResourceId,
     35                    std::string ResourceDescription = "")
     36     : ResourceId(std::move(ResourceId)),
     37       ResourceDescription(std::move(ResourceDescription)) {}
     38 
     39   std::error_code convertToErrorCode() const override {
     40     return orcError(OrcErrorCode::UnknownResourceHandle);
     41   }
     42 
     43   void log(raw_ostream &OS) const override {
     44     OS << (ResourceDescription.empty()
     45              ? "Remote resource with id "
     46                : ResourceDescription)
     47        << " " << ResourceId << " not found";
     48   }
     49 
     50 private:
     51   ResourceIdT ResourceId;
     52   std::string ResourceDescription;
     53 };
     54 
     55 template <typename ResourceIdT>
     56 char ResourceNotFound<ResourceIdT>::ID = 0;
     57 
     58 class DirectBufferWriter {
     59 public:
     60   DirectBufferWriter() = default;
     61   DirectBufferWriter(const char *Src, JITTargetAddress Dst, uint64_t Size)
     62       : Src(Src), Dst(Dst), Size(Size) {}
     63 
     64   const char *getSrc() const { return Src; }
     65   JITTargetAddress getDst() const { return Dst; }
     66   uint64_t getSize() const { return Size; }
     67 
     68 private:
     69   const char *Src;
     70   JITTargetAddress Dst;
     71   uint64_t Size;
     72 };
     73 
     74 } // end namespace remote
     75 
     76 namespace shared {
     77 
     78 template <> class SerializationTypeName<JITSymbolFlags> {
     79 public:
     80   static const char *getName() { return "JITSymbolFlags"; }
     81 };
     82 
     83 template <typename ChannelT>
     84 class SerializationTraits<ChannelT, JITSymbolFlags> {
     85 public:
     86 
     87   static Error serialize(ChannelT &C, const JITSymbolFlags &Flags) {
     88     return serializeSeq(C, Flags.getRawFlagsValue(), Flags.getTargetFlags());
     89   }
     90 
     91   static Error deserialize(ChannelT &C, JITSymbolFlags &Flags) {
     92     JITSymbolFlags::UnderlyingType JITFlags;
     93     JITSymbolFlags::TargetFlagsType TargetFlags;
     94     if (auto Err = deserializeSeq(C, JITFlags, TargetFlags))
     95       return Err;
     96     Flags = JITSymbolFlags(static_cast<JITSymbolFlags::FlagNames>(JITFlags),
     97                            TargetFlags);
     98     return Error::success();
     99   }
    100 };
    101 
    102 template <> class SerializationTypeName<remote::DirectBufferWriter> {
    103 public:
    104   static const char *getName() { return "DirectBufferWriter"; }
    105 };
    106 
    107 template <typename ChannelT>
    108 class SerializationTraits<
    109     ChannelT, remote::DirectBufferWriter, remote::DirectBufferWriter,
    110     std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
    111 public:
    112   static Error serialize(ChannelT &C, const remote::DirectBufferWriter &DBW) {
    113     if (auto EC = serializeSeq(C, DBW.getDst()))
    114       return EC;
    115     if (auto EC = serializeSeq(C, DBW.getSize()))
    116       return EC;
    117     return C.appendBytes(DBW.getSrc(), DBW.getSize());
    118   }
    119 
    120   static Error deserialize(ChannelT &C, remote::DirectBufferWriter &DBW) {
    121     JITTargetAddress Dst;
    122     if (auto EC = deserializeSeq(C, Dst))
    123       return EC;
    124     uint64_t Size;
    125     if (auto EC = deserializeSeq(C, Size))
    126       return EC;
    127     char *Addr = reinterpret_cast<char *>(static_cast<uintptr_t>(Dst));
    128 
    129     DBW = remote::DirectBufferWriter(nullptr, Dst, Size);
    130 
    131     return C.readBytes(Addr, Size);
    132   }
    133 };
    134 
    135 } // end namespace shared
    136 
    137 namespace remote {
    138 
    139 class ResourceIdMgr {
    140 public:
    141   using ResourceId = uint64_t;
    142   static const ResourceId InvalidId = ~0U;
    143 
    144   ResourceIdMgr() = default;
    145   explicit ResourceIdMgr(ResourceId FirstValidId)
    146     : NextId(std::move(FirstValidId)) {}
    147 
    148   ResourceId getNext() {
    149     if (!FreeIds.empty()) {
    150       ResourceId I = FreeIds.back();
    151       FreeIds.pop_back();
    152       return I;
    153     }
    154     assert(NextId + 1 != ~0ULL && "All ids allocated");
    155     return NextId++;
    156   }
    157 
    158   void release(ResourceId I) { FreeIds.push_back(I); }
    159 
    160 private:
    161   ResourceId NextId = 1;
    162   std::vector<ResourceId> FreeIds;
    163 };
    164 
    165 /// Registers EH frames on the remote.
    166 namespace eh {
    167 
    168   /// Registers EH frames on the remote.
    169 class RegisterEHFrames
    170     : public shared::RPCFunction<RegisterEHFrames,
    171                                  void(JITTargetAddress Addr, uint32_t Size)> {
    172 public:
    173   static const char *getName() { return "RegisterEHFrames"; }
    174 };
    175 
    176   /// Deregisters EH frames on the remote.
    177 class DeregisterEHFrames
    178     : public shared::RPCFunction<DeregisterEHFrames,
    179                                  void(JITTargetAddress Addr, uint32_t Size)> {
    180 public:
    181   static const char *getName() { return "DeregisterEHFrames"; }
    182 };
    183 
    184 } // end namespace eh
    185 
    186 /// RPC functions for executing remote code.
    187 namespace exec {
    188 
    189   /// Call an 'int32_t()'-type function on the remote, returns the called
    190   /// function's return value.
    191 class CallIntVoid
    192     : public shared::RPCFunction<CallIntVoid, int32_t(JITTargetAddress Addr)> {
    193 public:
    194   static const char *getName() { return "CallIntVoid"; }
    195 };
    196 
    197   /// Call an 'int32_t(int32_t)'-type function on the remote, returns the called
    198   /// function's return value.
    199 class CallIntInt
    200     : public shared::RPCFunction<CallIntInt,
    201                                  int32_t(JITTargetAddress Addr, int)> {
    202 public:
    203   static const char *getName() { return "CallIntInt"; }
    204 };
    205 
    206   /// Call an 'int32_t(int32_t, char**)'-type function on the remote, returns the
    207   /// called function's return value.
    208 class CallMain
    209     : public shared::RPCFunction<CallMain,
    210                                  int32_t(JITTargetAddress Addr,
    211                                          std::vector<std::string> Args)> {
    212 public:
    213   static const char *getName() { return "CallMain"; }
    214 };
    215 
    216   /// Calls a 'void()'-type function on the remote, returns when the called
    217   /// function completes.
    218 class CallVoidVoid
    219     : public shared::RPCFunction<CallVoidVoid, void(JITTargetAddress FnAddr)> {
    220 public:
    221   static const char *getName() { return "CallVoidVoid"; }
    222 };
    223 
    224 } // end namespace exec
    225 
    226 /// RPC functions for remote memory management / inspection / modification.
    227 namespace mem {
    228 
    229   /// Creates a memory allocator on the remote.
    230 class CreateRemoteAllocator
    231     : public shared::RPCFunction<CreateRemoteAllocator,
    232                                  void(ResourceIdMgr::ResourceId AllocatorID)> {
    233 public:
    234   static const char *getName() { return "CreateRemoteAllocator"; }
    235 };
    236 
    237   /// Destroys a remote allocator, freeing any memory allocated by it.
    238 class DestroyRemoteAllocator
    239     : public shared::RPCFunction<DestroyRemoteAllocator,
    240                                  void(ResourceIdMgr::ResourceId AllocatorID)> {
    241 public:
    242   static const char *getName() { return "DestroyRemoteAllocator"; }
    243 };
    244 
    245   /// Read a remote memory block.
    246 class ReadMem
    247     : public shared::RPCFunction<
    248           ReadMem, std::vector<uint8_t>(JITTargetAddress Src, uint64_t Size)> {
    249 public:
    250   static const char *getName() { return "ReadMem"; }
    251 };
    252 
    253   /// Reserve a block of memory on the remote via the given allocator.
    254 class ReserveMem
    255     : public shared::RPCFunction<
    256           ReserveMem, JITTargetAddress(ResourceIdMgr::ResourceId AllocID,
    257                                        uint64_t Size, uint32_t Align)> {
    258 public:
    259   static const char *getName() { return "ReserveMem"; }
    260 };
    261 
    262   /// Set the memory protection on a memory block.
    263 class SetProtections
    264     : public shared::RPCFunction<
    265           SetProtections, void(ResourceIdMgr::ResourceId AllocID,
    266                                JITTargetAddress Dst, uint32_t ProtFlags)> {
    267 public:
    268   static const char *getName() { return "SetProtections"; }
    269 };
    270 
    271   /// Write to a remote memory block.
    272 class WriteMem
    273     : public shared::RPCFunction<WriteMem,
    274                                  void(remote::DirectBufferWriter DB)> {
    275 public:
    276   static const char *getName() { return "WriteMem"; }
    277 };
    278 
    279   /// Write to a remote pointer.
    280 class WritePtr
    281     : public shared::RPCFunction<WritePtr, void(JITTargetAddress Dst,
    282                                                 JITTargetAddress Val)> {
    283 public:
    284   static const char *getName() { return "WritePtr"; }
    285 };
    286 
    287 } // end namespace mem
    288 
    289 /// RPC functions for remote stub and trampoline management.
    290 namespace stubs {
    291 
    292   /// Creates an indirect stub owner on the remote.
    293 class CreateIndirectStubsOwner
    294     : public shared::RPCFunction<CreateIndirectStubsOwner,
    295                                  void(ResourceIdMgr::ResourceId StubOwnerID)> {
    296 public:
    297   static const char *getName() { return "CreateIndirectStubsOwner"; }
    298 };
    299 
    300   /// RPC function for destroying an indirect stubs owner.
    301 class DestroyIndirectStubsOwner
    302     : public shared::RPCFunction<DestroyIndirectStubsOwner,
    303                                  void(ResourceIdMgr::ResourceId StubsOwnerID)> {
    304 public:
    305   static const char *getName() { return "DestroyIndirectStubsOwner"; }
    306 };
    307 
    308   /// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted).
    309 class EmitIndirectStubs
    310     : public shared::RPCFunction<
    311           EmitIndirectStubs,
    312           std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>(
    313               ResourceIdMgr::ResourceId StubsOwnerID,
    314               uint32_t NumStubsRequired)> {
    315 public:
    316   static const char *getName() { return "EmitIndirectStubs"; }
    317 };
    318 
    319   /// RPC function to emit the resolver block and return its address.
    320 class EmitResolverBlock
    321     : public shared::RPCFunction<EmitResolverBlock, void()> {
    322 public:
    323   static const char *getName() { return "EmitResolverBlock"; }
    324 };
    325 
    326   /// EmitTrampolineBlock result is (BlockAddr, NumTrampolines).
    327 class EmitTrampolineBlock
    328     : public shared::RPCFunction<EmitTrampolineBlock,
    329                                  std::tuple<JITTargetAddress, uint32_t>()> {
    330 public:
    331   static const char *getName() { return "EmitTrampolineBlock"; }
    332 };
    333 
    334 } // end namespace stubs
    335 
    336 /// Miscelaneous RPC functions for dealing with remotes.
    337 namespace utils {
    338 
    339   /// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize,
    340   ///                          IndirectStubsSize).
    341 class GetRemoteInfo
    342     : public shared::RPCFunction<
    343           GetRemoteInfo,
    344           std::tuple<std::string, uint32_t, uint32_t, uint32_t, uint32_t>()> {
    345 public:
    346   static const char *getName() { return "GetRemoteInfo"; }
    347 };
    348 
    349   /// Get the address of a remote symbol.
    350 class GetSymbolAddress
    351     : public shared::RPCFunction<GetSymbolAddress,
    352                                  JITTargetAddress(std::string SymbolName)> {
    353 public:
    354   static const char *getName() { return "GetSymbolAddress"; }
    355 };
    356 
    357   /// Request that the host execute a compile callback.
    358 class RequestCompile
    359     : public shared::RPCFunction<
    360           RequestCompile, JITTargetAddress(JITTargetAddress TrampolineAddr)> {
    361 public:
    362   static const char *getName() { return "RequestCompile"; }
    363 };
    364 
    365   /// Notify the remote and terminate the session.
    366 class TerminateSession : public shared::RPCFunction<TerminateSession, void()> {
    367 public:
    368   static const char *getName() { return "TerminateSession"; }
    369 };
    370 
    371 } // namespace utils
    372 
    373 class OrcRemoteTargetRPCAPI
    374     : public shared::SingleThreadedRPCEndpoint<shared::RawByteChannel> {
    375 public:
    376   // FIXME: Remove constructors once MSVC supports synthesizing move-ops.
    377   OrcRemoteTargetRPCAPI(shared::RawByteChannel &C)
    378       : shared::SingleThreadedRPCEndpoint<shared::RawByteChannel>(C, true) {}
    379 };
    380 
    381 } // end namespace remote
    382 
    383 } // end namespace orc
    384 } // end namespace llvm
    385 
    386 #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H
    387