[Alignment][NFC] Use Align with TargetLowering::setMinFunctionAlignment
[llvm-core.git] / include / llvm / ExecutionEngine / Orc / OrcRemoteTargetClient.h
blob86e8d5df3ad93ac9bd36854fb2cdb3d4baf1a2c1
1 //===- OrcRemoteTargetClient.h - Orc Remote-target Client -------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
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"
33 #include <algorithm>
34 #include <cassert>
35 #include <cstdint>
36 #include <memory>
37 #include <string>
38 #include <tuple>
39 #include <utility>
40 #include <vector>
42 #define DEBUG_TYPE "orc-remote"
44 namespace llvm {
45 namespace orc {
46 namespace remote {
48 /// This class provides utilities (including memory manager, indirect stubs
49 /// manager, and compile callback manager types) that support remote JITing
50 /// in ORC.
51 ///
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
54 /// its actions.
55 class OrcRemoteTargetClient
56 : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
57 public:
58 /// Remote-mapped RuntimeDyld-compatible memory manager.
59 class RemoteRTDyldMemoryManager : public RuntimeDyld::MemoryManager {
60 friend class OrcRemoteTargetClient;
62 public:
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,
75 unsigned SectionID,
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");
83 return Alloc;
86 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
87 unsigned SectionID, StringRef SectionName,
88 bool IsReadOnly) override {
89 if (IsReadOnly) {
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");
96 return Alloc;
97 } // else...
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");
105 return Alloc;
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");
116 if (CodeSize != 0) {
117 Unmapped.back().RemoteCodeAddr =
118 Client.reserveMem(Id, CodeSize, CodeAlign);
120 LLVM_DEBUG(
121 dbgs() << " code: "
122 << format("0x%016" PRIx64, Unmapped.back().RemoteCodeAddr)
123 << " (" << CodeSize << " bytes, alignment " << CodeAlign
124 << ")\n");
127 if (RODataSize != 0) {
128 Unmapped.back().RemoteRODataAddr =
129 Client.reserveMem(Id, RODataSize, RODataAlign);
131 LLVM_DEBUG(
132 dbgs() << " ro-data: "
133 << format("0x%016" PRIx64, Unmapped.back().RemoteRODataAddr)
134 << " (" << RODataSize << " bytes, alignment " << RODataAlign
135 << ")\n");
138 if (RWDataSize != 0) {
139 Unmapped.back().RemoteRWDataAddr =
140 Client.reserveMem(Id, RWDataSize, RWDataAlign);
142 LLVM_DEBUG(
143 dbgs() << " rw-data: "
144 << format("0x%016" PRIx64, Unmapped.back().RemoteRWDataAddr)
145 << " (" << RWDataSize << " bytes, alignment " << RWDataAlign
146 << ")\n");
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));
176 Unmapped.clear();
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))
185 return true;
187 if (copyAndProtect(ObjAllocs.RODataAllocs, ObjAllocs.RemoteRODataAddr,
188 sys::Memory::MF_READ))
189 return true;
191 if (copyAndProtect(ObjAllocs.RWDataAllocs, ObjAllocs.RemoteRWDataAddr,
192 sys::Memory::MF_READ | sys::Memory::MF_WRITE))
193 return true;
195 Unfinalized.clear();
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) {
201 if (ErrMsg) {
202 raw_string_ostream ErrOut(*ErrMsg);
203 EIB.log(ErrOut);
206 return false;
209 RegisteredEHFrames = std::move(UnfinalizedEHFrames);
210 UnfinalizedEHFrames = {};
212 return false;
215 private:
216 class Alloc {
217 public:
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; }
242 private:
243 uint64_t Size;
244 unsigned Align;
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);
274 LLVM_DEBUG(
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.
281 if (NextAddr)
282 NextAddr += Alloc.getSize();
286 // Copies data for each alloc in the list, then set permissions on the
287 // segment.
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())
297 << " -> "
298 << format("0x%016" PRIx64, Alloc.getRemoteAddress())
299 << " (" << Alloc.getSize() << " bytes)\n";);
301 if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
302 Alloc.getSize()))
303 return true;
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)
312 << "\n");
313 if (Client.setProtections(Id, RemoteSegmentAddr, Permissions))
314 return true;
316 return false;
319 OrcRemoteTargetClient &Client;
320 ResourceIdMgr::ResourceId Id;
321 std::vector<ObjectAllocs> Unmapped;
322 std::vector<ObjectAllocs> Unfinalized;
324 struct EHFrame {
325 JITTargetAddress Addr;
326 uint64_t Size;
328 std::vector<EHFrame> UnfinalizedEHFrames;
329 std::vector<EHFrame> RegisteredEHFrames;
332 /// Remote indirect stubs manager.
333 class RemoteIndirectStubsManager : public IndirectStubsManager {
334 public:
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))
346 return Err;
348 return createStubInternal(StubName, StubAddr, StubFlags);
351 Error createStubs(const StubInitsMap &StubInits) override {
352 if (auto Err = reserveStubs(StubInits.size()))
353 return Err;
355 for (auto &Entry : StubInits)
356 if (auto Err = createStubInternal(Entry.first(), Entry.second.first,
357 Entry.second.second))
358 return Err;
360 return Error::success();
363 JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
364 auto I = StubIndexes.find(Name);
365 if (I == StubIndexes.end())
366 return nullptr;
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())
371 return nullptr;
372 return StubSymbol;
375 JITEvaluatedSymbol findPointer(StringRef Name) override {
376 auto I = StubIndexes.find(Name);
377 if (I == StubIndexes.end())
378 return nullptr;
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);
391 private:
392 struct RemoteIndirectStubsInfo {
393 JITTargetAddress StubBase;
394 JITTargetAddress PtrBase;
395 unsigned NumStubs;
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;
411 else
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 {
453 public:
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;
468 private:
469 Error grow() {
470 JITTargetAddress BlockAddr = 0;
471 uint32_t NumTrampolines = 0;
472 if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock())
473 std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
474 else
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();
484 std::mutex RTPMutex;
485 OrcRemoteTargetClient &Client;
486 std::vector<JITTargetAddress> AvailableTrampolines;
489 /// Remote compile callback manager.
490 class RemoteCompileCallbackManager : public JITCompileCallbackManager {
491 public:
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));
508 if (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
514 /// its result.
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
531 /// it to finish.
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
539 /// target.
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
550 /// target.
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;
570 return Mgr;
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
575 /// JIT stack.
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>(); }
585 private:
586 OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES,
587 Error &Err)
588 : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
589 ES(ES) {
590 ErrorAsOutParameter EAO(&Err);
592 addHandler<utils::RequestCompile>(
593 [this](JITTargetAddress Addr) -> JITTargetAddress {
594 if (CallbackManager)
595 return CallbackManager->executeCompileCallback(Addr);
596 return 0;
599 if (auto RIOrErr = callB<utils::GetRemoteInfo>()) {
600 std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
601 RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
602 Err = Error::success();
603 } else
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,
643 uint64_t Size) {
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,
653 uint32_t Align) {
654 if (auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align))
655 return *AddrOrErr;
656 else {
657 ES.reportError(AddrOrErr.takeError());
658 return 0;
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));
666 return true;
667 } else
668 return false;
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));
674 return true;
675 } else
676 return false;
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
700 #undef DEBUG_TYPE
702 #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H