1 //===- 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 
23 namespace llvm {
24 namespace orc {
25 
26 namespace remote {
27 
28 /// Template error for missing resources.
29 template <typename ResourceIdT>
30 class ResourceNotFound
31   : public ErrorInfo<ResourceNotFound<ResourceIdT>> {
32 public:
33   static char ID;
34 
35   ResourceNotFound(ResourceIdT ResourceId,
36                    std::string ResourceDescription = "")
ResourceId(std::move (ResourceId))37     : ResourceId(std::move(ResourceId)),
38       ResourceDescription(std::move(ResourceDescription)) {}
39 
convertToErrorCode()40   std::error_code convertToErrorCode() const override {
41     return orcError(OrcErrorCode::UnknownResourceHandle);
42   }
43 
log(raw_ostream & OS)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 
51 private:
52   ResourceIdT ResourceId;
53   std::string ResourceDescription;
54 };
55 
56 template <typename ResourceIdT>
57 char ResourceNotFound<ResourceIdT>::ID = 0;
58 
59 class DirectBufferWriter {
60 public:
61   DirectBufferWriter() = default;
DirectBufferWriter(const char * Src,JITTargetAddress Dst,uint64_t Size)62   DirectBufferWriter(const char *Src, JITTargetAddress Dst, uint64_t Size)
63       : Src(Src), Dst(Dst), Size(Size) {}
64 
getSrc()65   const char *getSrc() const { return Src; }
getDst()66   JITTargetAddress getDst() const { return Dst; }
getSize()67   uint64_t getSize() const { return Size; }
68 
69 private:
70   const char *Src;
71   JITTargetAddress Dst;
72   uint64_t Size;
73 };
74 
75 } // end namespace remote
76 
77 namespace rpc {
78 
79 template <>
80 class RPCTypeName<JITSymbolFlags> {
81 public:
getName()82   static const char *getName() { return "JITSymbolFlags"; }
83 };
84 
85 template <typename ChannelT>
86 class SerializationTraits<ChannelT, JITSymbolFlags> {
87 public:
88 
serialize(ChannelT & C,const JITSymbolFlags & Flags)89   static Error serialize(ChannelT &C, const JITSymbolFlags &Flags) {
90     return serializeSeq(C, Flags.getRawFlagsValue(), Flags.getTargetFlags());
91   }
92 
deserialize(ChannelT & C,JITSymbolFlags & Flags)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 
104 template <> class RPCTypeName<remote::DirectBufferWriter> {
105 public:
getName()106   static const char *getName() { return "DirectBufferWriter"; }
107 };
108 
109 template <typename ChannelT>
110 class SerializationTraits<
111     ChannelT, remote::DirectBufferWriter, remote::DirectBufferWriter,
112     typename std::enable_if<
113         std::is_base_of<RawByteChannel, ChannelT>::value>::type> {
114 public:
serialize(ChannelT & C,const remote::DirectBufferWriter & DBW)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 
deserialize(ChannelT & C,remote::DirectBufferWriter & DBW)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 
140 namespace remote {
141 
142 class ResourceIdMgr {
143 public:
144   using ResourceId = uint64_t;
145   static const ResourceId InvalidId = ~0U;
146 
147   ResourceIdMgr() = default;
ResourceIdMgr(ResourceId FirstValidId)148   explicit ResourceIdMgr(ResourceId FirstValidId)
149     : NextId(std::move(FirstValidId)) {}
150 
getNext()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 
release(ResourceId I)161   void release(ResourceId I) { FreeIds.push_back(I); }
162 
163 private:
164   ResourceId NextId = 1;
165   std::vector<ResourceId> FreeIds;
166 };
167 
168 /// Registers EH frames on the remote.
169 namespace 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:
getName()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:
getName()184     static const char *getName() { return "DeregisterEHFrames"; }
185   };
186 
187 } // end namespace eh
188 
189 /// RPC functions for executing remote code.
190 namespace 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:
getName()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:
getName()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:
getName()214     static const char *getName() { return "CallVoidVoid"; }
215   };
216 
217 } // end namespace exec
218 
219 /// RPC functions for remote memory management / inspection / modification.
220 namespace 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:
getName()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:
getName()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:
getName()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:
getName()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:
getName()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:
getName()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:
getName()275     static const char *getName() { return "WritePtr"; }
276   };
277 
278 } // end namespace mem
279 
280 /// RPC functions for remote stub and trampoline management.
281 namespace 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:
getName()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:
getName()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:
getName()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:
getName()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:
getName()321     static const char *getName() { return "EmitTrampolineBlock"; }
322   };
323 
324 } // end namespace stubs
325 
326 /// Miscelaneous RPC functions for dealing with remotes.
327 namespace 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:
getName()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:
getName()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:
getName()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:
getName()358     static const char *getName() { return "TerminateSession"; }
359   };
360 
361 } // namespace utils
362 
363 class OrcRemoteTargetRPCAPI
364     : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
365 public:
366   // FIXME: Remove constructors once MSVC supports synthesizing move-ops.
OrcRemoteTargetRPCAPI(rpc::RawByteChannel & C)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
377