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
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 shared {
77
78template <> class SerializationTypeName<JITSymbolFlags> {
79public:
80 static const char *getName() { return "JITSymbolFlags"; }
81};
82
83template <typename ChannelT>
84class SerializationTraits<ChannelT, JITSymbolFlags> {
85public:
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
102template <> class SerializationTypeName<remote::DirectBufferWriter> {
103public:
104 static const char *getName() { return "DirectBufferWriter"; }
105};
106
107template <typename ChannelT>
108class SerializationTraits<
109 ChannelT, remote::DirectBufferWriter, remote::DirectBufferWriter,
110 std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
111public:
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
137namespace remote {
138
139class ResourceIdMgr {
140public:
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
160private:
161 ResourceId NextId = 1;
162 std::vector<ResourceId> FreeIds;
163};
164
165/// Registers EH frames on the remote.
166namespace eh {
167
168 /// Registers EH frames on the remote.
169class RegisterEHFrames
170 : public shared::RPCFunction<RegisterEHFrames,
171 void(JITTargetAddress Addr, uint32_t Size)> {
172public:
173 static const char *getName() { return "RegisterEHFrames"; }
174};
175
176 /// Deregisters EH frames on the remote.
177class DeregisterEHFrames
178 : public shared::RPCFunction<DeregisterEHFrames,
179 void(JITTargetAddress Addr, uint32_t Size)> {
180public:
181 static const char *getName() { return "DeregisterEHFrames"; }
182};
183
184} // end namespace eh
185
186/// RPC functions for executing remote code.
187namespace exec {
188
189 /// Call an 'int32_t()'-type function on the remote, returns the called
190 /// function's return value.
191class CallIntVoid
192 : public shared::RPCFunction<CallIntVoid, int32_t(JITTargetAddress Addr)> {
193public:
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.
199class CallIntInt
200 : public shared::RPCFunction<CallIntInt,
201 int32_t(JITTargetAddress Addr, int)> {
202public:
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.
208class CallMain
209 : public shared::RPCFunction<CallMain,
210 int32_t(JITTargetAddress Addr,
211 std::vector<std::string> Args)> {
212public:
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.
218class CallVoidVoid
219 : public shared::RPCFunction<CallVoidVoid, void(JITTargetAddress FnAddr)> {
220public:
221 static const char *getName() { return "CallVoidVoid"; }
222};
223
224} // end namespace exec
225
226/// RPC functions for remote memory management / inspection / modification.
227namespace mem {
228
229 /// Creates a memory allocator on the remote.
230class CreateRemoteAllocator
231 : public shared::RPCFunction<CreateRemoteAllocator,
232 void(ResourceIdMgr::ResourceId AllocatorID)> {
233public:
234 static const char *getName() { return "CreateRemoteAllocator"; }
235};
236
237 /// Destroys a remote allocator, freeing any memory allocated by it.
238class DestroyRemoteAllocator
239 : public shared::RPCFunction<DestroyRemoteAllocator,
240 void(ResourceIdMgr::ResourceId AllocatorID)> {
241public:
242 static const char *getName() { return "DestroyRemoteAllocator"; }
243};
244
245 /// Read a remote memory block.
246class ReadMem
247 : public shared::RPCFunction<
248 ReadMem, std::vector<uint8_t>(JITTargetAddress Src, uint64_t Size)> {
249public:
250 static const char *getName() { return "ReadMem"; }
251};
252
253 /// Reserve a block of memory on the remote via the given allocator.
254class ReserveMem
255 : public shared::RPCFunction<
256 ReserveMem, JITTargetAddress(ResourceIdMgr::ResourceId AllocID,
257 uint64_t Size, uint32_t Align)> {
258public:
259 static const char *getName() { return "ReserveMem"; }
260};
261
262 /// Set the memory protection on a memory block.
263class SetProtections
264 : public shared::RPCFunction<
265 SetProtections, void(ResourceIdMgr::ResourceId AllocID,
266 JITTargetAddress Dst, uint32_t ProtFlags)> {
267public:
268 static const char *getName() { return "SetProtections"; }
269};
270
271 /// Write to a remote memory block.
272class WriteMem
273 : public shared::RPCFunction<WriteMem,
274 void(remote::DirectBufferWriter DB)> {
275public:
276 static const char *getName() { return "WriteMem"; }
277};
278
279 /// Write to a remote pointer.
280class WritePtr
281 : public shared::RPCFunction<WritePtr, void(JITTargetAddress Dst,
282 JITTargetAddress Val)> {
283public:
284 static const char *getName() { return "WritePtr"; }
285};
286
287} // end namespace mem
288
289/// RPC functions for remote stub and trampoline management.
290namespace stubs {
291
292 /// Creates an indirect stub owner on the remote.
293class CreateIndirectStubsOwner
294 : public shared::RPCFunction<CreateIndirectStubsOwner,
295 void(ResourceIdMgr::ResourceId StubOwnerID)> {
296public:
297 static const char *getName() { return "CreateIndirectStubsOwner"; }
298};
299
300 /// RPC function for destroying an indirect stubs owner.
301class DestroyIndirectStubsOwner
302 : public shared::RPCFunction<DestroyIndirectStubsOwner,
303 void(ResourceIdMgr::ResourceId StubsOwnerID)> {
304public:
305 static const char *getName() { return "DestroyIndirectStubsOwner"; }
306};
307
308 /// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted).
309class EmitIndirectStubs
310 : public shared::RPCFunction<
311 EmitIndirectStubs,
312 std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>(
313 ResourceIdMgr::ResourceId StubsOwnerID,
314 uint32_t NumStubsRequired)> {
315public:
316 static const char *getName() { return "EmitIndirectStubs"; }
317};
318
319 /// RPC function to emit the resolver block and return its address.
320class EmitResolverBlock
321 : public shared::RPCFunction<EmitResolverBlock, void()> {
322public:
323 static const char *getName() { return "EmitResolverBlock"; }
324};
325
326 /// EmitTrampolineBlock result is (BlockAddr, NumTrampolines).
327class EmitTrampolineBlock
328 : public shared::RPCFunction<EmitTrampolineBlock,
329 std::tuple<JITTargetAddress, uint32_t>()> {
330public:
331 static const char *getName() { return "EmitTrampolineBlock"; }
332};
333
334} // end namespace stubs
335
336/// Miscelaneous RPC functions for dealing with remotes.
337namespace utils {
338
339 /// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize,
340 /// IndirectStubsSize).
341class GetRemoteInfo
342 : public shared::RPCFunction<
343 GetRemoteInfo,
344 std::tuple<std::string, uint32_t, uint32_t, uint32_t, uint32_t>()> {
345public:
346 static const char *getName() { return "GetRemoteInfo"; }
347};
348
349 /// Get the address of a remote symbol.
350class GetSymbolAddress
351 : public shared::RPCFunction<GetSymbolAddress,
352 JITTargetAddress(std::string SymbolName)> {
353public:
354 static const char *getName() { return "GetSymbolAddress"; }
355};
356
357 /// Request that the host execute a compile callback.
358class RequestCompile
359 : public shared::RPCFunction<
360 RequestCompile, JITTargetAddress(JITTargetAddress TrampolineAddr)> {
361public:
362 static const char *getName() { return "RequestCompile"; }
363};
364
365 /// Notify the remote and terminate the session.
366class TerminateSession : public shared::RPCFunction<TerminateSession, void()> {
367public:
368 static const char *getName() { return "TerminateSession"; }
369};
370
371} // namespace utils
372
373class OrcRemoteTargetRPCAPI
374 : public shared::SingleThreadedRPCEndpoint<shared::RawByteChannel> {
375public:
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