1 //===- OrcRemoteTargetClient.h - Orc Remote-target Client -------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines the OrcRemoteTargetClient class and helpers. This class
10 // can be used to communicate over an RawByteChannel with an
11 // OrcRemoteTargetServer instance to support remote-JITing.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
16 #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
18 #include "llvm/ADT/Optional.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/ExecutionEngine/JITSymbol.h"
23 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
24 #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h"
25 #include "llvm/ExecutionEngine/RuntimeDyld.h"
26 #include "llvm/Support/Debug.h"
27 #include "llvm/Support/Error.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include "llvm/Support/Format.h"
30 #include "llvm/Support/MathExtras.h"
31 #include "llvm/Support/Memory.h"
32 #include "llvm/Support/raw_ostream.h"
42 #define DEBUG_TYPE "orc-remote"
48 /// This class provides utilities (including memory manager, indirect stubs
49 /// manager, and compile callback manager types) that support remote JITing
52 /// Each of the utility classes talks to a JIT server (an instance of the
53 /// OrcRemoteTargetServer class) via an RPC system (see RPCUtils.h) to carry out
55 class OrcRemoteTargetClient
56 : public rpc::SingleThreadedRPCEndpoint
<rpc::RawByteChannel
> {
58 /// Remote-mapped RuntimeDyld-compatible memory manager.
59 class RemoteRTDyldMemoryManager
: public RuntimeDyld::MemoryManager
{
60 friend class OrcRemoteTargetClient
;
63 ~RemoteRTDyldMemoryManager() {
64 Client
.destroyRemoteAllocator(Id
);
65 LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << Id
<< "\n");
68 RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager
&) = delete;
69 RemoteRTDyldMemoryManager
&
70 operator=(const RemoteRTDyldMemoryManager
&) = delete;
71 RemoteRTDyldMemoryManager(RemoteRTDyldMemoryManager
&&) = default;
72 RemoteRTDyldMemoryManager
&operator=(RemoteRTDyldMemoryManager
&&) = delete;
74 uint8_t *allocateCodeSection(uintptr_t Size
, unsigned Alignment
,
76 StringRef SectionName
) override
{
77 Unmapped
.back().CodeAllocs
.emplace_back(Size
, Alignment
);
78 uint8_t *Alloc
= reinterpret_cast<uint8_t *>(
79 Unmapped
.back().CodeAllocs
.back().getLocalAddress());
80 LLVM_DEBUG(dbgs() << "Allocator " << Id
<< " allocated code for "
81 << SectionName
<< ": " << Alloc
<< " (" << Size
82 << " bytes, alignment " << Alignment
<< ")\n");
86 uint8_t *allocateDataSection(uintptr_t Size
, unsigned Alignment
,
87 unsigned SectionID
, StringRef SectionName
,
88 bool IsReadOnly
) override
{
90 Unmapped
.back().RODataAllocs
.emplace_back(Size
, Alignment
);
91 uint8_t *Alloc
= reinterpret_cast<uint8_t *>(
92 Unmapped
.back().RODataAllocs
.back().getLocalAddress());
93 LLVM_DEBUG(dbgs() << "Allocator " << Id
<< " allocated ro-data for "
94 << SectionName
<< ": " << Alloc
<< " (" << Size
95 << " bytes, alignment " << Alignment
<< ")\n");
99 Unmapped
.back().RWDataAllocs
.emplace_back(Size
, Alignment
);
100 uint8_t *Alloc
= reinterpret_cast<uint8_t *>(
101 Unmapped
.back().RWDataAllocs
.back().getLocalAddress());
102 LLVM_DEBUG(dbgs() << "Allocator " << Id
<< " allocated rw-data for "
103 << SectionName
<< ": " << Alloc
<< " (" << Size
104 << " bytes, alignment " << Alignment
<< ")\n");
108 void reserveAllocationSpace(uintptr_t CodeSize
, uint32_t CodeAlign
,
109 uintptr_t RODataSize
, uint32_t RODataAlign
,
110 uintptr_t RWDataSize
,
111 uint32_t RWDataAlign
) override
{
112 Unmapped
.push_back(ObjectAllocs());
114 LLVM_DEBUG(dbgs() << "Allocator " << Id
<< " reserved:\n");
117 Unmapped
.back().RemoteCodeAddr
=
118 Client
.reserveMem(Id
, CodeSize
, CodeAlign
);
122 << format("0x%016" PRIx64
, Unmapped
.back().RemoteCodeAddr
)
123 << " (" << CodeSize
<< " bytes, alignment " << CodeAlign
127 if (RODataSize
!= 0) {
128 Unmapped
.back().RemoteRODataAddr
=
129 Client
.reserveMem(Id
, RODataSize
, RODataAlign
);
132 dbgs() << " ro-data: "
133 << format("0x%016" PRIx64
, Unmapped
.back().RemoteRODataAddr
)
134 << " (" << RODataSize
<< " bytes, alignment " << RODataAlign
138 if (RWDataSize
!= 0) {
139 Unmapped
.back().RemoteRWDataAddr
=
140 Client
.reserveMem(Id
, RWDataSize
, RWDataAlign
);
143 dbgs() << " rw-data: "
144 << format("0x%016" PRIx64
, Unmapped
.back().RemoteRWDataAddr
)
145 << " (" << RWDataSize
<< " bytes, alignment " << RWDataAlign
150 bool needsToReserveAllocationSpace() override
{ return true; }
152 void registerEHFrames(uint8_t *Addr
, uint64_t LoadAddr
,
153 size_t Size
) override
{
154 UnfinalizedEHFrames
.push_back({LoadAddr
, Size
});
157 void deregisterEHFrames() override
{
158 for (auto &Frame
: RegisteredEHFrames
) {
159 // FIXME: Add error poll.
160 Client
.deregisterEHFrames(Frame
.Addr
, Frame
.Size
);
164 void notifyObjectLoaded(RuntimeDyld
&Dyld
,
165 const object::ObjectFile
&Obj
) override
{
166 LLVM_DEBUG(dbgs() << "Allocator " << Id
<< " applied mappings:\n");
167 for (auto &ObjAllocs
: Unmapped
) {
168 mapAllocsToRemoteAddrs(Dyld
, ObjAllocs
.CodeAllocs
,
169 ObjAllocs
.RemoteCodeAddr
);
170 mapAllocsToRemoteAddrs(Dyld
, ObjAllocs
.RODataAllocs
,
171 ObjAllocs
.RemoteRODataAddr
);
172 mapAllocsToRemoteAddrs(Dyld
, ObjAllocs
.RWDataAllocs
,
173 ObjAllocs
.RemoteRWDataAddr
);
174 Unfinalized
.push_back(std::move(ObjAllocs
));
179 bool finalizeMemory(std::string
*ErrMsg
= nullptr) override
{
180 LLVM_DEBUG(dbgs() << "Allocator " << Id
<< " finalizing:\n");
182 for (auto &ObjAllocs
: Unfinalized
) {
183 if (copyAndProtect(ObjAllocs
.CodeAllocs
, ObjAllocs
.RemoteCodeAddr
,
184 sys::Memory::MF_READ
| sys::Memory::MF_EXEC
))
187 if (copyAndProtect(ObjAllocs
.RODataAllocs
, ObjAllocs
.RemoteRODataAddr
,
188 sys::Memory::MF_READ
))
191 if (copyAndProtect(ObjAllocs
.RWDataAllocs
, ObjAllocs
.RemoteRWDataAddr
,
192 sys::Memory::MF_READ
| sys::Memory::MF_WRITE
))
197 for (auto &EHFrame
: UnfinalizedEHFrames
) {
198 if (auto Err
= Client
.registerEHFrames(EHFrame
.Addr
, EHFrame
.Size
)) {
199 // FIXME: Replace this once finalizeMemory can return an Error.
200 handleAllErrors(std::move(Err
), [&](ErrorInfoBase
&EIB
) {
202 raw_string_ostream
ErrOut(*ErrMsg
);
209 RegisteredEHFrames
= std::move(UnfinalizedEHFrames
);
210 UnfinalizedEHFrames
= {};
218 Alloc(uint64_t Size
, unsigned Align
)
219 : Size(Size
), Align(Align
), Contents(new char[Size
+ Align
- 1]) {}
221 Alloc(const Alloc
&) = delete;
222 Alloc
&operator=(const Alloc
&) = delete;
223 Alloc(Alloc
&&) = default;
224 Alloc
&operator=(Alloc
&&) = default;
226 uint64_t getSize() const { return Size
; }
228 unsigned getAlign() const { return Align
; }
230 char *getLocalAddress() const {
231 uintptr_t LocalAddr
= reinterpret_cast<uintptr_t>(Contents
.get());
232 LocalAddr
= alignTo(LocalAddr
, Align
);
233 return reinterpret_cast<char *>(LocalAddr
);
236 void setRemoteAddress(JITTargetAddress RemoteAddr
) {
237 this->RemoteAddr
= RemoteAddr
;
240 JITTargetAddress
getRemoteAddress() const { return RemoteAddr
; }
245 std::unique_ptr
<char[]> Contents
;
246 JITTargetAddress RemoteAddr
= 0;
249 struct ObjectAllocs
{
250 ObjectAllocs() = default;
251 ObjectAllocs(const ObjectAllocs
&) = delete;
252 ObjectAllocs
&operator=(const ObjectAllocs
&) = delete;
253 ObjectAllocs(ObjectAllocs
&&) = default;
254 ObjectAllocs
&operator=(ObjectAllocs
&&) = default;
256 JITTargetAddress RemoteCodeAddr
= 0;
257 JITTargetAddress RemoteRODataAddr
= 0;
258 JITTargetAddress RemoteRWDataAddr
= 0;
259 std::vector
<Alloc
> CodeAllocs
, RODataAllocs
, RWDataAllocs
;
262 RemoteRTDyldMemoryManager(OrcRemoteTargetClient
&Client
,
263 ResourceIdMgr::ResourceId Id
)
264 : Client(Client
), Id(Id
) {
265 LLVM_DEBUG(dbgs() << "Created remote allocator " << Id
<< "\n");
268 // Maps all allocations in Allocs to aligned blocks
269 void mapAllocsToRemoteAddrs(RuntimeDyld
&Dyld
, std::vector
<Alloc
> &Allocs
,
270 JITTargetAddress NextAddr
) {
271 for (auto &Alloc
: Allocs
) {
272 NextAddr
= alignTo(NextAddr
, Alloc
.getAlign());
273 Dyld
.mapSectionAddress(Alloc
.getLocalAddress(), NextAddr
);
275 dbgs() << " " << static_cast<void *>(Alloc
.getLocalAddress())
276 << " -> " << format("0x%016" PRIx64
, NextAddr
) << "\n");
277 Alloc
.setRemoteAddress(NextAddr
);
279 // Only advance NextAddr if it was non-null to begin with,
280 // otherwise leave it as null.
282 NextAddr
+= Alloc
.getSize();
286 // Copies data for each alloc in the list, then set permissions on the
288 bool copyAndProtect(const std::vector
<Alloc
> &Allocs
,
289 JITTargetAddress RemoteSegmentAddr
,
290 unsigned Permissions
) {
291 if (RemoteSegmentAddr
) {
292 assert(!Allocs
.empty() && "No sections in allocated segment");
294 for (auto &Alloc
: Allocs
) {
295 LLVM_DEBUG(dbgs() << " copying section: "
296 << static_cast<void *>(Alloc
.getLocalAddress())
298 << format("0x%016" PRIx64
, Alloc
.getRemoteAddress())
299 << " (" << Alloc
.getSize() << " bytes)\n";);
301 if (Client
.writeMem(Alloc
.getRemoteAddress(), Alloc
.getLocalAddress(),
306 LLVM_DEBUG(dbgs() << " setting "
307 << (Permissions
& sys::Memory::MF_READ
? 'R' : '-')
308 << (Permissions
& sys::Memory::MF_WRITE
? 'W' : '-')
309 << (Permissions
& sys::Memory::MF_EXEC
? 'X' : '-')
310 << " permissions on block: "
311 << format("0x%016" PRIx64
, RemoteSegmentAddr
)
313 if (Client
.setProtections(Id
, RemoteSegmentAddr
, Permissions
))
319 OrcRemoteTargetClient
&Client
;
320 ResourceIdMgr::ResourceId Id
;
321 std::vector
<ObjectAllocs
> Unmapped
;
322 std::vector
<ObjectAllocs
> Unfinalized
;
325 JITTargetAddress Addr
;
328 std::vector
<EHFrame
> UnfinalizedEHFrames
;
329 std::vector
<EHFrame
> RegisteredEHFrames
;
332 /// Remote indirect stubs manager.
333 class RemoteIndirectStubsManager
: public IndirectStubsManager
{
335 RemoteIndirectStubsManager(OrcRemoteTargetClient
&Client
,
336 ResourceIdMgr::ResourceId Id
)
337 : Client(Client
), Id(Id
) {}
339 ~RemoteIndirectStubsManager() override
{
340 Client
.destroyIndirectStubsManager(Id
);
343 Error
createStub(StringRef StubName
, JITTargetAddress StubAddr
,
344 JITSymbolFlags StubFlags
) override
{
345 if (auto Err
= reserveStubs(1))
348 return createStubInternal(StubName
, StubAddr
, StubFlags
);
351 Error
createStubs(const StubInitsMap
&StubInits
) override
{
352 if (auto Err
= reserveStubs(StubInits
.size()))
355 for (auto &Entry
: StubInits
)
356 if (auto Err
= createStubInternal(Entry
.first(), Entry
.second
.first
,
357 Entry
.second
.second
))
360 return Error::success();
363 JITEvaluatedSymbol
findStub(StringRef Name
, bool ExportedStubsOnly
) override
{
364 auto I
= StubIndexes
.find(Name
);
365 if (I
== StubIndexes
.end())
367 auto Key
= I
->second
.first
;
368 auto Flags
= I
->second
.second
;
369 auto StubSymbol
= JITEvaluatedSymbol(getStubAddr(Key
), Flags
);
370 if (ExportedStubsOnly
&& !StubSymbol
.getFlags().isExported())
375 JITEvaluatedSymbol
findPointer(StringRef Name
) override
{
376 auto I
= StubIndexes
.find(Name
);
377 if (I
== StubIndexes
.end())
379 auto Key
= I
->second
.first
;
380 auto Flags
= I
->second
.second
;
381 return JITEvaluatedSymbol(getPtrAddr(Key
), Flags
);
384 Error
updatePointer(StringRef Name
, JITTargetAddress NewAddr
) override
{
385 auto I
= StubIndexes
.find(Name
);
386 assert(I
!= StubIndexes
.end() && "No stub pointer for symbol");
387 auto Key
= I
->second
.first
;
388 return Client
.writePointer(getPtrAddr(Key
), NewAddr
);
392 struct RemoteIndirectStubsInfo
{
393 JITTargetAddress StubBase
;
394 JITTargetAddress PtrBase
;
398 using StubKey
= std::pair
<uint16_t, uint16_t>;
400 Error
reserveStubs(unsigned NumStubs
) {
401 if (NumStubs
<= FreeStubs
.size())
402 return Error::success();
404 unsigned NewStubsRequired
= NumStubs
- FreeStubs
.size();
405 JITTargetAddress StubBase
;
406 JITTargetAddress PtrBase
;
407 unsigned NumStubsEmitted
;
409 if (auto StubInfoOrErr
= Client
.emitIndirectStubs(Id
, NewStubsRequired
))
410 std::tie(StubBase
, PtrBase
, NumStubsEmitted
) = *StubInfoOrErr
;
412 return StubInfoOrErr
.takeError();
414 unsigned NewBlockId
= RemoteIndirectStubsInfos
.size();
415 RemoteIndirectStubsInfos
.push_back({StubBase
, PtrBase
, NumStubsEmitted
});
417 for (unsigned I
= 0; I
< NumStubsEmitted
; ++I
)
418 FreeStubs
.push_back(std::make_pair(NewBlockId
, I
));
420 return Error::success();
423 Error
createStubInternal(StringRef StubName
, JITTargetAddress InitAddr
,
424 JITSymbolFlags StubFlags
) {
425 auto Key
= FreeStubs
.back();
426 FreeStubs
.pop_back();
427 StubIndexes
[StubName
] = std::make_pair(Key
, StubFlags
);
428 return Client
.writePointer(getPtrAddr(Key
), InitAddr
);
431 JITTargetAddress
getStubAddr(StubKey K
) {
432 assert(RemoteIndirectStubsInfos
[K
.first
].StubBase
!= 0 &&
433 "Missing stub address");
434 return RemoteIndirectStubsInfos
[K
.first
].StubBase
+
435 K
.second
* Client
.getIndirectStubSize();
438 JITTargetAddress
getPtrAddr(StubKey K
) {
439 assert(RemoteIndirectStubsInfos
[K
.first
].PtrBase
!= 0 &&
440 "Missing pointer address");
441 return RemoteIndirectStubsInfos
[K
.first
].PtrBase
+
442 K
.second
* Client
.getPointerSize();
445 OrcRemoteTargetClient
&Client
;
446 ResourceIdMgr::ResourceId Id
;
447 std::vector
<RemoteIndirectStubsInfo
> RemoteIndirectStubsInfos
;
448 std::vector
<StubKey
> FreeStubs
;
449 StringMap
<std::pair
<StubKey
, JITSymbolFlags
>> StubIndexes
;
452 class RemoteTrampolinePool
: public TrampolinePool
{
454 RemoteTrampolinePool(OrcRemoteTargetClient
&Client
) : Client(Client
) {}
456 Expected
<JITTargetAddress
> getTrampoline() override
{
457 std::lock_guard
<std::mutex
> Lock(RTPMutex
);
458 if (AvailableTrampolines
.empty()) {
459 if (auto Err
= grow())
460 return std::move(Err
);
462 assert(!AvailableTrampolines
.empty() && "Failed to grow trampoline pool");
463 auto TrampolineAddr
= AvailableTrampolines
.back();
464 AvailableTrampolines
.pop_back();
465 return TrampolineAddr
;
470 JITTargetAddress BlockAddr
= 0;
471 uint32_t NumTrampolines
= 0;
472 if (auto TrampolineInfoOrErr
= Client
.emitTrampolineBlock())
473 std::tie(BlockAddr
, NumTrampolines
) = *TrampolineInfoOrErr
;
475 return TrampolineInfoOrErr
.takeError();
477 uint32_t TrampolineSize
= Client
.getTrampolineSize();
478 for (unsigned I
= 0; I
< NumTrampolines
; ++I
)
479 this->AvailableTrampolines
.push_back(BlockAddr
+ (I
* TrampolineSize
));
481 return Error::success();
485 OrcRemoteTargetClient
&Client
;
486 std::vector
<JITTargetAddress
> AvailableTrampolines
;
489 /// Remote compile callback manager.
490 class RemoteCompileCallbackManager
: public JITCompileCallbackManager
{
492 RemoteCompileCallbackManager(OrcRemoteTargetClient
&Client
,
493 ExecutionSession
&ES
,
494 JITTargetAddress ErrorHandlerAddress
)
495 : JITCompileCallbackManager(
496 std::make_unique
<RemoteTrampolinePool
>(Client
), ES
,
497 ErrorHandlerAddress
) {}
500 /// Create an OrcRemoteTargetClient.
501 /// Channel is the ChannelT instance to communicate on. It is assumed that
502 /// the channel is ready to be read from and written to.
503 static Expected
<std::unique_ptr
<OrcRemoteTargetClient
>>
504 Create(rpc::RawByteChannel
&Channel
, ExecutionSession
&ES
) {
505 Error Err
= Error::success();
506 auto Client
= std::unique_ptr
<OrcRemoteTargetClient
>(
507 new OrcRemoteTargetClient(Channel
, ES
, Err
));
509 return std::move(Err
);
510 return std::move(Client
);
513 /// Call the int(void) function at the given address in the target and return
515 Expected
<int> callIntVoid(JITTargetAddress Addr
) {
516 LLVM_DEBUG(dbgs() << "Calling int(*)(void) "
517 << format("0x%016" PRIx64
, Addr
) << "\n");
518 return callB
<exec::CallIntVoid
>(Addr
);
521 /// Call the int(int, char*[]) function at the given address in the target and
522 /// return its result.
523 Expected
<int> callMain(JITTargetAddress Addr
,
524 const std::vector
<std::string
> &Args
) {
525 LLVM_DEBUG(dbgs() << "Calling int(*)(int, char*[]) "
526 << format("0x%016" PRIx64
, Addr
) << "\n");
527 return callB
<exec::CallMain
>(Addr
, Args
);
530 /// Call the void() function at the given address in the target and wait for
532 Error
callVoidVoid(JITTargetAddress Addr
) {
533 LLVM_DEBUG(dbgs() << "Calling void(*)(void) "
534 << format("0x%016" PRIx64
, Addr
) << "\n");
535 return callB
<exec::CallVoidVoid
>(Addr
);
538 /// Create an RCMemoryManager which will allocate its memory on the remote
540 Expected
<std::unique_ptr
<RemoteRTDyldMemoryManager
>>
541 createRemoteMemoryManager() {
542 auto Id
= AllocatorIds
.getNext();
543 if (auto Err
= callB
<mem::CreateRemoteAllocator
>(Id
))
544 return std::move(Err
);
545 return std::unique_ptr
<RemoteRTDyldMemoryManager
>(
546 new RemoteRTDyldMemoryManager(*this, Id
));
549 /// Create an RCIndirectStubsManager that will allocate stubs on the remote
551 Expected
<std::unique_ptr
<RemoteIndirectStubsManager
>>
552 createIndirectStubsManager() {
553 auto Id
= IndirectStubOwnerIds
.getNext();
554 if (auto Err
= callB
<stubs::CreateIndirectStubsOwner
>(Id
))
555 return std::move(Err
);
556 return std::make_unique
<RemoteIndirectStubsManager
>(*this, Id
);
559 Expected
<RemoteCompileCallbackManager
&>
560 enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress
) {
561 assert(!CallbackManager
&& "CallbackManager already obtained");
563 // Emit the resolver block on the JIT server.
564 if (auto Err
= callB
<stubs::EmitResolverBlock
>())
565 return std::move(Err
);
567 // Create the callback manager.
568 CallbackManager
.emplace(*this, ES
, ErrorHandlerAddress
);
569 RemoteCompileCallbackManager
&Mgr
= *CallbackManager
;
573 /// Search for symbols in the remote process. Note: This should be used by
574 /// symbol resolvers *after* they've searched the local symbol table in the
576 Expected
<JITTargetAddress
> getSymbolAddress(StringRef Name
) {
577 return callB
<utils::GetSymbolAddress
>(Name
);
580 /// Get the triple for the remote target.
581 const std::string
&getTargetTriple() const { return RemoteTargetTriple
; }
583 Error
terminateSession() { return callB
<utils::TerminateSession
>(); }
586 OrcRemoteTargetClient(rpc::RawByteChannel
&Channel
, ExecutionSession
&ES
,
588 : rpc::SingleThreadedRPCEndpoint
<rpc::RawByteChannel
>(Channel
, true),
590 ErrorAsOutParameter
EAO(&Err
);
592 addHandler
<utils::RequestCompile
>(
593 [this](JITTargetAddress Addr
) -> JITTargetAddress
{
595 return CallbackManager
->executeCompileCallback(Addr
);
599 if (auto RIOrErr
= callB
<utils::GetRemoteInfo
>()) {
600 std::tie(RemoteTargetTriple
, RemotePointerSize
, RemotePageSize
,
601 RemoteTrampolineSize
, RemoteIndirectStubSize
) = *RIOrErr
;
602 Err
= Error::success();
604 Err
= RIOrErr
.takeError();
607 void deregisterEHFrames(JITTargetAddress Addr
, uint32_t Size
) {
608 if (auto Err
= callB
<eh::RegisterEHFrames
>(Addr
, Size
))
609 ES
.reportError(std::move(Err
));
612 void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id
) {
613 if (auto Err
= callB
<mem::DestroyRemoteAllocator
>(Id
)) {
614 // FIXME: This will be triggered by a removeModuleSet call: Propagate
615 // error return up through that.
616 llvm_unreachable("Failed to destroy remote allocator.");
617 AllocatorIds
.release(Id
);
621 void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id
) {
622 IndirectStubOwnerIds
.release(Id
);
623 if (auto Err
= callB
<stubs::DestroyIndirectStubsOwner
>(Id
))
624 ES
.reportError(std::move(Err
));
627 Expected
<std::tuple
<JITTargetAddress
, JITTargetAddress
, uint32_t>>
628 emitIndirectStubs(ResourceIdMgr::ResourceId Id
, uint32_t NumStubsRequired
) {
629 return callB
<stubs::EmitIndirectStubs
>(Id
, NumStubsRequired
);
632 Expected
<std::tuple
<JITTargetAddress
, uint32_t>> emitTrampolineBlock() {
633 return callB
<stubs::EmitTrampolineBlock
>();
636 uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize
; }
637 uint32_t getPageSize() const { return RemotePageSize
; }
638 uint32_t getPointerSize() const { return RemotePointerSize
; }
640 uint32_t getTrampolineSize() const { return RemoteTrampolineSize
; }
642 Expected
<std::vector
<uint8_t>> readMem(char *Dst
, JITTargetAddress Src
,
644 return callB
<mem::ReadMem
>(Src
, Size
);
647 Error
registerEHFrames(JITTargetAddress
&RAddr
, uint32_t Size
) {
648 // FIXME: Duplicate error and report it via ReportError too?
649 return callB
<eh::RegisterEHFrames
>(RAddr
, Size
);
652 JITTargetAddress
reserveMem(ResourceIdMgr::ResourceId Id
, uint64_t Size
,
654 if (auto AddrOrErr
= callB
<mem::ReserveMem
>(Id
, Size
, Align
))
657 ES
.reportError(AddrOrErr
.takeError());
662 bool setProtections(ResourceIdMgr::ResourceId Id
,
663 JITTargetAddress RemoteSegAddr
, unsigned ProtFlags
) {
664 if (auto Err
= callB
<mem::SetProtections
>(Id
, RemoteSegAddr
, ProtFlags
)) {
665 ES
.reportError(std::move(Err
));
671 bool writeMem(JITTargetAddress Addr
, const char *Src
, uint64_t Size
) {
672 if (auto Err
= callB
<mem::WriteMem
>(DirectBufferWriter(Src
, Addr
, Size
))) {
673 ES
.reportError(std::move(Err
));
679 Error
writePointer(JITTargetAddress Addr
, JITTargetAddress PtrVal
) {
680 return callB
<mem::WritePtr
>(Addr
, PtrVal
);
683 static Error
doNothing() { return Error::success(); }
685 ExecutionSession
&ES
;
686 std::function
<void(Error
)> ReportError
;
687 std::string RemoteTargetTriple
;
688 uint32_t RemotePointerSize
= 0;
689 uint32_t RemotePageSize
= 0;
690 uint32_t RemoteTrampolineSize
= 0;
691 uint32_t RemoteIndirectStubSize
= 0;
692 ResourceIdMgr AllocatorIds
, IndirectStubOwnerIds
;
693 Optional
<RemoteCompileCallbackManager
> CallbackManager
;
696 } // end namespace remote
697 } // end namespace orc
698 } // end namespace llvm
702 #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H