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