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