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 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 rpc { 77 78 template <> 79 class RPCTypeName<JITSymbolFlags> { 80 public: getName()81 static const char *getName() { return "JITSymbolFlags"; } 82 }; 83 84 template <typename ChannelT> 85 class SerializationTraits<ChannelT, JITSymbolFlags> { 86 public: 87 serialize(ChannelT & C,const JITSymbolFlags & Flags)88 static Error serialize(ChannelT &C, const JITSymbolFlags &Flags) { 89 return serializeSeq(C, Flags.getRawFlagsValue(), Flags.getTargetFlags()); 90 } 91 deserialize(ChannelT & C,JITSymbolFlags & Flags)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 103 template <> class RPCTypeName<remote::DirectBufferWriter> { 104 public: getName()105 static const char *getName() { return "DirectBufferWriter"; } 106 }; 107 108 template <typename ChannelT> 109 class SerializationTraits< 110 ChannelT, remote::DirectBufferWriter, remote::DirectBufferWriter, 111 typename std::enable_if< 112 std::is_base_of<RawByteChannel, ChannelT>::value>::type> { 113 public: serialize(ChannelT & C,const remote::DirectBufferWriter & DBW)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 deserialize(ChannelT & C,remote::DirectBufferWriter & DBW)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 139 namespace remote { 140 141 class ResourceIdMgr { 142 public: 143 using ResourceId = uint64_t; 144 static const ResourceId InvalidId = ~0U; 145 146 ResourceIdMgr() = default; ResourceIdMgr(ResourceId FirstValidId)147 explicit ResourceIdMgr(ResourceId FirstValidId) 148 : NextId(std::move(FirstValidId)) {} 149 getNext()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 release(ResourceId I)160 void release(ResourceId I) { FreeIds.push_back(I); } 161 162 private: 163 ResourceId NextId = 1; 164 std::vector<ResourceId> FreeIds; 165 }; 166 167 /// Registers EH frames on the remote. 168 namespace 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: getName()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: getName()183 static const char *getName() { return "DeregisterEHFrames"; } 184 }; 185 186 } // end namespace eh 187 188 /// RPC functions for executing remote code. 189 namespace 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: getName()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: getName()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: getName()213 static const char *getName() { return "CallVoidVoid"; } 214 }; 215 216 } // end namespace exec 217 218 /// RPC functions for remote memory management / inspection / modification. 219 namespace 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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()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: getName()274 static const char *getName() { return "WritePtr"; } 275 }; 276 277 } // end namespace mem 278 279 /// RPC functions for remote stub and trampoline management. 280 namespace 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: getName()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: getName()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: getName()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: getName()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: getName()320 static const char *getName() { return "EmitTrampolineBlock"; } 321 }; 322 323 } // end namespace stubs 324 325 /// Miscelaneous RPC functions for dealing with remotes. 326 namespace 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: getName()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: getName()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: getName()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: getName()357 static const char *getName() { return "TerminateSession"; } 358 }; 359 360 } // namespace utils 361 362 class OrcRemoteTargetRPCAPI 363 : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> { 364 public: 365 // FIXME: Remove constructors once MSVC supports synthesizing move-ops. OrcRemoteTargetRPCAPI(rpc::RawByteChannel & C)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