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