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 = "") ResourceId(std::move (ResourceId))36 : ResourceId(std::move(ResourceId)), 37 ResourceDescription(std::move(ResourceDescription)) {} 38 convertToErrorCode()39 std::error_code convertToErrorCode() const override { 40 return orcError(OrcErrorCode::UnknownResourceHandle); 41 } 42 log(raw_ostream & OS)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; DirectBufferWriter(const char * Src,JITTargetAddress Dst,uint64_t Size)61 DirectBufferWriter(const char *Src, JITTargetAddress Dst, uint64_t Size) 62 : Src(Src), Dst(Dst), Size(Size) {} 63 getSrc()64 const char *getSrc() const { return Src; } getDst()65 JITTargetAddress getDst() const { return Dst; } getSize()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: getName()80 static const char *getName() { return "JITSymbolFlags"; } 81 }; 82 83 template <typename ChannelT> 84 class SerializationTraits<ChannelT, JITSymbolFlags> { 85 public: 86 serialize(ChannelT & C,const JITSymbolFlags & Flags)87 static Error serialize(ChannelT &C, const JITSymbolFlags &Flags) { 88 return serializeSeq(C, Flags.getRawFlagsValue(), Flags.getTargetFlags()); 89 } 90 deserialize(ChannelT & C,JITSymbolFlags & Flags)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: getName()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: serialize(ChannelT & C,const remote::DirectBufferWriter & DBW)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 deserialize(ChannelT & C,remote::DirectBufferWriter & DBW)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; ResourceIdMgr(ResourceId FirstValidId)145 explicit ResourceIdMgr(ResourceId FirstValidId) 146 : NextId(std::move(FirstValidId)) {} 147 getNext()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 release(ResourceId I)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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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. OrcRemoteTargetRPCAPI(shared::RawByteChannel & C)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