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);
123 << format("0x%016" PRIx64, Unmapped.back().RemoteCodeAddr)
124 << " (" << CodeSize << " bytes, alignment " << CodeAlign
128 if (RODataSize != 0) {
129 Unmapped.back().RemoteRODataAddr =
130 Client.reserveMem(Id, RODataSize, RODataAlign);
133 dbgs() << " ro-data: "
134 << format("0x%016" PRIx64, Unmapped.back().RemoteRODataAddr)
135 << " (" << RODataSize << " bytes, alignment " << RODataAlign
139 if (RWDataSize != 0) {
140 Unmapped.back().RemoteRWDataAddr =
141 Client.reserveMem(Id, RWDataSize, RWDataAlign);
144 dbgs() << " rw-data: "
145 << format("0x%016" PRIx64, Unmapped.back().RemoteRWDataAddr)
146 << " (" << RWDataSize << " bytes, alignment " << RWDataAlign
151 bool needsToReserveAllocationSpace() override { return true; }
153 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
154 size_t Size) override {
155 UnfinalizedEHFrames.push_back({LoadAddr, Size});
158 void deregisterEHFrames() override {
159 for (auto &Frame : RegisteredEHFrames) {
160 // FIXME: Add error poll.
161 Client.deregisterEHFrames(Frame.Addr, Frame.Size);
165 void notifyObjectLoaded(RuntimeDyld &Dyld,
166 const object::ObjectFile &Obj) override {
167 LLVM_DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
168 for (auto &ObjAllocs : Unmapped) {
169 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,
170 ObjAllocs.RemoteCodeAddr);
171 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs,
172 ObjAllocs.RemoteRODataAddr);
173 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs,
174 ObjAllocs.RemoteRWDataAddr);
175 Unfinalized.push_back(std::move(ObjAllocs));
180 bool finalizeMemory(std::string *ErrMsg = nullptr) override {
181 LLVM_DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
183 for (auto &ObjAllocs : Unfinalized) {
184 if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr,
185 sys::Memory::MF_READ | sys::Memory::MF_EXEC))
188 if (copyAndProtect(ObjAllocs.RODataAllocs, ObjAllocs.RemoteRODataAddr,
189 sys::Memory::MF_READ))
192 if (copyAndProtect(ObjAllocs.RWDataAllocs, ObjAllocs.RemoteRWDataAddr,
193 sys::Memory::MF_READ | sys::Memory::MF_WRITE))
198 for (auto &EHFrame : UnfinalizedEHFrames) {
199 if (auto Err = Client.registerEHFrames(EHFrame.Addr, EHFrame.Size)) {
200 // FIXME: Replace this once finalizeMemory can return an Error.
201 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
203 raw_string_ostream ErrOut(*ErrMsg);
210 RegisteredEHFrames = std::move(UnfinalizedEHFrames);
211 UnfinalizedEHFrames = {};
219 Alloc(uint64_t Size, unsigned Align)
220 : Size(Size), Align(Align), Contents(new char[Size + Align - 1]) {}
222 Alloc(const Alloc &) = delete;
223 Alloc &operator=(const Alloc &) = delete;
224 Alloc(Alloc &&) = default;
225 Alloc &operator=(Alloc &&) = default;
227 uint64_t getSize() const { return Size; }
229 unsigned getAlign() const { return Align; }
231 char *getLocalAddress() const {
232 uintptr_t LocalAddr = reinterpret_cast<uintptr_t>(Contents.get());
233 LocalAddr = alignTo(LocalAddr, Align);
234 return reinterpret_cast<char *>(LocalAddr);
237 void setRemoteAddress(JITTargetAddress RemoteAddr) {
238 this->RemoteAddr = RemoteAddr;
241 JITTargetAddress getRemoteAddress() const { return RemoteAddr; }
246 std::unique_ptr<char[]> Contents;
247 JITTargetAddress RemoteAddr = 0;
250 struct ObjectAllocs {
251 ObjectAllocs() = default;
252 ObjectAllocs(const ObjectAllocs &) = delete;
253 ObjectAllocs &operator=(const ObjectAllocs &) = delete;
254 ObjectAllocs(ObjectAllocs &&) = default;
255 ObjectAllocs &operator=(ObjectAllocs &&) = default;
257 JITTargetAddress RemoteCodeAddr = 0;
258 JITTargetAddress RemoteRODataAddr = 0;
259 JITTargetAddress RemoteRWDataAddr = 0;
260 std::vector<Alloc> CodeAllocs, RODataAllocs, RWDataAllocs;
263 RemoteRTDyldMemoryManager(OrcRemoteTargetClient &Client,
264 ResourceIdMgr::ResourceId Id)
265 : Client(Client), Id(Id) {
266 LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
269 // Maps all allocations in Allocs to aligned blocks
270 void mapAllocsToRemoteAddrs(RuntimeDyld &Dyld, std::vector<Alloc> &Allocs,
271 JITTargetAddress NextAddr) {
272 for (auto &Alloc : Allocs) {
273 NextAddr = alignTo(NextAddr, Alloc.getAlign());
274 Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr);
276 dbgs() << " " << static_cast<void *>(Alloc.getLocalAddress())
277 << " -> " << format("0x%016" PRIx64, NextAddr) << "\n");
278 Alloc.setRemoteAddress(NextAddr);
280 // Only advance NextAddr if it was non-null to begin with,
281 // otherwise leave it as null.
283 NextAddr += Alloc.getSize();
287 // Copies data for each alloc in the list, then set permissions on the
289 bool copyAndProtect(const std::vector<Alloc> &Allocs,
290 JITTargetAddress RemoteSegmentAddr,
291 unsigned Permissions) {
292 if (RemoteSegmentAddr) {
293 assert(!Allocs.empty() && "No sections in allocated segment");
295 for (auto &Alloc : Allocs) {
296 LLVM_DEBUG(dbgs() << " copying section: "
297 << static_cast<void *>(Alloc.getLocalAddress())
299 << format("0x%016" PRIx64, Alloc.getRemoteAddress())
300 << " (" << Alloc.getSize() << " bytes)\n";);
302 if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
307 LLVM_DEBUG(dbgs() << " setting "
308 << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
309 << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
310 << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
311 << " permissions on block: "
312 << format("0x%016" PRIx64, RemoteSegmentAddr)
314 if (Client.setProtections(Id, RemoteSegmentAddr, Permissions))
320 OrcRemoteTargetClient &Client;
321 ResourceIdMgr::ResourceId Id;
322 std::vector<ObjectAllocs> Unmapped;
323 std::vector<ObjectAllocs> Unfinalized;
326 JITTargetAddress Addr;
329 std::vector<EHFrame> UnfinalizedEHFrames;
330 std::vector<EHFrame> RegisteredEHFrames;
333 /// Remote indirect stubs manager.
334 class RemoteIndirectStubsManager : public IndirectStubsManager {
336 RemoteIndirectStubsManager(OrcRemoteTargetClient &Client,
337 ResourceIdMgr::ResourceId Id)
338 : Client(Client), Id(Id) {}
340 ~RemoteIndirectStubsManager() override {
341 Client.destroyIndirectStubsManager(Id);
344 Error createStub(StringRef StubName, JITTargetAddress StubAddr,
345 JITSymbolFlags StubFlags) override {
346 if (auto Err = reserveStubs(1))
349 return createStubInternal(StubName, StubAddr, StubFlags);
352 Error createStubs(const StubInitsMap &StubInits) override {
353 if (auto Err = reserveStubs(StubInits.size()))
356 for (auto &Entry : StubInits)
357 if (auto Err = createStubInternal(Entry.first(), Entry.second.first,
358 Entry.second.second))
361 return Error::success();
364 JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
365 auto I = StubIndexes.find(Name);
366 if (I == StubIndexes.end())
368 auto Key = I->second.first;
369 auto Flags = I->second.second;
370 auto StubSymbol = JITEvaluatedSymbol(getStubAddr(Key), Flags);
371 if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
376 JITEvaluatedSymbol findPointer(StringRef Name) override {
377 auto I = StubIndexes.find(Name);
378 if (I == StubIndexes.end())
380 auto Key = I->second.first;
381 auto Flags = I->second.second;
382 return JITEvaluatedSymbol(getPtrAddr(Key), Flags);
385 Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
386 auto I = StubIndexes.find(Name);
387 assert(I != StubIndexes.end() && "No stub pointer for symbol");
388 auto Key = I->second.first;
389 return Client.writePointer(getPtrAddr(Key), NewAddr);
393 struct RemoteIndirectStubsInfo {
394 JITTargetAddress StubBase;
395 JITTargetAddress PtrBase;
399 using StubKey = std::pair<uint16_t, uint16_t>;
401 Error reserveStubs(unsigned NumStubs) {
402 if (NumStubs <= FreeStubs.size())
403 return Error::success();
405 unsigned NewStubsRequired = NumStubs - FreeStubs.size();
406 JITTargetAddress StubBase;
407 JITTargetAddress PtrBase;
408 unsigned NumStubsEmitted;
410 if (auto StubInfoOrErr = Client.emitIndirectStubs(Id, NewStubsRequired))
411 std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
413 return StubInfoOrErr.takeError();
415 unsigned NewBlockId = RemoteIndirectStubsInfos.size();
416 RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted});
418 for (unsigned I = 0; I < NumStubsEmitted; ++I)
419 FreeStubs.push_back(std::make_pair(NewBlockId, I));
421 return Error::success();
424 Error createStubInternal(StringRef StubName, JITTargetAddress InitAddr,
425 JITSymbolFlags StubFlags) {
426 auto Key = FreeStubs.back();
427 FreeStubs.pop_back();
428 StubIndexes[StubName] = std::make_pair(Key, StubFlags);
429 return Client.writePointer(getPtrAddr(Key), InitAddr);
432 JITTargetAddress getStubAddr(StubKey K) {
433 assert(RemoteIndirectStubsInfos[K.first].StubBase != 0 &&
434 "Missing stub address");
435 return RemoteIndirectStubsInfos[K.first].StubBase +
436 K.second * Client.getIndirectStubSize();
439 JITTargetAddress getPtrAddr(StubKey K) {
440 assert(RemoteIndirectStubsInfos[K.first].PtrBase != 0 &&
441 "Missing pointer address");
442 return RemoteIndirectStubsInfos[K.first].PtrBase +
443 K.second * Client.getPointerSize();
446 OrcRemoteTargetClient &Client;
447 ResourceIdMgr::ResourceId Id;
448 std::vector<RemoteIndirectStubsInfo> RemoteIndirectStubsInfos;
449 std::vector<StubKey> FreeStubs;
450 StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
453 class RemoteTrampolinePool : public TrampolinePool {
455 RemoteTrampolinePool(OrcRemoteTargetClient &Client) : Client(Client) {}
457 Expected<JITTargetAddress> getTrampoline() override {
458 std::lock_guard<std::mutex> Lock(RTPMutex);
459 if (AvailableTrampolines.empty()) {
460 if (auto Err = grow())
461 return std::move(Err);
463 assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool");
464 auto TrampolineAddr = AvailableTrampolines.back();
465 AvailableTrampolines.pop_back();
466 return TrampolineAddr;
471 JITTargetAddress BlockAddr = 0;
472 uint32_t NumTrampolines = 0;
473 if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock())
474 std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
476 return TrampolineInfoOrErr.takeError();
478 uint32_t TrampolineSize = Client.getTrampolineSize();
479 for (unsigned I = 0; I < NumTrampolines; ++I)
480 this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize));
482 return Error::success();
486 OrcRemoteTargetClient &Client;
487 std::vector<JITTargetAddress> AvailableTrampolines;
490 /// Remote compile callback manager.
491 class RemoteCompileCallbackManager : public JITCompileCallbackManager {
493 RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
494 ExecutionSession &ES,
495 JITTargetAddress ErrorHandlerAddress)
496 : JITCompileCallbackManager(
497 llvm::make_unique<RemoteTrampolinePool>(Client), ES,
498 ErrorHandlerAddress) {}
501 /// Create an OrcRemoteTargetClient.
502 /// Channel is the ChannelT instance to communicate on. It is assumed that
503 /// the channel is ready to be read from and written to.
504 static Expected<std::unique_ptr<OrcRemoteTargetClient>>
505 Create(rpc::RawByteChannel &Channel, ExecutionSession &ES) {
506 Error Err = Error::success();
507 auto Client = std::unique_ptr<OrcRemoteTargetClient>(
508 new OrcRemoteTargetClient(Channel, ES, Err));
510 return std::move(Err);
511 return std::move(Client);
514 /// Call the int(void) function at the given address in the target and return
516 Expected<int> callIntVoid(JITTargetAddress Addr) {
517 LLVM_DEBUG(dbgs() << "Calling int(*)(void) "
518 << format("0x%016" PRIx64, Addr) << "\n");
519 return callB<exec::CallIntVoid>(Addr);
522 /// Call the int(int, char*[]) function at the given address in the target and
523 /// return its result.
524 Expected<int> callMain(JITTargetAddress Addr,
525 const std::vector<std::string> &Args) {
526 LLVM_DEBUG(dbgs() << "Calling int(*)(int, char*[]) "
527 << format("0x%016" PRIx64, Addr) << "\n");
528 return callB<exec::CallMain>(Addr, Args);
531 /// Call the void() function at the given address in the target and wait for
533 Error callVoidVoid(JITTargetAddress Addr) {
534 LLVM_DEBUG(dbgs() << "Calling void(*)(void) "
535 << format("0x%016" PRIx64, Addr) << "\n");
536 return callB<exec::CallVoidVoid>(Addr);
539 /// Create an RCMemoryManager which will allocate its memory on the remote
541 Expected<std::unique_ptr<RemoteRTDyldMemoryManager>>
542 createRemoteMemoryManager() {
543 auto Id = AllocatorIds.getNext();
544 if (auto Err = callB<mem::CreateRemoteAllocator>(Id))
545 return std::move(Err);
546 return std::unique_ptr<RemoteRTDyldMemoryManager>(
547 new RemoteRTDyldMemoryManager(*this, Id));
550 /// Create an RCIndirectStubsManager that will allocate stubs on the remote
552 Expected<std::unique_ptr<RemoteIndirectStubsManager>>
553 createIndirectStubsManager() {
554 auto Id = IndirectStubOwnerIds.getNext();
555 if (auto Err = callB<stubs::CreateIndirectStubsOwner>(Id))
556 return std::move(Err);
557 return llvm::make_unique<RemoteIndirectStubsManager>(*this, Id);
560 Expected<RemoteCompileCallbackManager &>
561 enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) {
562 assert(!CallbackManager && "CallbackManager already obtained");
564 // Emit the resolver block on the JIT server.
565 if (auto Err = callB<stubs::EmitResolverBlock>())
566 return std::move(Err);
568 // Create the callback manager.
569 CallbackManager.emplace(*this, ES, ErrorHandlerAddress);
570 RemoteCompileCallbackManager &Mgr = *CallbackManager;
574 /// Search for symbols in the remote process. Note: This should be used by
575 /// symbol resolvers *after* they've searched the local symbol table in the
577 Expected<JITTargetAddress> getSymbolAddress(StringRef Name) {
578 return callB<utils::GetSymbolAddress>(Name);
581 /// Get the triple for the remote target.
582 const std::string &getTargetTriple() const { return RemoteTargetTriple; }
584 Error terminateSession() { return callB<utils::TerminateSession>(); }
587 OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES,
589 : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
591 ErrorAsOutParameter EAO(&Err);
593 addHandler<utils::RequestCompile>(
594 [this](JITTargetAddress Addr) -> JITTargetAddress {
596 return CallbackManager->executeCompileCallback(Addr);
600 if (auto RIOrErr = callB<utils::GetRemoteInfo>()) {
601 std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
602 RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
603 Err = Error::success();
605 Err = RIOrErr.takeError();
608 void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
609 if (auto Err = callB<eh::RegisterEHFrames>(Addr, Size))
610 ES.reportError(std::move(Err));
613 void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
614 if (auto Err = callB<mem::DestroyRemoteAllocator>(Id)) {
615 // FIXME: This will be triggered by a removeModuleSet call: Propagate
616 // error return up through that.
617 llvm_unreachable("Failed to destroy remote allocator.");
618 AllocatorIds.release(Id);
622 void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
623 IndirectStubOwnerIds.release(Id);
624 if (auto Err = callB<stubs::DestroyIndirectStubsOwner>(Id))
625 ES.reportError(std::move(Err));
628 Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
629 emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) {
630 return callB<stubs::EmitIndirectStubs>(Id, NumStubsRequired);
633 Expected<std::tuple<JITTargetAddress, uint32_t>> emitTrampolineBlock() {
634 return callB<stubs::EmitTrampolineBlock>();
637 uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
638 uint32_t getPageSize() const { return RemotePageSize; }
639 uint32_t getPointerSize() const { return RemotePointerSize; }
641 uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
643 Expected<std::vector<uint8_t>> readMem(char *Dst, JITTargetAddress Src,
645 return callB<mem::ReadMem>(Src, Size);
648 Error registerEHFrames(JITTargetAddress &RAddr, uint32_t Size) {
649 // FIXME: Duplicate error and report it via ReportError too?
650 return callB<eh::RegisterEHFrames>(RAddr, Size);
653 JITTargetAddress reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
655 if (auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align))
658 ES.reportError(AddrOrErr.takeError());
663 bool setProtections(ResourceIdMgr::ResourceId Id,
664 JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
665 if (auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) {
666 ES.reportError(std::move(Err));
672 bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
673 if (auto Err = callB<mem::WriteMem>(DirectBufferWriter(Src, Addr, Size))) {
674 ES.reportError(std::move(Err));
680 Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) {
681 return callB<mem::WritePtr>(Addr, PtrVal);
684 static Error doNothing() { return Error::success(); }
686 ExecutionSession &ES;
687 std::function<void(Error)> ReportError;
688 std::string RemoteTargetTriple;
689 uint32_t RemotePointerSize = 0;
690 uint32_t RemotePageSize = 0;
691 uint32_t RemoteTrampolineSize = 0;
692 uint32_t RemoteIndirectStubSize = 0;
693 ResourceIdMgr AllocatorIds, IndirectStubOwnerIds;
694 Optional<RemoteCompileCallbackManager> CallbackManager;
697 } // end namespace remote
698 } // end namespace orc
699 } // end namespace llvm
703 #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H