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