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 23namespace llvm { 24namespace orc { 25 26namespace remote { 27 28/// Template error for missing resources. 29template <typename ResourceIdT> 30class ResourceNotFound 31 : public ErrorInfo<ResourceNotFound<ResourceIdT>> { 32public: 33 static char ID; 34 35 ResourceNotFound(ResourceIdT ResourceId, 36 std::string ResourceDescription = "") 37 : ResourceId(std::move(ResourceId)), 38 ResourceDescription(std::move(ResourceDescription)) {} 39 40 std::error_code convertToErrorCode() const override { 41 return orcError(OrcErrorCode::UnknownResourceHandle); 42 } 43 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 51private: 52 ResourceIdT ResourceId; 53 std::string ResourceDescription; 54}; 55 56template <typename ResourceIdT> 57char ResourceNotFound<ResourceIdT>::ID = 0; 58 59class DirectBufferWriter { 60public: 61 DirectBufferWriter() = default; 62 DirectBufferWriter(const char *Src, JITTargetAddress Dst, uint64_t Size) 63 : Src(Src), Dst(Dst), Size(Size) {} 64 65 const char *getSrc() const { return Src; } 66 JITTargetAddress getDst() const { return Dst; } 67 uint64_t getSize() const { return Size; } 68 69private: 70 const char *Src; 71 JITTargetAddress Dst; 72 uint64_t Size; 73}; 74 75} // end namespace remote 76 77namespace rpc { 78 79template <> 80class RPCTypeName<JITSymbolFlags> { 81public: 82 static const char *getName() { return "JITSymbolFlags"; } 83}; 84 85template <typename ChannelT> 86class SerializationTraits<ChannelT, JITSymbolFlags> { 87public: 88 89 static Error serialize(ChannelT &C, const JITSymbolFlags &Flags) { 90 return serializeSeq(C, static_cast<JITSymbolFlags::UnderlyingType>(Flags), 91 Flags.getTargetFlags()); 92 } 93 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 105template <> class RPCTypeName<remote::DirectBufferWriter> { 106public: 107 static const char *getName() { return "DirectBufferWriter"; } 108}; 109 110template <typename ChannelT> 111class SerializationTraits< 112 ChannelT, remote::DirectBufferWriter, remote::DirectBufferWriter, 113 typename std::enable_if< 114 std::is_base_of<RawByteChannel, ChannelT>::value>::type> { 115public: 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 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 141namespace remote { 142 143class ResourceIdMgr { 144public: 145 using ResourceId = uint64_t; 146 static const ResourceId InvalidId = ~0U; 147 148 ResourceIdMgr() = default; 149 explicit ResourceIdMgr(ResourceId FirstValidId) 150 : NextId(std::move(FirstValidId)) {} 151 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 162 void release(ResourceId I) { FreeIds.push_back(I); } 163 164private: 165 ResourceId NextId = 1; 166 std::vector<ResourceId> FreeIds; 167}; 168 169/// Registers EH frames on the remote. 170namespace 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: 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: 185 static const char *getName() { return "DeregisterEHFrames"; } 186 }; 187 188} // end namespace eh 189 190/// RPC functions for executing remote code. 191namespace 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: 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: 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: 215 static const char *getName() { return "CallVoidVoid"; } 216 }; 217 218} // end namespace exec 219 220/// RPC functions for remote memory management / inspection / modification. 221namespace 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: 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: 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: 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: 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: 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: 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: 276 static const char *getName() { return "WritePtr"; } 277 }; 278 279} // end namespace mem 280 281/// RPC functions for remote stub and trampoline management. 282namespace 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: 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: 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: 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: 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: 322 static const char *getName() { return "EmitTrampolineBlock"; } 323 }; 324 325} // end namespace stubs 326 327/// Miscelaneous RPC functions for dealing with remotes. 328namespace 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: 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: 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: 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: 359 static const char *getName() { return "TerminateSession"; } 360 }; 361 362} // namespace utils 363 364class OrcRemoteTargetRPCAPI 365 : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> { 366public: 367 // FIXME: Remove constructors once MSVC supports synthesizing move-ops. 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