1 //===- OrcRemoteTargetClient.h - Orc Remote-target Client -------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the OrcRemoteTargetClient class and helpers. This class
11 // can be used to communicate over an RawByteChannel with an
12 // OrcRemoteTargetServer instance to support remote-JITing.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
17 #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
19 #include "llvm/ADT/Optional.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/StringMap.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/ExecutionEngine/JITSymbol.h"
24 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
25 #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h"
26 #include "llvm/ExecutionEngine/RuntimeDyld.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/Error.h"
29 #include "llvm/Support/ErrorHandling.h"
30 #include "llvm/Support/Format.h"
31 #include "llvm/Support/MathExtras.h"
32 #include "llvm/Support/Memory.h"
33 #include "llvm/Support/raw_ostream.h"
43 #define DEBUG_TYPE "orc-remote"
49 /// This class provides utilities (including memory manager, indirect stubs
50 /// manager, and compile callback manager types) that support remote JITing
53 /// Each of the utility classes talks to a JIT server (an instance of the
54 /// OrcRemoteTargetServer class) via an RPC system (see RPCUtils.h) to carry out
56 class OrcRemoteTargetClient
57 : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
59 /// Remote-mapped RuntimeDyld-compatible memory manager.
60 class RemoteRTDyldMemoryManager : public RuntimeDyld::MemoryManager {
61 friend class OrcRemoteTargetClient;
64 ~RemoteRTDyldMemoryManager() {
65 Client.destroyRemoteAllocator(Id);
66 LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
69 RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &) = delete;
70 RemoteRTDyldMemoryManager &
71 operator=(const RemoteRTDyldMemoryManager &) = delete;
72 RemoteRTDyldMemoryManager(RemoteRTDyldMemoryManager &&) = default;
73 RemoteRTDyldMemoryManager &operator=(RemoteRTDyldMemoryManager &&) = delete;
75 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
77 StringRef SectionName) override {
78 Unmapped.back().CodeAllocs.emplace_back(Size, Alignment);
79 uint8_t *Alloc = reinterpret_cast<uint8_t *>(
80 Unmapped.back().CodeAllocs.back().getLocalAddress());
81 LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated code for "
82 << SectionName << ": " << Alloc << " (" << Size
83 << " bytes, alignment " << Alignment << ")\n");
87 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
88 unsigned SectionID, StringRef SectionName,
89 bool IsReadOnly) override {
91 Unmapped.back().RODataAllocs.emplace_back(Size, Alignment);
92 uint8_t *Alloc = reinterpret_cast<uint8_t *>(
93 Unmapped.back().RODataAllocs.back().getLocalAddress());
94 LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for "
95 << SectionName << ": " << Alloc << " (" << Size
96 << " bytes, alignment " << Alignment << ")\n");
100 Unmapped.back().RWDataAllocs.emplace_back(Size, Alignment);
101 uint8_t *Alloc = reinterpret_cast<uint8_t *>(
102 Unmapped.back().RWDataAllocs.back().getLocalAddress());
103 LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for "
104 << SectionName << ": " << Alloc << " (" << Size
105 << " bytes, alignment " << Alignment << ")\n");
109 void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
110 uintptr_t RODataSize, uint32_t RODataAlign,
111 uintptr_t RWDataSize,
112 uint32_t RWDataAlign) override {
113 Unmapped.push_back(ObjectAllocs());
115 LLVM_DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
118 Unmapped.back().RemoteCodeAddr =
119 Client.reserveMem(Id, CodeSize, CodeAlign);
121 LLVM_DEBUG(dbgs() << " code: "
122 << format("0x%016x", Unmapped.back().RemoteCodeAddr)
123 << " (" << CodeSize << " bytes, alignment "
124 << CodeAlign << ")\n");
127 if (RODataSize != 0) {
128 Unmapped.back().RemoteRODataAddr =
129 Client.reserveMem(Id, RODataSize, RODataAlign);
131 LLVM_DEBUG(dbgs() << " ro-data: "
132 << format("0x%016x", Unmapped.back().RemoteRODataAddr)
133 << " (" << RODataSize << " bytes, alignment "
134 << RODataAlign << ")\n");
137 if (RWDataSize != 0) {
138 Unmapped.back().RemoteRWDataAddr =
139 Client.reserveMem(Id, RWDataSize, RWDataAlign);
141 LLVM_DEBUG(dbgs() << " rw-data: "
142 << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
143 << " (" << RWDataSize << " bytes, alignment "
144 << RWDataAlign << ")\n");
148 bool needsToReserveAllocationSpace() override { return true; }
150 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
151 size_t Size) override {
152 UnfinalizedEHFrames.push_back({LoadAddr, Size});
155 void deregisterEHFrames() override {
156 for (auto &Frame : RegisteredEHFrames) {
157 // FIXME: Add error poll.
158 Client.deregisterEHFrames(Frame.Addr, Frame.Size);
162 void notifyObjectLoaded(RuntimeDyld &Dyld,
163 const object::ObjectFile &Obj) override {
164 LLVM_DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
165 for (auto &ObjAllocs : Unmapped) {
166 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,
167 ObjAllocs.RemoteCodeAddr);
168 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs,
169 ObjAllocs.RemoteRODataAddr);
170 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs,
171 ObjAllocs.RemoteRWDataAddr);
172 Unfinalized.push_back(std::move(ObjAllocs));
177 bool finalizeMemory(std::string *ErrMsg = nullptr) override {
178 LLVM_DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
180 for (auto &ObjAllocs : Unfinalized) {
181 if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr,
182 sys::Memory::MF_READ | sys::Memory::MF_EXEC))
185 if (copyAndProtect(ObjAllocs.RODataAllocs, ObjAllocs.RemoteRODataAddr,
186 sys::Memory::MF_READ))
189 if (copyAndProtect(ObjAllocs.RWDataAllocs, ObjAllocs.RemoteRWDataAddr,
190 sys::Memory::MF_READ | sys::Memory::MF_WRITE))
195 for (auto &EHFrame : UnfinalizedEHFrames) {
196 if (auto Err = Client.registerEHFrames(EHFrame.Addr, EHFrame.Size)) {
197 // FIXME: Replace this once finalizeMemory can return an Error.
198 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
200 raw_string_ostream ErrOut(*ErrMsg);
207 RegisteredEHFrames = std::move(UnfinalizedEHFrames);
208 UnfinalizedEHFrames = {};
216 Alloc(uint64_t Size, unsigned Align)
217 : Size(Size), Align(Align), Contents(new char[Size + Align - 1]) {}
219 Alloc(const Alloc &) = delete;
220 Alloc &operator=(const Alloc &) = delete;
221 Alloc(Alloc &&) = default;
222 Alloc &operator=(Alloc &&) = default;
224 uint64_t getSize() const { return Size; }
226 unsigned getAlign() const { return Align; }
228 char *getLocalAddress() const {
229 uintptr_t LocalAddr = reinterpret_cast<uintptr_t>(Contents.get());
230 LocalAddr = alignTo(LocalAddr, Align);
231 return reinterpret_cast<char *>(LocalAddr);
234 void setRemoteAddress(JITTargetAddress RemoteAddr) {
235 this->RemoteAddr = RemoteAddr;
238 JITTargetAddress getRemoteAddress() const { return RemoteAddr; }
243 std::unique_ptr<char[]> Contents;
244 JITTargetAddress RemoteAddr = 0;
247 struct ObjectAllocs {
248 ObjectAllocs() = default;
249 ObjectAllocs(const ObjectAllocs &) = delete;
250 ObjectAllocs &operator=(const ObjectAllocs &) = delete;
251 ObjectAllocs(ObjectAllocs &&) = default;
252 ObjectAllocs &operator=(ObjectAllocs &&) = default;
254 JITTargetAddress RemoteCodeAddr = 0;
255 JITTargetAddress RemoteRODataAddr = 0;
256 JITTargetAddress RemoteRWDataAddr = 0;
257 std::vector<Alloc> CodeAllocs, RODataAllocs, RWDataAllocs;
260 RemoteRTDyldMemoryManager(OrcRemoteTargetClient &Client,
261 ResourceIdMgr::ResourceId Id)
262 : Client(Client), Id(Id) {
263 LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
266 // Maps all allocations in Allocs to aligned blocks
267 void mapAllocsToRemoteAddrs(RuntimeDyld &Dyld, std::vector<Alloc> &Allocs,
268 JITTargetAddress NextAddr) {
269 for (auto &Alloc : Allocs) {
270 NextAddr = alignTo(NextAddr, Alloc.getAlign());
271 Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr);
272 LLVM_DEBUG(dbgs() << " "
273 << static_cast<void *>(Alloc.getLocalAddress())
274 << " -> " << format("0x%016x", NextAddr) << "\n");
275 Alloc.setRemoteAddress(NextAddr);
277 // Only advance NextAddr if it was non-null to begin with,
278 // otherwise leave it as null.
280 NextAddr += Alloc.getSize();
284 // Copies data for each alloc in the list, then set permissions on the
286 bool copyAndProtect(const std::vector<Alloc> &Allocs,
287 JITTargetAddress RemoteSegmentAddr,
288 unsigned Permissions) {
289 if (RemoteSegmentAddr) {
290 assert(!Allocs.empty() && "No sections in allocated segment");
292 for (auto &Alloc : Allocs) {
293 LLVM_DEBUG(dbgs() << " copying section: "
294 << static_cast<void *>(Alloc.getLocalAddress())
296 << format("0x%016x", Alloc.getRemoteAddress())
297 << " (" << Alloc.getSize() << " bytes)\n";);
299 if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
304 LLVM_DEBUG(dbgs() << " setting "
305 << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
306 << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
307 << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
308 << " permissions on block: "
309 << format("0x%016x", RemoteSegmentAddr) << "\n");
310 if (Client.setProtections(Id, RemoteSegmentAddr, Permissions))
316 OrcRemoteTargetClient &Client;
317 ResourceIdMgr::ResourceId Id;
318 std::vector<ObjectAllocs> Unmapped;
319 std::vector<ObjectAllocs> Unfinalized;
322 JITTargetAddress Addr;
325 std::vector<EHFrame> UnfinalizedEHFrames;
326 std::vector<EHFrame> RegisteredEHFrames;
329 /// Remote indirect stubs manager.
330 class RemoteIndirectStubsManager : public IndirectStubsManager {
332 RemoteIndirectStubsManager(OrcRemoteTargetClient &Client,
333 ResourceIdMgr::ResourceId Id)
334 : Client(Client), Id(Id) {}
336 ~RemoteIndirectStubsManager() override {
337 Client.destroyIndirectStubsManager(Id);
340 Error createStub(StringRef StubName, JITTargetAddress StubAddr,
341 JITSymbolFlags StubFlags) override {
342 if (auto Err = reserveStubs(1))
345 return createStubInternal(StubName, StubAddr, StubFlags);
348 Error createStubs(const StubInitsMap &StubInits) override {
349 if (auto Err = reserveStubs(StubInits.size()))
352 for (auto &Entry : StubInits)
353 if (auto Err = createStubInternal(Entry.first(), Entry.second.first,
354 Entry.second.second))
357 return Error::success();
360 JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
361 auto I = StubIndexes.find(Name);
362 if (I == StubIndexes.end())
364 auto Key = I->second.first;
365 auto Flags = I->second.second;
366 auto StubSymbol = JITEvaluatedSymbol(getStubAddr(Key), Flags);
367 if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
372 JITEvaluatedSymbol findPointer(StringRef Name) override {
373 auto I = StubIndexes.find(Name);
374 if (I == StubIndexes.end())
376 auto Key = I->second.first;
377 auto Flags = I->second.second;
378 return JITEvaluatedSymbol(getPtrAddr(Key), Flags);
381 Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
382 auto I = StubIndexes.find(Name);
383 assert(I != StubIndexes.end() && "No stub pointer for symbol");
384 auto Key = I->second.first;
385 return Client.writePointer(getPtrAddr(Key), NewAddr);
389 struct RemoteIndirectStubsInfo {
390 JITTargetAddress StubBase;
391 JITTargetAddress PtrBase;
395 using StubKey = std::pair<uint16_t, uint16_t>;
397 Error reserveStubs(unsigned NumStubs) {
398 if (NumStubs <= FreeStubs.size())
399 return Error::success();
401 unsigned NewStubsRequired = NumStubs - FreeStubs.size();
402 JITTargetAddress StubBase;
403 JITTargetAddress PtrBase;
404 unsigned NumStubsEmitted;
406 if (auto StubInfoOrErr = Client.emitIndirectStubs(Id, NewStubsRequired))
407 std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
409 return StubInfoOrErr.takeError();
411 unsigned NewBlockId = RemoteIndirectStubsInfos.size();
412 RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted});
414 for (unsigned I = 0; I < NumStubsEmitted; ++I)
415 FreeStubs.push_back(std::make_pair(NewBlockId, I));
417 return Error::success();
420 Error createStubInternal(StringRef StubName, JITTargetAddress InitAddr,
421 JITSymbolFlags StubFlags) {
422 auto Key = FreeStubs.back();
423 FreeStubs.pop_back();
424 StubIndexes[StubName] = std::make_pair(Key, StubFlags);
425 return Client.writePointer(getPtrAddr(Key), InitAddr);
428 JITTargetAddress getStubAddr(StubKey K) {
429 assert(RemoteIndirectStubsInfos[K.first].StubBase != 0 &&
430 "Missing stub address");
431 return RemoteIndirectStubsInfos[K.first].StubBase +
432 K.second * Client.getIndirectStubSize();
435 JITTargetAddress getPtrAddr(StubKey K) {
436 assert(RemoteIndirectStubsInfos[K.first].PtrBase != 0 &&
437 "Missing pointer address");
438 return RemoteIndirectStubsInfos[K.first].PtrBase +
439 K.second * Client.getPointerSize();
442 OrcRemoteTargetClient &Client;
443 ResourceIdMgr::ResourceId Id;
444 std::vector<RemoteIndirectStubsInfo> RemoteIndirectStubsInfos;
445 std::vector<StubKey> FreeStubs;
446 StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
449 /// Remote compile callback manager.
450 class RemoteCompileCallbackManager : public JITCompileCallbackManager {
452 RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
453 ExecutionSession &ES,
454 JITTargetAddress ErrorHandlerAddress)
455 : JITCompileCallbackManager(ES, ErrorHandlerAddress), Client(Client) {}
458 Error grow() override {
459 JITTargetAddress BlockAddr = 0;
460 uint32_t NumTrampolines = 0;
461 if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock())
462 std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
464 return TrampolineInfoOrErr.takeError();
466 uint32_t TrampolineSize = Client.getTrampolineSize();
467 for (unsigned I = 0; I < NumTrampolines; ++I)
468 this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize));
470 return Error::success();
473 OrcRemoteTargetClient &Client;
476 /// Create an OrcRemoteTargetClient.
477 /// Channel is the ChannelT instance to communicate on. It is assumed that
478 /// the channel is ready to be read from and written to.
479 static Expected<std::unique_ptr<OrcRemoteTargetClient>>
480 Create(rpc::RawByteChannel &Channel, ExecutionSession &ES) {
481 Error Err = Error::success();
482 auto Client = std::unique_ptr<OrcRemoteTargetClient>(
483 new OrcRemoteTargetClient(Channel, ES, Err));
485 return std::move(Err);
486 return std::move(Client);
489 /// Call the int(void) function at the given address in the target and return
491 Expected<int> callIntVoid(JITTargetAddress Addr) {
492 LLVM_DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr)
494 return callB<exec::CallIntVoid>(Addr);
497 /// Call the int(int, char*[]) function at the given address in the target and
498 /// return its result.
499 Expected<int> callMain(JITTargetAddress Addr,
500 const std::vector<std::string> &Args) {
501 LLVM_DEBUG(dbgs() << "Calling int(*)(int, char*[]) "
502 << format("0x%016x", Addr) << "\n");
503 return callB<exec::CallMain>(Addr, Args);
506 /// Call the void() function at the given address in the target and wait for
508 Error callVoidVoid(JITTargetAddress Addr) {
509 LLVM_DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
511 return callB<exec::CallVoidVoid>(Addr);
514 /// Create an RCMemoryManager which will allocate its memory on the remote
516 Expected<std::unique_ptr<RemoteRTDyldMemoryManager>>
517 createRemoteMemoryManager() {
518 auto Id = AllocatorIds.getNext();
519 if (auto Err = callB<mem::CreateRemoteAllocator>(Id))
520 return std::move(Err);
521 return std::unique_ptr<RemoteRTDyldMemoryManager>(
522 new RemoteRTDyldMemoryManager(*this, Id));
525 /// Create an RCIndirectStubsManager that will allocate stubs on the remote
527 Expected<std::unique_ptr<RemoteIndirectStubsManager>>
528 createIndirectStubsManager() {
529 auto Id = IndirectStubOwnerIds.getNext();
530 if (auto Err = callB<stubs::CreateIndirectStubsOwner>(Id))
531 return std::move(Err);
532 return llvm::make_unique<RemoteIndirectStubsManager>(*this, Id);
535 Expected<RemoteCompileCallbackManager &>
536 enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) {
537 assert(!CallbackManager && "CallbackManager already obtained");
539 // Emit the resolver block on the JIT server.
540 if (auto Err = callB<stubs::EmitResolverBlock>())
541 return std::move(Err);
543 // Create the callback manager.
544 CallbackManager.emplace(*this, ES, ErrorHandlerAddress);
545 RemoteCompileCallbackManager &Mgr = *CallbackManager;
549 /// Search for symbols in the remote process. Note: This should be used by
550 /// symbol resolvers *after* they've searched the local symbol table in the
552 Expected<JITTargetAddress> getSymbolAddress(StringRef Name) {
553 return callB<utils::GetSymbolAddress>(Name);
556 /// Get the triple for the remote target.
557 const std::string &getTargetTriple() const { return RemoteTargetTriple; }
559 Error terminateSession() { return callB<utils::TerminateSession>(); }
562 OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES,
564 : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
566 ErrorAsOutParameter EAO(&Err);
568 addHandler<utils::RequestCompile>(
569 [this](JITTargetAddress Addr) -> JITTargetAddress {
571 return CallbackManager->executeCompileCallback(Addr);
575 if (auto RIOrErr = callB<utils::GetRemoteInfo>()) {
576 std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
577 RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
578 Err = Error::success();
580 Err = RIOrErr.takeError();
583 void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
584 if (auto Err = callB<eh::RegisterEHFrames>(Addr, Size))
585 ES.reportError(std::move(Err));
588 void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
589 if (auto Err = callB<mem::DestroyRemoteAllocator>(Id)) {
590 // FIXME: This will be triggered by a removeModuleSet call: Propagate
591 // error return up through that.
592 llvm_unreachable("Failed to destroy remote allocator.");
593 AllocatorIds.release(Id);
597 void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
598 IndirectStubOwnerIds.release(Id);
599 if (auto Err = callB<stubs::DestroyIndirectStubsOwner>(Id))
600 ES.reportError(std::move(Err));
603 Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
604 emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) {
605 return callB<stubs::EmitIndirectStubs>(Id, NumStubsRequired);
608 Expected<std::tuple<JITTargetAddress, uint32_t>> emitTrampolineBlock() {
609 return callB<stubs::EmitTrampolineBlock>();
612 uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
613 uint32_t getPageSize() const { return RemotePageSize; }
614 uint32_t getPointerSize() const { return RemotePointerSize; }
616 uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
618 Expected<std::vector<uint8_t>> readMem(char *Dst, JITTargetAddress Src,
620 return callB<mem::ReadMem>(Src, Size);
623 Error registerEHFrames(JITTargetAddress &RAddr, uint32_t Size) {
624 // FIXME: Duplicate error and report it via ReportError too?
625 return callB<eh::RegisterEHFrames>(RAddr, Size);
628 JITTargetAddress reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
630 if (auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align))
633 ES.reportError(AddrOrErr.takeError());
638 bool setProtections(ResourceIdMgr::ResourceId Id,
639 JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
640 if (auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) {
641 ES.reportError(std::move(Err));
647 bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
648 if (auto Err = callB<mem::WriteMem>(DirectBufferWriter(Src, Addr, Size))) {
649 ES.reportError(std::move(Err));
655 Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) {
656 return callB<mem::WritePtr>(Addr, PtrVal);
659 static Error doNothing() { return Error::success(); }
661 ExecutionSession &ES;
662 std::function<void(Error)> ReportError;
663 std::string RemoteTargetTriple;
664 uint32_t RemotePointerSize = 0;
665 uint32_t RemotePageSize = 0;
666 uint32_t RemoteTrampolineSize = 0;
667 uint32_t RemoteIndirectStubSize = 0;
668 ResourceIdMgr AllocatorIds, IndirectStubOwnerIds;
669 Optional<RemoteCompileCallbackManager> CallbackManager;
672 } // end namespace remote
673 } // end namespace orc
674 } // end namespace llvm
678 #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H