blob: 7179e5ff66fdd6ed78e72599bce49762bccc60e6 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- OrcRemoteTargetClient.h - Orc Remote-target Client -------*- 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 OrcRemoteTargetClient class and helpers. This class
11// can be used to communicate over an RawByteChannel with an
12// OrcRemoteTargetServer instance to support remote-JITing.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
17#define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
18
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"
34#include <algorithm>
35#include <cassert>
36#include <cstdint>
37#include <memory>
38#include <string>
39#include <tuple>
40#include <utility>
41#include <vector>
42
43#define DEBUG_TYPE "orc-remote"
44
45namespace llvm {
46namespace orc {
47namespace remote {
48
49/// This class provides utilities (including memory manager, indirect stubs
50/// manager, and compile callback manager types) that support remote JITing
51/// in ORC.
52///
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
55/// its actions.
56class OrcRemoteTargetClient
57 : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
58public:
59 /// Remote-mapped RuntimeDyld-compatible memory manager.
60 class RemoteRTDyldMemoryManager : public RuntimeDyld::MemoryManager {
61 friend class OrcRemoteTargetClient;
62
63 public:
64 ~RemoteRTDyldMemoryManager() {
65 Client.destroyRemoteAllocator(Id);
66 DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
67 }
68
69 RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &) = delete;
70 RemoteRTDyldMemoryManager &
71 operator=(const RemoteRTDyldMemoryManager &) = delete;
72 RemoteRTDyldMemoryManager(RemoteRTDyldMemoryManager &&) = default;
73 RemoteRTDyldMemoryManager &
74 operator=(RemoteRTDyldMemoryManager &&) = default;
75
76 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
77 unsigned SectionID,
78 StringRef SectionName) override {
79 Unmapped.back().CodeAllocs.emplace_back(Size, Alignment);
80 uint8_t *Alloc = reinterpret_cast<uint8_t *>(
81 Unmapped.back().CodeAllocs.back().getLocalAddress());
82 DEBUG(dbgs() << "Allocator " << Id << " allocated code for "
83 << SectionName << ": " << Alloc << " (" << Size
84 << " bytes, alignment " << Alignment << ")\n");
85 return Alloc;
86 }
87
88 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
89 unsigned SectionID, StringRef SectionName,
90 bool IsReadOnly) override {
91 if (IsReadOnly) {
92 Unmapped.back().RODataAllocs.emplace_back(Size, Alignment);
93 uint8_t *Alloc = reinterpret_cast<uint8_t *>(
94 Unmapped.back().RODataAllocs.back().getLocalAddress());
95 DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for "
96 << SectionName << ": " << Alloc << " (" << Size
97 << " bytes, alignment " << Alignment << ")\n");
98 return Alloc;
99 } // else...
100
101 Unmapped.back().RWDataAllocs.emplace_back(Size, Alignment);
102 uint8_t *Alloc = reinterpret_cast<uint8_t *>(
103 Unmapped.back().RWDataAllocs.back().getLocalAddress());
104 DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for "
105 << SectionName << ": " << Alloc << " (" << Size
106 << " bytes, alignment " << Alignment << ")\n");
107 return Alloc;
108 }
109
110 void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
111 uintptr_t RODataSize, uint32_t RODataAlign,
112 uintptr_t RWDataSize,
113 uint32_t RWDataAlign) override {
114 Unmapped.push_back(ObjectAllocs());
115
116 DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
117
118 if (CodeSize != 0) {
119 Unmapped.back().RemoteCodeAddr =
120 Client.reserveMem(Id, CodeSize, CodeAlign);
121
122 DEBUG(dbgs() << " code: "
123 << format("0x%016x", Unmapped.back().RemoteCodeAddr)
124 << " (" << CodeSize << " bytes, alignment " << CodeAlign
125 << ")\n");
126 }
127
128 if (RODataSize != 0) {
129 Unmapped.back().RemoteRODataAddr =
130 Client.reserveMem(Id, RODataSize, RODataAlign);
131
132 DEBUG(dbgs() << " ro-data: "
133 << format("0x%016x", Unmapped.back().RemoteRODataAddr)
134 << " (" << RODataSize << " bytes, alignment "
135 << RODataAlign << ")\n");
136 }
137
138 if (RWDataSize != 0) {
139 Unmapped.back().RemoteRWDataAddr =
140 Client.reserveMem(Id, RWDataSize, RWDataAlign);
141
142 DEBUG(dbgs() << " rw-data: "
143 << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
144 << " (" << RWDataSize << " bytes, alignment "
145 << RWDataAlign << ")\n");
146 }
147 }
148
149 bool needsToReserveAllocationSpace() override { return true; }
150
151 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
152 size_t Size) override {
153 UnfinalizedEHFrames.push_back({LoadAddr, Size});
154 }
155
156 void deregisterEHFrames() override {
157 for (auto &Frame : RegisteredEHFrames) {
158 // FIXME: Add error poll.
159 Client.deregisterEHFrames(Frame.Addr, Frame.Size);
160 }
161 }
162
163 void notifyObjectLoaded(RuntimeDyld &Dyld,
164 const object::ObjectFile &Obj) override {
165 DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
166 for (auto &ObjAllocs : Unmapped) {
167 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,
168 ObjAllocs.RemoteCodeAddr);
169 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs,
170 ObjAllocs.RemoteRODataAddr);
171 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs,
172 ObjAllocs.RemoteRWDataAddr);
173 Unfinalized.push_back(std::move(ObjAllocs));
174 }
175 Unmapped.clear();
176 }
177
178 bool finalizeMemory(std::string *ErrMsg = nullptr) override {
179 DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
180
181 for (auto &ObjAllocs : Unfinalized) {
182 if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr,
183 sys::Memory::MF_READ | sys::Memory::MF_EXEC))
184 return true;
185
186 if (copyAndProtect(ObjAllocs.RODataAllocs, ObjAllocs.RemoteRODataAddr,
187 sys::Memory::MF_READ))
188 return true;
189
190 if (copyAndProtect(ObjAllocs.RWDataAllocs, ObjAllocs.RemoteRWDataAddr,
191 sys::Memory::MF_READ | sys::Memory::MF_WRITE))
192 return true;
193 }
194 Unfinalized.clear();
195
196 for (auto &EHFrame : UnfinalizedEHFrames) {
197 if (auto Err = Client.registerEHFrames(EHFrame.Addr, EHFrame.Size)) {
198 // FIXME: Replace this once finalizeMemory can return an Error.
199 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
200 if (ErrMsg) {
201 raw_string_ostream ErrOut(*ErrMsg);
202 EIB.log(ErrOut);
203 }
204 });
205 return false;
206 }
207 }
208 RegisteredEHFrames = std::move(UnfinalizedEHFrames);
209 UnfinalizedEHFrames = {};
210
211 return false;
212 }
213
214 private:
215 class Alloc {
216 public:
217 Alloc(uint64_t Size, unsigned Align)
218 : Size(Size), Align(Align), Contents(new char[Size + Align - 1]) {}
219
220 Alloc(const Alloc &) = delete;
221 Alloc &operator=(const Alloc &) = delete;
222 Alloc(Alloc &&) = default;
223 Alloc &operator=(Alloc &&) = default;
224
225 uint64_t getSize() const { return Size; }
226
227 unsigned getAlign() const { return Align; }
228
229 char *getLocalAddress() const {
230 uintptr_t LocalAddr = reinterpret_cast<uintptr_t>(Contents.get());
231 LocalAddr = alignTo(LocalAddr, Align);
232 return reinterpret_cast<char *>(LocalAddr);
233 }
234
235 void setRemoteAddress(JITTargetAddress RemoteAddr) {
236 this->RemoteAddr = RemoteAddr;
237 }
238
239 JITTargetAddress getRemoteAddress() const { return RemoteAddr; }
240
241 private:
242 uint64_t Size;
243 unsigned Align;
244 std::unique_ptr<char[]> Contents;
245 JITTargetAddress RemoteAddr = 0;
246 };
247
248 struct ObjectAllocs {
249 ObjectAllocs() = default;
250 ObjectAllocs(const ObjectAllocs &) = delete;
251 ObjectAllocs &operator=(const ObjectAllocs &) = delete;
252 ObjectAllocs(ObjectAllocs &&) = default;
253 ObjectAllocs &operator=(ObjectAllocs &&) = default;
254
255 JITTargetAddress RemoteCodeAddr = 0;
256 JITTargetAddress RemoteRODataAddr = 0;
257 JITTargetAddress RemoteRWDataAddr = 0;
258 std::vector<Alloc> CodeAllocs, RODataAllocs, RWDataAllocs;
259 };
260
261 RemoteRTDyldMemoryManager(OrcRemoteTargetClient &Client,
262 ResourceIdMgr::ResourceId Id)
263 : Client(Client), Id(Id) {
264 DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
265 }
266
267 // Maps all allocations in Allocs to aligned blocks
268 void mapAllocsToRemoteAddrs(RuntimeDyld &Dyld, std::vector<Alloc> &Allocs,
269 JITTargetAddress NextAddr) {
270 for (auto &Alloc : Allocs) {
271 NextAddr = alignTo(NextAddr, Alloc.getAlign());
272 Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr);
273 DEBUG(dbgs() << " " << static_cast<void *>(Alloc.getLocalAddress())
274 << " -> " << format("0x%016x", NextAddr) << "\n");
275 Alloc.setRemoteAddress(NextAddr);
276
277 // Only advance NextAddr if it was non-null to begin with,
278 // otherwise leave it as null.
279 if (NextAddr)
280 NextAddr += Alloc.getSize();
281 }
282 }
283
284 // Copies data for each alloc in the list, then set permissions on the
285 // segment.
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");
291
292 for (auto &Alloc : Allocs) {
293 DEBUG(dbgs() << " copying section: "
294 << static_cast<void *>(Alloc.getLocalAddress()) << " -> "
295 << format("0x%016x", Alloc.getRemoteAddress()) << " ("
296 << Alloc.getSize() << " bytes)\n";);
297
298 if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
299 Alloc.getSize()))
300 return true;
301 }
302
303 DEBUG(dbgs() << " setting "
304 << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
305 << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
306 << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
307 << " permissions on block: "
308 << format("0x%016x", RemoteSegmentAddr) << "\n");
309 if (Client.setProtections(Id, RemoteSegmentAddr, Permissions))
310 return true;
311 }
312 return false;
313 }
314
315 OrcRemoteTargetClient &Client;
316 ResourceIdMgr::ResourceId Id;
317 std::vector<ObjectAllocs> Unmapped;
318 std::vector<ObjectAllocs> Unfinalized;
319
320 struct EHFrame {
321 JITTargetAddress Addr;
322 uint64_t Size;
323 };
324 std::vector<EHFrame> UnfinalizedEHFrames;
325 std::vector<EHFrame> RegisteredEHFrames;
326 };
327
328 /// Remote indirect stubs manager.
329 class RemoteIndirectStubsManager : public IndirectStubsManager {
330 public:
331 RemoteIndirectStubsManager(OrcRemoteTargetClient &Client,
332 ResourceIdMgr::ResourceId Id)
333 : Client(Client), Id(Id) {}
334
335 ~RemoteIndirectStubsManager() override {
336 Client.destroyIndirectStubsManager(Id);
337 }
338
339 Error createStub(StringRef StubName, JITTargetAddress StubAddr,
340 JITSymbolFlags StubFlags) override {
341 if (auto Err = reserveStubs(1))
342 return Err;
343
344 return createStubInternal(StubName, StubAddr, StubFlags);
345 }
346
347 Error createStubs(const StubInitsMap &StubInits) override {
348 if (auto Err = reserveStubs(StubInits.size()))
349 return Err;
350
351 for (auto &Entry : StubInits)
352 if (auto Err = createStubInternal(Entry.first(), Entry.second.first,
353 Entry.second.second))
354 return Err;
355
356 return Error::success();
357 }
358
359 JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
360 auto I = StubIndexes.find(Name);
361 if (I == StubIndexes.end())
362 return nullptr;
363 auto Key = I->second.first;
364 auto Flags = I->second.second;
365 auto StubSymbol = JITSymbol(getStubAddr(Key), Flags);
366 if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
367 return nullptr;
368 return StubSymbol;
369 }
370
371 JITSymbol findPointer(StringRef Name) override {
372 auto I = StubIndexes.find(Name);
373 if (I == StubIndexes.end())
374 return nullptr;
375 auto Key = I->second.first;
376 auto Flags = I->second.second;
377 return JITSymbol(getPtrAddr(Key), Flags);
378 }
379
380 Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
381 auto I = StubIndexes.find(Name);
382 assert(I != StubIndexes.end() && "No stub pointer for symbol");
383 auto Key = I->second.first;
384 return Client.writePointer(getPtrAddr(Key), NewAddr);
385 }
386
387 private:
388 struct RemoteIndirectStubsInfo {
389 JITTargetAddress StubBase;
390 JITTargetAddress PtrBase;
391 unsigned NumStubs;
392 };
393
394 using StubKey = std::pair<uint16_t, uint16_t>;
395
396 Error reserveStubs(unsigned NumStubs) {
397 if (NumStubs <= FreeStubs.size())
398 return Error::success();
399
400 unsigned NewStubsRequired = NumStubs - FreeStubs.size();
401 JITTargetAddress StubBase;
402 JITTargetAddress PtrBase;
403 unsigned NumStubsEmitted;
404
405 if (auto StubInfoOrErr = Client.emitIndirectStubs(Id, NewStubsRequired))
406 std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
407 else
408 return StubInfoOrErr.takeError();
409
410 unsigned NewBlockId = RemoteIndirectStubsInfos.size();
411 RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted});
412
413 for (unsigned I = 0; I < NumStubsEmitted; ++I)
414 FreeStubs.push_back(std::make_pair(NewBlockId, I));
415
416 return Error::success();
417 }
418
419 Error createStubInternal(StringRef StubName, JITTargetAddress InitAddr,
420 JITSymbolFlags StubFlags) {
421 auto Key = FreeStubs.back();
422 FreeStubs.pop_back();
423 StubIndexes[StubName] = std::make_pair(Key, StubFlags);
424 return Client.writePointer(getPtrAddr(Key), InitAddr);
425 }
426
427 JITTargetAddress getStubAddr(StubKey K) {
428 assert(RemoteIndirectStubsInfos[K.first].StubBase != 0 &&
429 "Missing stub address");
430 return RemoteIndirectStubsInfos[K.first].StubBase +
431 K.second * Client.getIndirectStubSize();
432 }
433
434 JITTargetAddress getPtrAddr(StubKey K) {
435 assert(RemoteIndirectStubsInfos[K.first].PtrBase != 0 &&
436 "Missing pointer address");
437 return RemoteIndirectStubsInfos[K.first].PtrBase +
438 K.second * Client.getPointerSize();
439 }
440
441 OrcRemoteTargetClient &Client;
442 ResourceIdMgr::ResourceId Id;
443 std::vector<RemoteIndirectStubsInfo> RemoteIndirectStubsInfos;
444 std::vector<StubKey> FreeStubs;
445 StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
446 };
447
448 /// Remote compile callback manager.
449 class RemoteCompileCallbackManager : public JITCompileCallbackManager {
450 public:
451 RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
452 JITTargetAddress ErrorHandlerAddress)
453 : JITCompileCallbackManager(ErrorHandlerAddress), Client(Client) {}
454
455 private:
456 Error grow() override {
457 JITTargetAddress BlockAddr = 0;
458 uint32_t NumTrampolines = 0;
459 if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock())
460 std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
461 else
462 return TrampolineInfoOrErr.takeError();
463
464 uint32_t TrampolineSize = Client.getTrampolineSize();
465 for (unsigned I = 0; I < NumTrampolines; ++I)
466 this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize));
467
468 return Error::success();
469 }
470
471 OrcRemoteTargetClient &Client;
472 };
473
474 /// Create an OrcRemoteTargetClient.
475 /// Channel is the ChannelT instance to communicate on. It is assumed that
476 /// the channel is ready to be read from and written to.
477 static Expected<std::unique_ptr<OrcRemoteTargetClient>>
478 Create(rpc::RawByteChannel &Channel, std::function<void(Error)> ReportError) {
479 Error Err = Error::success();
480 auto Client = std::unique_ptr<OrcRemoteTargetClient>(
481 new OrcRemoteTargetClient(Channel, std::move(ReportError), Err));
482 if (Err)
483 return std::move(Err);
484 return std::move(Client);
485 }
486
487 /// Call the int(void) function at the given address in the target and return
488 /// its result.
489 Expected<int> callIntVoid(JITTargetAddress Addr) {
490 DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n");
491 return callB<exec::CallIntVoid>(Addr);
492 }
493
494 /// Call the int(int, char*[]) function at the given address in the target and
495 /// return its result.
496 Expected<int> callMain(JITTargetAddress Addr,
497 const std::vector<std::string> &Args) {
498 DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)
499 << "\n");
500 return callB<exec::CallMain>(Addr, Args);
501 }
502
503 /// Call the void() function at the given address in the target and wait for
504 /// it to finish.
505 Error callVoidVoid(JITTargetAddress Addr) {
506 DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
507 << "\n");
508 return callB<exec::CallVoidVoid>(Addr);
509 }
510
511 /// Create an RCMemoryManager which will allocate its memory on the remote
512 /// target.
513 Expected<std::unique_ptr<RemoteRTDyldMemoryManager>>
514 createRemoteMemoryManager() {
515 auto Id = AllocatorIds.getNext();
516 if (auto Err = callB<mem::CreateRemoteAllocator>(Id))
517 return std::move(Err);
518 return std::unique_ptr<RemoteRTDyldMemoryManager>(
519 new RemoteRTDyldMemoryManager(*this, Id));
520 }
521
522 /// Create an RCIndirectStubsManager that will allocate stubs on the remote
523 /// target.
524 Expected<std::unique_ptr<RemoteIndirectStubsManager>>
525 createIndirectStubsManager() {
526 auto Id = IndirectStubOwnerIds.getNext();
527 if (auto Err = callB<stubs::CreateIndirectStubsOwner>(Id))
528 return std::move(Err);
529 return llvm::make_unique<RemoteIndirectStubsManager>(*this, Id);
530 }
531
532 Expected<RemoteCompileCallbackManager &>
533 enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) {
534 // Emit the resolver block on the JIT server.
535 if (auto Err = callB<stubs::EmitResolverBlock>())
536 return std::move(Err);
537
538 // Create the callback manager.
539 CallbackManager.emplace(*this, ErrorHandlerAddress);
540 RemoteCompileCallbackManager &Mgr = *CallbackManager;
541 return Mgr;
542 }
543
544 /// Search for symbols in the remote process. Note: This should be used by
545 /// symbol resolvers *after* they've searched the local symbol table in the
546 /// JIT stack.
547 Expected<JITTargetAddress> getSymbolAddress(StringRef Name) {
548 return callB<utils::GetSymbolAddress>(Name);
549 }
550
551 /// Get the triple for the remote target.
552 const std::string &getTargetTriple() const { return RemoteTargetTriple; }
553
554 Error terminateSession() { return callB<utils::TerminateSession>(); }
555
556private:
557 OrcRemoteTargetClient(rpc::RawByteChannel &Channel,
558 std::function<void(Error)> ReportError, Error &Err)
559 : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
560 ReportError(std::move(ReportError)) {
561 ErrorAsOutParameter EAO(&Err);
562
563 addHandler<utils::RequestCompile>(
564 [this](JITTargetAddress Addr) -> JITTargetAddress {
565 if (CallbackManager)
566 return CallbackManager->executeCompileCallback(Addr);
567 return 0;
568 });
569
570 if (auto RIOrErr = callB<utils::GetRemoteInfo>()) {
571 std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
572 RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
573 Err = Error::success();
574 } else
575 Err = RIOrErr.takeError();
576 }
577
578 void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
579 if (auto Err = callB<eh::RegisterEHFrames>(Addr, Size))
580 ReportError(std::move(Err));
581 }
582
583 void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
584 if (auto Err = callB<mem::DestroyRemoteAllocator>(Id)) {
585 // FIXME: This will be triggered by a removeModuleSet call: Propagate
586 // error return up through that.
587 llvm_unreachable("Failed to destroy remote allocator.");
588 AllocatorIds.release(Id);
589 }
590 }
591
592 void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
593 IndirectStubOwnerIds.release(Id);
594 if (auto Err = callB<stubs::DestroyIndirectStubsOwner>(Id))
595 ReportError(std::move(Err));
596 }
597
598 Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
599 emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) {
600 return callB<stubs::EmitIndirectStubs>(Id, NumStubsRequired);
601 }
602
603 Expected<std::tuple<JITTargetAddress, uint32_t>> emitTrampolineBlock() {
604 return callB<stubs::EmitTrampolineBlock>();
605 }
606
607 uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
608 uint32_t getPageSize() const { return RemotePageSize; }
609 uint32_t getPointerSize() const { return RemotePointerSize; }
610
611 uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
612
613 Expected<std::vector<uint8_t>> readMem(char *Dst, JITTargetAddress Src,
614 uint64_t Size) {
615 return callB<mem::ReadMem>(Src, Size);
616 }
617
618 Error registerEHFrames(JITTargetAddress &RAddr, uint32_t Size) {
619 // FIXME: Duplicate error and report it via ReportError too?
620 return callB<eh::RegisterEHFrames>(RAddr, Size);
621 }
622
623 JITTargetAddress reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
624 uint32_t Align) {
625 if (auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align))
626 return *AddrOrErr;
627 else {
628 ReportError(AddrOrErr.takeError());
629 return 0;
630 }
631 }
632
633 bool setProtections(ResourceIdMgr::ResourceId Id,
634 JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
635 if (auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) {
636 ReportError(std::move(Err));
637 return true;
638 } else
639 return false;
640 }
641
642 bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
643 if (auto Err = callB<mem::WriteMem>(DirectBufferWriter(Src, Addr, Size))) {
644 ReportError(std::move(Err));
645 return true;
646 } else
647 return false;
648 }
649
650 Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) {
651 return callB<mem::WritePtr>(Addr, PtrVal);
652 }
653
654 static Error doNothing() { return Error::success(); }
655
656 std::function<void(Error)> ReportError;
657 std::string RemoteTargetTriple;
658 uint32_t RemotePointerSize = 0;
659 uint32_t RemotePageSize = 0;
660 uint32_t RemoteTrampolineSize = 0;
661 uint32_t RemoteIndirectStubSize = 0;
662 ResourceIdMgr AllocatorIds, IndirectStubOwnerIds;
663 Optional<RemoteCompileCallbackManager> CallbackManager;
664};
665
666} // end namespace remote
667} // end namespace orc
668} // end namespace llvm
669
670#undef DEBUG_TYPE
671
672#endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H