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 std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> { 112 public: serialize(ChannelT & C,const remote::DirectBufferWriter & DBW)113 static Error serialize(ChannelT &C, const remote::DirectBufferWriter &DBW) { 114 if (auto EC = serializeSeq(C, DBW.getDst())) 115 return EC; 116 if (auto EC = serializeSeq(C, DBW.getSize())) 117 return EC; 118 return C.appendBytes(DBW.getSrc(), DBW.getSize()); 119 } 120 deserialize(ChannelT & C,remote::DirectBufferWriter & DBW)121 static Error deserialize(ChannelT &C, remote::DirectBufferWriter &DBW) { 122 JITTargetAddress Dst; 123 if (auto EC = deserializeSeq(C, Dst)) 124 return EC; 125 uint64_t Size; 126 if (auto EC = deserializeSeq(C, Size)) 127 return EC; 128 char *Addr = reinterpret_cast<char *>(static_cast<uintptr_t>(Dst)); 129 130 DBW = remote::DirectBufferWriter(nullptr, Dst, Size); 131 132 return C.readBytes(Addr, Size); 133 } 134 }; 135 136 } // end namespace rpc 137 138 namespace remote { 139 140 class ResourceIdMgr { 141 public: 142 using ResourceId = uint64_t; 143 static const ResourceId InvalidId = ~0U; 144 145 ResourceIdMgr() = default; ResourceIdMgr(ResourceId FirstValidId)146 explicit ResourceIdMgr(ResourceId FirstValidId) 147 : NextId(std::move(FirstValidId)) {} 148 getNext()149 ResourceId getNext() { 150 if (!FreeIds.empty()) { 151 ResourceId I = FreeIds.back(); 152 FreeIds.pop_back(); 153 return I; 154 } 155 assert(NextId + 1 != ~0ULL && "All ids allocated"); 156 return NextId++; 157 } 158 release(ResourceId I)159 void release(ResourceId I) { FreeIds.push_back(I); } 160 161 private: 162 ResourceId NextId = 1; 163 std::vector<ResourceId> FreeIds; 164 }; 165 166 /// Registers EH frames on the remote. 167 namespace eh { 168 169 /// Registers EH frames on the remote. 170 class RegisterEHFrames 171 : public rpc::Function<RegisterEHFrames, 172 void(JITTargetAddress Addr, uint32_t Size)> { 173 public: getName()174 static const char *getName() { return "RegisterEHFrames"; } 175 }; 176 177 /// Deregisters EH frames on the remote. 178 class DeregisterEHFrames 179 : public rpc::Function<DeregisterEHFrames, 180 void(JITTargetAddress Addr, uint32_t Size)> { 181 public: getName()182 static const char *getName() { return "DeregisterEHFrames"; } 183 }; 184 185 } // end namespace eh 186 187 /// RPC functions for executing remote code. 188 namespace exec { 189 190 /// Call an 'int32_t()'-type function on the remote, returns the called 191 /// function's return value. 192 class CallIntVoid 193 : public rpc::Function<CallIntVoid, int32_t(JITTargetAddress Addr)> { 194 public: getName()195 static const char *getName() { return "CallIntVoid"; } 196 }; 197 198 /// Call an 'int32_t(int32_t, char**)'-type function on the remote, returns the 199 /// called function's return value. 200 class CallMain 201 : public rpc::Function<CallMain, int32_t(JITTargetAddress Addr, 202 std::vector<std::string> Args)> { 203 public: getName()204 static const char *getName() { return "CallMain"; } 205 }; 206 207 /// Calls a 'void()'-type function on the remote, returns when the called 208 /// function completes. 209 class CallVoidVoid 210 : public rpc::Function<CallVoidVoid, void(JITTargetAddress FnAddr)> { 211 public: getName()212 static const char *getName() { return "CallVoidVoid"; } 213 }; 214 215 } // end namespace exec 216 217 /// RPC functions for remote memory management / inspection / modification. 218 namespace mem { 219 220 /// Creates a memory allocator on the remote. 221 class CreateRemoteAllocator 222 : public rpc::Function<CreateRemoteAllocator, 223 void(ResourceIdMgr::ResourceId AllocatorID)> { 224 public: getName()225 static const char *getName() { return "CreateRemoteAllocator"; } 226 }; 227 228 /// Destroys a remote allocator, freeing any memory allocated by it. 229 class DestroyRemoteAllocator 230 : public rpc::Function<DestroyRemoteAllocator, 231 void(ResourceIdMgr::ResourceId AllocatorID)> { 232 public: getName()233 static const char *getName() { return "DestroyRemoteAllocator"; } 234 }; 235 236 /// Read a remote memory block. 237 class ReadMem 238 : public rpc::Function<ReadMem, std::vector<uint8_t>(JITTargetAddress Src, 239 uint64_t Size)> { 240 public: getName()241 static const char *getName() { return "ReadMem"; } 242 }; 243 244 /// Reserve a block of memory on the remote via the given allocator. 245 class ReserveMem 246 : public rpc::Function<ReserveMem, 247 JITTargetAddress(ResourceIdMgr::ResourceId AllocID, 248 uint64_t Size, uint32_t Align)> { 249 public: getName()250 static const char *getName() { return "ReserveMem"; } 251 }; 252 253 /// Set the memory protection on a memory block. 254 class SetProtections 255 : public rpc::Function<SetProtections, 256 void(ResourceIdMgr::ResourceId AllocID, 257 JITTargetAddress Dst, uint32_t ProtFlags)> { 258 public: getName()259 static const char *getName() { return "SetProtections"; } 260 }; 261 262 /// Write to a remote memory block. 263 class WriteMem 264 : public rpc::Function<WriteMem, void(remote::DirectBufferWriter DB)> { 265 public: getName()266 static const char *getName() { return "WriteMem"; } 267 }; 268 269 /// Write to a remote pointer. 270 class WritePtr : public rpc::Function<WritePtr, void(JITTargetAddress Dst, 271 JITTargetAddress Val)> { 272 public: getName()273 static const char *getName() { return "WritePtr"; } 274 }; 275 276 } // end namespace mem 277 278 /// RPC functions for remote stub and trampoline management. 279 namespace stubs { 280 281 /// Creates an indirect stub owner on the remote. 282 class CreateIndirectStubsOwner 283 : public rpc::Function<CreateIndirectStubsOwner, 284 void(ResourceIdMgr::ResourceId StubOwnerID)> { 285 public: getName()286 static const char *getName() { return "CreateIndirectStubsOwner"; } 287 }; 288 289 /// RPC function for destroying an indirect stubs owner. 290 class DestroyIndirectStubsOwner 291 : public rpc::Function<DestroyIndirectStubsOwner, 292 void(ResourceIdMgr::ResourceId StubsOwnerID)> { 293 public: getName()294 static const char *getName() { return "DestroyIndirectStubsOwner"; } 295 }; 296 297 /// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted). 298 class EmitIndirectStubs 299 : public rpc::Function< 300 EmitIndirectStubs, 301 std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>( 302 ResourceIdMgr::ResourceId StubsOwnerID, 303 uint32_t NumStubsRequired)> { 304 public: getName()305 static const char *getName() { return "EmitIndirectStubs"; } 306 }; 307 308 /// RPC function to emit the resolver block and return its address. 309 class EmitResolverBlock : public rpc::Function<EmitResolverBlock, void()> { 310 public: getName()311 static const char *getName() { return "EmitResolverBlock"; } 312 }; 313 314 /// EmitTrampolineBlock result is (BlockAddr, NumTrampolines). 315 class EmitTrampolineBlock 316 : public rpc::Function<EmitTrampolineBlock, 317 std::tuple<JITTargetAddress, uint32_t>()> { 318 public: getName()319 static const char *getName() { return "EmitTrampolineBlock"; } 320 }; 321 322 } // end namespace stubs 323 324 /// Miscelaneous RPC functions for dealing with remotes. 325 namespace utils { 326 327 /// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize, 328 /// IndirectStubsSize). 329 class GetRemoteInfo 330 : public rpc::Function< 331 GetRemoteInfo, 332 std::tuple<std::string, uint32_t, uint32_t, uint32_t, uint32_t>()> { 333 public: getName()334 static const char *getName() { return "GetRemoteInfo"; } 335 }; 336 337 /// Get the address of a remote symbol. 338 class GetSymbolAddress 339 : public rpc::Function<GetSymbolAddress, 340 JITTargetAddress(std::string SymbolName)> { 341 public: getName()342 static const char *getName() { return "GetSymbolAddress"; } 343 }; 344 345 /// Request that the host execute a compile callback. 346 class RequestCompile 347 : public rpc::Function< 348 RequestCompile, JITTargetAddress(JITTargetAddress TrampolineAddr)> { 349 public: getName()350 static const char *getName() { return "RequestCompile"; } 351 }; 352 353 /// Notify the remote and terminate the session. 354 class TerminateSession : public rpc::Function<TerminateSession, void()> { 355 public: getName()356 static const char *getName() { return "TerminateSession"; } 357 }; 358 359 } // namespace utils 360 361 class OrcRemoteTargetRPCAPI 362 : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> { 363 public: 364 // FIXME: Remove constructors once MSVC supports synthesizing move-ops. OrcRemoteTargetRPCAPI(rpc::RawByteChannel & C)365 OrcRemoteTargetRPCAPI(rpc::RawByteChannel &C) 366 : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(C, true) {} 367 }; 368 369 } // end namespace remote 370 371 } // end namespace orc 372 } // end namespace llvm 373 374 #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H 375