llvm.org GIT mirror llvm / 30e9aa6
[ORC] Refactor OrcRemoteTarget code to expose its RPC API, reduce code duplication in the client, and improve error propagation. This patch moves the OrcRemoteTarget rpc::Function declarations from OrcRemoteTargetRPCAPI into their own namespaces under llvm::orc::remote so that they can be used in new contexts (in particular, a remote-object-file adapter layer that I will commit shortly). Code duplication in OrcRemoteTargetClient (especially in loops processing the code, rw-data and ro-data allocations) is removed by moving the loop bodies into their own functions. Error propagation is (slightly) improved by adding an ErrorReporter functor to the OrcRemoteTargetClient -- Errors that can't be returned (because they occur in destructors, or behind stable APIs that don't provide error returns) can be sent to the ErrorReporter instead. Some methods in the Client API are also changed to make better use of the Expected class: returning Expected<T>s rather than returning Errors and taking T&s to store the results. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312500 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 2 years ago
6 changed file(s) with 373 addition(s) and 435 deletion(s). Raw diff Collapse all Expand all
7171 namespace orc {
7272
7373 // Typedef the remote-client API.
74 using MyRemote = remote::OrcRemoteTargetClient;
74 using MyRemote = remote::OrcRemoteTargetClient;
7575
7676 class KaleidoscopeJIT {
7777 private:
9797 "", SmallVector())),
9898 DL(TM->createDataLayout()),
9999 ObjectLayer([&Remote]() {
100 std::unique_ptr MemMgr;
101 if (auto Err = Remote.createRemoteMemoryManager(MemMgr)) {
102 logAllUnhandledErrors(std::move(Err), errs(),
103 "Error creating remote memory manager:");
104 exit(1);
105 }
106 return MemMgr;
100 return cantFail(Remote.createRemoteMemoryManager());
107101 }),
108102 CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
109103 OptimizeLayer(CompileLayer,
118112 exit(1);
119113 }
120114 CompileCallbackMgr = &*CCMgrOrErr;
121 std::unique_ptr ISM;
122 if (auto Err = Remote.createIndirectStubsManager(ISM)) {
123 logAllUnhandledErrors(std::move(Err), errs(),
124 "Error creating indirect stubs manager:");
125 exit(1);
126 }
127 IndirectStubsMgr = std::move(ISM);
115 IndirectStubsMgr = cantFail(Remote.createIndirectStubsManager());
128116 llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
129117 }
130118
12761276 BinopPrecedence['*'] = 40; // highest.
12771277
12781278 auto TCPChannel = connect();
1279 auto Remote = ExitOnErr(MyRemote::Create(*TCPChannel));
1279 auto Remote = ExitOnErr(MyRemote::Create(*TCPChannel, ExitOnErr));
12801280 TheJIT = llvm::make_unique(*Remote);
12811281
12821282 // Automatically inject a definition for 'printExprResult'.
5252 /// Each of the utility classes talks to a JIT server (an instance of the
5353 /// OrcRemoteTargetServer class) via an RPC system (see RPCUtils.h) to carry out
5454 /// its actions.
55 template
56 class OrcRemoteTargetClient : public OrcRemoteTargetRPCAPI {
55 class OrcRemoteTargetClient
56 : public rpc::SingleThreadedRPCEndpoint {
5757 public:
58 /// Remote memory manager.
59 class RCMemoryManager : public RuntimeDyld::MemoryManager {
58 /// Remote-mapped RuntimeDyld-compatible memory manager.
59 class RemoteRTDyldMemoryManager : public RuntimeDyld::MemoryManager {
60 friend class OrcRemoteTargetClient;
61
6062 public:
61 RCMemoryManager(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id)
62 : Client(Client), Id(Id) {
63 DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
64 }
65
66 RCMemoryManager(const RCMemoryManager &) = delete;
67 RCMemoryManager &operator=(const RCMemoryManager &) = delete;
68 RCMemoryManager(RCMemoryManager &&) = default;
69 RCMemoryManager &operator=(RCMemoryManager &&) = default;
70
71 ~RCMemoryManager() override {
63 ~RemoteRTDyldMemoryManager() {
7264 Client.destroyRemoteAllocator(Id);
7365 DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
7466 }
67
68 RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &) = delete;
69 RemoteRTDyldMemoryManager &
70 operator=(const RemoteRTDyldMemoryManager &) = delete;
71 RemoteRTDyldMemoryManager(RemoteRTDyldMemoryManager &&) = default;
72 RemoteRTDyldMemoryManager &
73 operator=(RemoteRTDyldMemoryManager &&) = default;
7574
7675 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
7776 unsigned SectionID,
116115 DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
117116
118117 if (CodeSize != 0) {
119 if (auto AddrOrErr = Client.reserveMem(Id, CodeSize, CodeAlign))
120 Unmapped.back().RemoteCodeAddr = *AddrOrErr;
121 else {
122 // FIXME; Add error to poll.
123 assert(!AddrOrErr.takeError() && "Failed reserving remote memory.");
124 }
118 Unmapped.back().RemoteCodeAddr =
119 Client.reserveMem(Id, CodeSize, CodeAlign);
125120
126121 DEBUG(dbgs() << " code: "
127122 << format("0x%016x", Unmapped.back().RemoteCodeAddr)
130125 }
131126
132127 if (RODataSize != 0) {
133 if (auto AddrOrErr = Client.reserveMem(Id, RODataSize, RODataAlign))
134 Unmapped.back().RemoteRODataAddr = *AddrOrErr;
135 else {
136 // FIXME; Add error to poll.
137 assert(!AddrOrErr.takeError() && "Failed reserving remote memory.");
138 }
128 Unmapped.back().RemoteRODataAddr =
129 Client.reserveMem(Id, RODataSize, RODataAlign);
139130
140131 DEBUG(dbgs() << " ro-data: "
141132 << format("0x%016x", Unmapped.back().RemoteRODataAddr)
144135 }
145136
146137 if (RWDataSize != 0) {
147 if (auto AddrOrErr = Client.reserveMem(Id, RWDataSize, RWDataAlign))
148 Unmapped.back().RemoteRWDataAddr = *AddrOrErr;
149 else {
150 // FIXME; Add error to poll.
151 assert(!AddrOrErr.takeError() && "Failed reserving remote memory.");
152 }
138 Unmapped.back().RemoteRWDataAddr =
139 Client.reserveMem(Id, RWDataSize, RWDataAlign);
153140
154141 DEBUG(dbgs() << " rw-data: "
155142 << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
168155 void deregisterEHFrames() override {
169156 for (auto &Frame : RegisteredEHFrames) {
170157 // FIXME: Add error poll.
171 llvm::cantFail(Client.deregisterEHFrames(Frame.Addr, Frame.Size));
158 Client.deregisterEHFrames(Frame.Addr, Frame.Size);
172159 }
173160 }
174161
176163 const object::ObjectFile &Obj) override {
177164 DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
178165 for (auto &ObjAllocs : Unmapped) {
179 {
180 JITTargetAddress NextCodeAddr = ObjAllocs.RemoteCodeAddr;
181 for (auto &Alloc : ObjAllocs.CodeAllocs) {
182 NextCodeAddr = alignTo(NextCodeAddr, Alloc.getAlign());
183 Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextCodeAddr);
184 DEBUG(dbgs() << " code: "
185 << static_cast(Alloc.getLocalAddress())
186 << " -> " << format("0x%016x", NextCodeAddr) << "\n");
187 Alloc.setRemoteAddress(NextCodeAddr);
188 NextCodeAddr += Alloc.getSize();
189 }
190 }
191 {
192 JITTargetAddress NextRODataAddr = ObjAllocs.RemoteRODataAddr;
193 for (auto &Alloc : ObjAllocs.RODataAllocs) {
194 NextRODataAddr = alignTo(NextRODataAddr, Alloc.getAlign());
195 Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextRODataAddr);
196 DEBUG(dbgs() << " ro-data: "
197 << static_cast(Alloc.getLocalAddress())
198 << " -> " << format("0x%016x", NextRODataAddr)
199 << "\n");
200 Alloc.setRemoteAddress(NextRODataAddr);
201 NextRODataAddr += Alloc.getSize();
202 }
203 }
204 {
205 JITTargetAddress NextRWDataAddr = ObjAllocs.RemoteRWDataAddr;
206 for (auto &Alloc : ObjAllocs.RWDataAllocs) {
207 NextRWDataAddr = alignTo(NextRWDataAddr, Alloc.getAlign());
208 Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextRWDataAddr);
209 DEBUG(dbgs() << " rw-data: "
210 << static_cast(Alloc.getLocalAddress())
211 << " -> " << format("0x%016x", NextRWDataAddr)
212 << "\n");
213 Alloc.setRemoteAddress(NextRWDataAddr);
214 NextRWDataAddr += Alloc.getSize();
215 }
216 }
166 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,
167 ObjAllocs.RemoteCodeAddr);
168 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs,
169 ObjAllocs.RemoteRODataAddr);
170 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs,
171 ObjAllocs.RemoteRWDataAddr);
217172 Unfinalized.push_back(std::move(ObjAllocs));
218173 }
219174 Unmapped.clear();
223178 DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
224179
225180 for (auto &ObjAllocs : Unfinalized) {
226 for (auto &Alloc : ObjAllocs.CodeAllocs) {
227 DEBUG(dbgs() << " copying code: "
228 << static_cast(Alloc.getLocalAddress()) << " -> "
229 << format("0x%016x", Alloc.getRemoteAddress()) << " ("
230 << Alloc.getSize() << " bytes)\n");
231 if (auto Err =
232 Client.writeMem(Alloc.getRemoteAddress(),
233 Alloc.getLocalAddress(), Alloc.getSize())) {
234 // FIXME: Replace this once finalizeMemory can return an Error.
235 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
236 if (ErrMsg) {
237 raw_string_ostream ErrOut(*ErrMsg);
238 EIB.log(ErrOut);
239 }
240 });
241 return true;
242 }
243 }
244
245 if (ObjAllocs.RemoteCodeAddr) {
246 DEBUG(dbgs() << " setting R-X permissions on code block: "
247 << format("0x%016x", ObjAllocs.RemoteCodeAddr) << "\n");
248 if (auto Err = Client.setProtections(Id, ObjAllocs.RemoteCodeAddr,
249 sys::Memory::MF_READ |
250 sys::Memory::MF_EXEC)) {
251 // FIXME: Replace this once finalizeMemory can return an Error.
252 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
253 if (ErrMsg) {
254 raw_string_ostream ErrOut(*ErrMsg);
255 EIB.log(ErrOut);
256 }
257 });
258 return true;
259 }
260 }
261
262 for (auto &Alloc : ObjAllocs.RODataAllocs) {
263 DEBUG(dbgs() << " copying ro-data: "
264 << static_cast(Alloc.getLocalAddress()) << " -> "
265 << format("0x%016x", Alloc.getRemoteAddress()) << " ("
266 << Alloc.getSize() << " bytes)\n");
267 if (auto Err =
268 Client.writeMem(Alloc.getRemoteAddress(),
269 Alloc.getLocalAddress(), Alloc.getSize())) {
270 // FIXME: Replace this once finalizeMemory can return an Error.
271 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
272 if (ErrMsg) {
273 raw_string_ostream ErrOut(*ErrMsg);
274 EIB.log(ErrOut);
275 }
276 });
277 return true;
278 }
279 }
280
281 if (ObjAllocs.RemoteRODataAddr) {
282 DEBUG(dbgs() << " setting R-- permissions on ro-data block: "
283 << format("0x%016x", ObjAllocs.RemoteRODataAddr)
284 << "\n");
285 if (auto Err = Client.setProtections(Id, ObjAllocs.RemoteRODataAddr,
286 sys::Memory::MF_READ)) {
287 // FIXME: Replace this once finalizeMemory can return an Error.
288 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
289 if (ErrMsg) {
290 raw_string_ostream ErrOut(*ErrMsg);
291 EIB.log(ErrOut);
292 }
293 });
294 return false;
295 }
296 }
297
298 for (auto &Alloc : ObjAllocs.RWDataAllocs) {
299 DEBUG(dbgs() << " copying rw-data: "
300 << static_cast(Alloc.getLocalAddress()) << " -> "
301 << format("0x%016x", Alloc.getRemoteAddress()) << " ("
302 << Alloc.getSize() << " bytes)\n");
303 if (auto Err =
304 Client.writeMem(Alloc.getRemoteAddress(),
305 Alloc.getLocalAddress(), Alloc.getSize())) {
306 // FIXME: Replace this once finalizeMemory can return an Error.
307 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
308 if (ErrMsg) {
309 raw_string_ostream ErrOut(*ErrMsg);
310 EIB.log(ErrOut);
311 }
312 });
313 return false;
314 }
315 }
316
317 if (ObjAllocs.RemoteRWDataAddr) {
318 DEBUG(dbgs() << " setting RW- permissions on rw-data block: "
319 << format("0x%016x", ObjAllocs.RemoteRWDataAddr)
320 << "\n");
321 if (auto Err = Client.setProtections(Id, ObjAllocs.RemoteRWDataAddr,
322 sys::Memory::MF_READ |
323 sys::Memory::MF_WRITE)) {
324 // FIXME: Replace this once finalizeMemory can return an Error.
325 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
326 if (ErrMsg) {
327 raw_string_ostream ErrOut(*ErrMsg);
328 EIB.log(ErrOut);
329 }
330 });
331 return false;
332 }
333 }
181 if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr,
182 sys::Memory::MF_READ | sys::Memory::MF_EXEC))
183 return true;
184
185 if (copyAndProtect(ObjAllocs.RODataAllocs, ObjAllocs.RemoteRODataAddr,
186 sys::Memory::MF_READ))
187 return true;
188
189 if (copyAndProtect(ObjAllocs.RWDataAllocs, ObjAllocs.RemoteRWDataAddr,
190 sys::Memory::MF_READ | sys::Memory::MF_WRITE))
191 return true;
334192 }
335193 Unfinalized.clear();
336194
399257 std::vector CodeAllocs, RODataAllocs, RWDataAllocs;
400258 };
401259
260 RemoteRTDyldMemoryManager(OrcRemoteTargetClient &Client,
261 ResourceIdMgr::ResourceId Id)
262 : Client(Client), Id(Id) {
263 DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
264 }
265
266 // Maps all allocations in Allocs to aligned blocks
267 void mapAllocsToRemoteAddrs(RuntimeDyld &Dyld, std::vector &Allocs,
268 JITTargetAddress NextAddr) {
269 for (auto &Alloc : Allocs) {
270 NextAddr = alignTo(NextAddr, Alloc.getAlign());
271 Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr);
272 DEBUG(dbgs() << " " << static_cast(Alloc.getLocalAddress())
273 << " -> " << format("0x%016x", NextAddr) << "\n");
274 Alloc.setRemoteAddress(NextAddr);
275
276 // Only advance NextAddr if it was non-null to begin with,
277 // otherwise leave it as null.
278 if (NextAddr)
279 NextAddr += Alloc.getSize();
280 }
281 }
282
283 // Copies data for each alloc in the list, then set permissions on the
284 // segment.
285 bool copyAndProtect(const std::vector &Allocs,
286 JITTargetAddress RemoteSegmentAddr,
287 unsigned Permissions) {
288 if (RemoteSegmentAddr) {
289 assert(!Allocs.empty() && "No sections in allocated segment");
290
291 for (auto &Alloc : Allocs) {
292 DEBUG(dbgs() << " copying section: "
293 << static_cast(Alloc.getLocalAddress()) << " -> "
294 << format("0x%016x", Alloc.getRemoteAddress()) << " ("
295 << Alloc.getSize() << " bytes)\n";);
296
297 if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
298 Alloc.getSize()))
299 return true;
300 }
301
302 DEBUG(dbgs() << " setting "
303 << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
304 << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
305 << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
306 << " permissions on block: "
307 << format("0x%016x", RemoteSegmentAddr) << "\n");
308 if (Client.setProtections(Id, RemoteSegmentAddr, Permissions))
309 return true;
310 }
311 return false;
312 }
313
402314 OrcRemoteTargetClient &Client;
403315 ResourceIdMgr::ResourceId Id;
404316 std::vector Unmapped;
413325 };
414326
415327 /// Remote indirect stubs manager.
416 class RCIndirectStubsManager : public IndirectStubsManager {
328 class RemoteIndirectStubsManager : public IndirectStubsManager {
417329 public:
418 RCIndirectStubsManager(OrcRemoteTargetClient &Remote,
419 ResourceIdMgr::ResourceId Id)
420 : Remote(Remote), Id(Id) {}
421
422 ~RCIndirectStubsManager() override {
423 if (auto Err = Remote.destroyIndirectStubsManager(Id)) {
424 // FIXME: Thread this error back to clients.
425 consumeError(std::move(Err));
426 }
330 RemoteIndirectStubsManager(OrcRemoteTargetClient &Client,
331 ResourceIdMgr::ResourceId Id)
332 : Client(Client), Id(Id) {}
333
334 ~RemoteIndirectStubsManager() override {
335 Client.destroyIndirectStubsManager(Id);
427336 }
428337
429338 Error createStub(StringRef StubName, JITTargetAddress StubAddr,
471380 auto I = StubIndexes.find(Name);
472381 assert(I != StubIndexes.end() && "No stub pointer for symbol");
473382 auto Key = I->second.first;
474 return Remote.writePointer(getPtrAddr(Key), NewAddr);
383 return Client.writePointer(getPtrAddr(Key), NewAddr);
475384 }
476385
477386 private:
481390 unsigned NumStubs;
482391 };
483392
484 OrcRemoteTargetClient &Remote;
485 ResourceIdMgr::ResourceId Id;
486 std::vector RemoteIndirectStubsInfos;
487393 using StubKey = std::pair;
488 std::vector FreeStubs;
489 StringMap> StubIndexes;
490394
491395 Error reserveStubs(unsigned NumStubs) {
492396 if (NumStubs <= FreeStubs.size())
497401 JITTargetAddress PtrBase;
498402 unsigned NumStubsEmitted;
499403
500 if (auto StubInfoOrErr = Remote.emitIndirectStubs(Id, NewStubsRequired))
404 if (auto StubInfoOrErr = Client.emitIndirectStubs(Id, NewStubsRequired))
501405 std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
502406 else
503407 return StubInfoOrErr.takeError();
516420 auto Key = FreeStubs.back();
517421 FreeStubs.pop_back();
518422 StubIndexes[StubName] = std::make_pair(Key, StubFlags);
519 return Remote.writePointer(getPtrAddr(Key), InitAddr);
423 return Client.writePointer(getPtrAddr(Key), InitAddr);
520424 }
521425
522426 JITTargetAddress getStubAddr(StubKey K) {
523427 assert(RemoteIndirectStubsInfos[K.first].StubBase != 0 &&
524428 "Missing stub address");
525429 return RemoteIndirectStubsInfos[K.first].StubBase +
526 K.second * Remote.getIndirectStubSize();
430 K.second * Client.getIndirectStubSize();
527431 }
528432
529433 JITTargetAddress getPtrAddr(StubKey K) {
530434 assert(RemoteIndirectStubsInfos[K.first].PtrBase != 0 &&
531435 "Missing pointer address");
532436 return RemoteIndirectStubsInfos[K.first].PtrBase +
533 K.second * Remote.getPointerSize();
534 }
437 K.second * Client.getPointerSize();
438 }
439
440 OrcRemoteTargetClient &Client;
441 ResourceIdMgr::ResourceId Id;
442 std::vector RemoteIndirectStubsInfos;
443 std::vector FreeStubs;
444 StringMap> StubIndexes;
535445 };
536446
537447 /// Remote compile callback manager.
538 class RCCompileCallbackManager : public JITCompileCallbackManager {
448 class RemoteCompileCallbackManager : public JITCompileCallbackManager {
539449 public:
540 RCCompileCallbackManager(JITTargetAddress ErrorHandlerAddress,
541 OrcRemoteTargetClient &Remote)
542 : JITCompileCallbackManager(ErrorHandlerAddress), Remote(Remote) {}
450 RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
451 JITTargetAddress ErrorHandlerAddress)
452 : JITCompileCallbackManager(ErrorHandlerAddress), Client(Client) {}
543453
544454 private:
545455 Error grow() override {
546456 JITTargetAddress BlockAddr = 0;
547457 uint32_t NumTrampolines = 0;
548 if (auto TrampolineInfoOrErr = Remote.emitTrampolineBlock())
458 if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock())
549459 std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
550460 else
551461 return TrampolineInfoOrErr.takeError();
552462
553 uint32_t TrampolineSize = Remote.getTrampolineSize();
463 uint32_t TrampolineSize = Client.getTrampolineSize();
554464 for (unsigned I = 0; I < NumTrampolines; ++I)
555465 this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize));
556466
557467 return Error::success();
558468 }
559469
560 OrcRemoteTargetClient &Remote;
470 OrcRemoteTargetClient &Client;
561471 };
562472
563473 /// Create an OrcRemoteTargetClient.
564474 /// Channel is the ChannelT instance to communicate on. It is assumed that
565475 /// the channel is ready to be read from and written to.
566476 static Expected>
567 Create(ChannelT &Channel) {
477 Create(rpc::RawByteChannel &Channel, std::function ReportError) {
568478 Error Err = Error::success();
569 std::unique_ptr Client(
570 new OrcRemoteTargetClient(Channel, Err));
479 auto Client = std::unique_ptr(
480 new OrcRemoteTargetClient(Channel, std::move(ReportError), Err));
571481 if (Err)
572482 return std::move(Err);
573483 return std::move(Client);
577487 /// its result.
578488 Expected callIntVoid(JITTargetAddress Addr) {
579489 DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n");
580 return callB<CallIntVoid>(Addr);
490 return callB<exec::CallIntVoid>(Addr);
581491 }
582492
583493 /// Call the int(int, char*[]) function at the given address in the target and
586496 const std::vector &Args) {
587497 DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)
588498 << "\n");
589 return callB<CallMain>(Addr, Args);
499 return callB<exec::CallMain>(Addr, Args);
590500 }
591501
592502 /// Call the void() function at the given address in the target and wait for
594504 Error callVoidVoid(JITTargetAddress Addr) {
595505 DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
596506 << "\n");
597 return callB<CallVoidVoid>(Addr);
507 return callB<exec::CallVoidVoid>(Addr);
598508 }
599509
600510 /// Create an RCMemoryManager which will allocate its memory on the remote
601511 /// target.
602 Error createRemoteMemoryManager(std::unique_ptr &MM) {
603 assert(!MM && "MemoryManager should be null before creation.");
604
512 Expected>
513 createRemoteMemoryManager() {
605514 auto Id = AllocatorIds.getNext();
606 if (auto Err = callB(Id))
607 return Err;
608 MM = llvm::make_unique(*this, Id);
609 return Error::success();
515 if (auto Err = callB(Id))
516 return std::move(Err);
517 return std::unique_ptr(
518 new RemoteRTDyldMemoryManager(*this, Id));
610519 }
611520
612521 /// Create an RCIndirectStubsManager that will allocate stubs on the remote
613522 /// target.
614 Error createIndirectStubsManager(std::unique_ptr &I) {
615 assert(!I && "Indirect stubs manager should be null before creation.");
523 Expected>
524 createIndirectStubsManager() {
616525 auto Id = IndirectStubOwnerIds.getNext();
617 if (auto Err = callB(Id))
618 return Err;
619 I = llvm::make_unique(*this, Id);
620 return Error::success();
621 }
622
623 Expected
526 if (auto Err = callB(Id))
527 return std::move(Err);
528 return llvm::make_unique(*this, Id);
529 }
530
531 Expected
624532 enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) {
625 // Check for an 'out-of-band' error, e.g. from an MM destructor.
626 if (ExistingError)
627 return std::move(ExistingError);
628
629533 // Emit the resolver block on the JIT server.
630 if (auto Err = callB<EmitResolverBlock>())
534 if (auto Err = callB<stubs::EmitResolverBlock>())
631535 return std::move(Err);
632536
633537 // Create the callback manager.
634 CallbackManager.emplace(ErrorHandlerAddress, *this);
635 RCCompileCallbackManager &Mgr = *CallbackManager;
538 CallbackManager.emplace(*this, ErrorHandlerAddress);
539 RemoteCompileCallbackManager &Mgr = *CallbackManager;
636540 return Mgr;
637541 }
638542
640544 /// symbol resolvers *after* they've searched the local symbol table in the
641545 /// JIT stack.
642546 Expected getSymbolAddress(StringRef Name) {
643 // Check for an 'out-of-band' error, e.g. from an MM destructor.
644 if (ExistingError)
645 return std::move(ExistingError);
646
647 return callB<GetSymbolAddress>(Name);
547 return callB<utils::GetSymbolAddress>(Name);
648548 }
649549
650550 /// Get the triple for the remote target.
651551 const std::string &getTargetTriple() const { return RemoteTargetTriple; }
652552
653 Error terminateSession() { return callB<TerminateSession>(); }
553 Error terminateSession() { return callB<utils::TerminateSession>(); }
654554
655555 private:
656 OrcRemoteTargetClient(ChannelT &Channel, Error &Err)
657 : OrcRemoteTargetRPCAPI(Channel) {
556 OrcRemoteTargetClient(rpc::RawByteChannel &Channel,
557 std::function ReportError, Error &Err)
558 : rpc::SingleThreadedRPCEndpoint(Channel, true),
559 ReportError(std::move(ReportError)) {
658560 ErrorAsOutParameter EAO(&Err);
659561
660 addHandler<RequestCompile>(
562 addHandler<utils::RequestCompile>(
661563 [this](JITTargetAddress Addr) -> JITTargetAddress {
662564 if (CallbackManager)
663565 return CallbackManager->executeCompileCallback(Addr);
664566 return 0;
665567 });
666568
667 if (auto RIOrErr = callB<GetRemoteInfo>()) {
569 if (auto RIOrErr = callB<utils::GetRemoteInfo>()) {
668570 std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
669571 RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
670572 Err = Error::success();
671 } else {
672 Err = joinErrors(RIOrErr.takeError(), std::move(ExistingError));
673 }
674 }
675
676 Error deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
677 return callB(Addr, Size);
573 } else
574 Err = RIOrErr.takeError();
575 }
576
577 void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
578 if (auto Err = callB(Addr, Size))
579 ReportError(std::move(Err));
678580 }
679581
680582 void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
681 if (auto Err = callB<DestroyRemoteAllocator>(Id)) {
583 if (auto Err = callB<mem::DestroyRemoteAllocator>(Id)) {
682584 // FIXME: This will be triggered by a removeModuleSet call: Propagate
683585 // error return up through that.
684586 llvm_unreachable("Failed to destroy remote allocator.");
686588 }
687589 }
688590
689 Error destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
591 void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
690592 IndirectStubOwnerIds.release(Id);
691 return callB(Id);
593 if (auto Err = callB(Id))
594 ReportError(std::move(Err));
692595 }
693596
694597 Expected>
695598 emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) {
696 return callB<EmitIndirectStubs>(Id, NumStubsRequired);
599 return callB<stubs::EmitIndirectStubs>(Id, NumStubsRequired);
697600 }
698601
699602 Expected> emitTrampolineBlock() {
700 // Check for an 'out-of-band' error, e.g. from an MM destructor.
701 if (ExistingError)
702 return std::move(ExistingError);
703
704 return callB<EmitTrampolineBlock>();
603 return callB<stubs::EmitTrampolineBlock>();
705604 }
706605
707606 uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
710609
711610 uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
712611
713 Expected> readMem(char *Dst, JITTargetAddress Src,
714 uint64_t Size) {
715 // Check for an 'out-of-band' error, e.g. from an MM destructor.
716 if (ExistingError)
717 return std::move(ExistingError);
718
719 return callB(Src, Size);
612 Expected> readMem(char *Dst, JITTargetAddress Src,
613 uint64_t Size) {
614 return callB(Src, Size);
720615 }
721616
722617 Error registerEHFrames(JITTargetAddress &RAddr, uint32_t Size) {
723 return callB(RAddr, Size);
724 }
725
726 Expected reserveMem(ResourceIdMgr::ResourceId Id,
727 uint64_t Size, uint32_t Align) {
728 // Check for an 'out-of-band' error, e.g. from an MM destructor.
729 if (ExistingError)
730 return std::move(ExistingError);
731
732 return callB(Id, Size, Align);
733 }
734
735 Error setProtections(ResourceIdMgr::ResourceId Id,
736 JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
737 return callB(Id, RemoteSegAddr, ProtFlags);
738 }
739
740 Error writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
741 // Check for an 'out-of-band' error, e.g. from an MM destructor.
742 if (ExistingError)
743 return std::move(ExistingError);
744
745 return callB(DirectBufferWriter(Src, Addr, Size));
618 // FIXME: Duplicate error and report it via ReportError too?
619 return callB(RAddr, Size);
620 }
621
622 JITTargetAddress reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
623 uint32_t Align) {
624 if (auto AddrOrErr = callB(Id, Size, Align))
625 return *AddrOrErr;
626 else {
627 ReportError(AddrOrErr.takeError());
628 return 0;
629 }
630 }
631
632 bool setProtections(ResourceIdMgr::ResourceId Id,
633 JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
634 if (auto Err = callB(Id, RemoteSegAddr, ProtFlags)) {
635 ReportError(std::move(Err));
636 return true;
637 } else
638 return false;
639 }
640
641 bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
642 if (auto Err = callB(DirectBufferWriter(Src, Addr, Size))) {
643 ReportError(std::move(Err));
644 return true;
645 } else
646 return false;
746647 }
747648
748649 Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) {
749 // Check for an 'out-of-band' error, e.g. from an MM destructor.
750 if (ExistingError)
751 return std::move(ExistingError);
752
753 return callB<WritePtr>(Addr, PtrVal);
650 return callB<mem::WritePtr>(Addr, PtrVal);
754651 }
755652
756653 static Error doNothing() { return Error::success(); }
757654
758 Error ExistingError = Error::success();
655 std::function ReportError;
759656 std::string RemoteTargetTriple;
760657 uint32_t RemotePointerSize = 0;
761658 uint32_t RemotePageSize = 0;
762659 uint32_t RemoteTrampolineSize = 0;
763660 uint32_t RemoteIndirectStubSize = 0;
764661 ResourceIdMgr AllocatorIds, IndirectStubOwnerIds;
765 OptionalCCompileCallbackManager> CallbackManager;
662 OptionalemoteCompileCallbackManager> CallbackManager;
766663 };
767664
768665 } // end namespace remote
8282
8383 namespace remote {
8484
85 class OrcRemoteTargetRPCAPI
86 : public rpc::SingleThreadedRPCEndpoint {
87 protected:
88 class ResourceIdMgr {
89 public:
90 using ResourceId = uint64_t;
91 static const ResourceId InvalidId = ~0U;
92
93 ResourceId getNext() {
94 if (!FreeIds.empty()) {
95 ResourceId I = FreeIds.back();
96 FreeIds.pop_back();
97 return I;
98 }
99 return NextId++;
85 class ResourceIdMgr {
86 public:
87 using ResourceId = uint64_t;
88 static const ResourceId InvalidId = ~0U;
89
90 ResourceIdMgr() = default;
91 explicit ResourceIdMgr(ResourceId FirstValidId)
92 : NextId(std::move(FirstValidId)) {}
93
94 ResourceId getNext() {
95 if (!FreeIds.empty()) {
96 ResourceId I = FreeIds.back();
97 FreeIds.pop_back();
98 return I;
10099 }
101
102 void release(ResourceId I) { FreeIds.push_back(I); }
103
104 private:
105 ResourceId NextId = 0;
106 std::vector FreeIds;
107 };
108
109 public:
110 // FIXME: Remove constructors once MSVC supports synthesizing move-ops.
111 OrcRemoteTargetRPCAPI(rpc::RawByteChannel &C)
112 : rpc::SingleThreadedRPCEndpoint(C, true) {}
113
100 assert(NextId + 1 != ~0ULL && "All ids allocated");
101 return NextId++;
102 }
103
104 void release(ResourceId I) { FreeIds.push_back(I); }
105
106 private:
107 ResourceId NextId = 1;
108 std::vector FreeIds;
109 };
110
111 /// Registers EH frames on the remote.
112 namespace eh {
113
114 /// Registers EH frames on the remote.
115 class RegisterEHFrames
116 : public rpc::Function
117 void(JITTargetAddress Addr, uint32_t Size)> {
118 public:
119 static const char *getName() { return "RegisterEHFrames"; }
120 };
121
122 /// Deregisters EH frames on the remote.
123 class DeregisterEHFrames
124 : public rpc::Function
125 void(JITTargetAddress Addr, uint32_t Size)> {
126 public:
127 static const char *getName() { return "DeregisterEHFrames"; }
128 };
129
130 } // end namespace eh
131
132 /// RPC functions for executing remote code.
133 namespace exec {
134
135 /// Call an 'int32_t()'-type function on the remote, returns the called
136 /// function's return value.
114137 class CallIntVoid
115138 : public rpc::Function {
116139 public:
117140 static const char *getName() { return "CallIntVoid"; }
118141 };
119142
143 /// Call an 'int32_t(int32_t, char**)'-type function on the remote, returns the
144 /// called function's return value.
120145 class CallMain
121146 : public rpc::Function
122147 std::vector Args)> {
124149 static const char *getName() { return "CallMain"; }
125150 };
126151
152 /// Calls a 'void()'-type function on the remote, returns when the called
153 /// function completes.
127154 class CallVoidVoid
128155 : public rpc::Function {
129156 public:
130157 static const char *getName() { return "CallVoidVoid"; }
131158 };
132159
160 } // end namespace exec
161
162 /// RPC functions for remote memory management / inspection / modification.
163 namespace mem {
164
165 /// Creates a memory allocator on the remote.
133166 class CreateRemoteAllocator
134167 : public rpc::Function
135168 void(ResourceIdMgr::ResourceId AllocatorID)> {
137170 static const char *getName() { return "CreateRemoteAllocator"; }
138171 };
139172
173 /// Destroys a remote allocator, freeing any memory allocated by it.
174 class DestroyRemoteAllocator
175 : public rpc::Function
176 void(ResourceIdMgr::ResourceId AllocatorID)> {
177 public:
178 static const char *getName() { return "DestroyRemoteAllocator"; }
179 };
180
181 /// Read a remote memory block.
182 class ReadMem
183 : public rpc::Function(JITTargetAddress Src,
184 uint64_t Size)> {
185 public:
186 static const char *getName() { return "ReadMem"; }
187 };
188
189 /// Reserve a block of memory on the remote via the given allocator.
190 class ReserveMem
191 : public rpc::Function
192 JITTargetAddress(ResourceIdMgr::ResourceId AllocID,
193 uint64_t Size, uint32_t Align)> {
194 public:
195 static const char *getName() { return "ReserveMem"; }
196 };
197
198 /// Set the memory protection on a memory block.
199 class SetProtections
200 : public rpc::Function
201 void(ResourceIdMgr::ResourceId AllocID,
202 JITTargetAddress Dst, uint32_t ProtFlags)> {
203 public:
204 static const char *getName() { return "SetProtections"; }
205 };
206
207 /// Write to a remote memory block.
208 class WriteMem
209 : public rpc::Function {
210 public:
211 static const char *getName() { return "WriteMem"; }
212 };
213
214 /// Write to a remote pointer.
215 class WritePtr : public rpc::Function
216 JITTargetAddress Val)> {
217 public:
218 static const char *getName() { return "WritePtr"; }
219 };
220
221 } // end namespace mem
222
223 /// RPC functions for remote stub and trampoline management.
224 namespace stubs {
225
226 /// Creates an indirect stub owner on the remote.
140227 class CreateIndirectStubsOwner
141228 : public rpc::Function
142229 void(ResourceIdMgr::ResourceId StubOwnerID)> {
144231 static const char *getName() { return "CreateIndirectStubsOwner"; }
145232 };
146233
147 class DeregisterEHFrames
148 : public rpc::Function
149 void(JITTargetAddress Addr, uint32_t Size)> {
150 public:
151 static const char *getName() { return "DeregisterEHFrames"; }
152 };
153
154 class DestroyRemoteAllocator
155 : public rpc::Function
156 void(ResourceIdMgr::ResourceId AllocatorID)> {
157 public:
158 static const char *getName() { return "DestroyRemoteAllocator"; }
159 };
160
234 /// RPC function for destroying an indirect stubs owner.
161235 class DestroyIndirectStubsOwner
162236 : public rpc::Function
163237 void(ResourceIdMgr::ResourceId StubsOwnerID)> {
176250 static const char *getName() { return "EmitIndirectStubs"; }
177251 };
178252
253 /// RPC function to emit the resolver block and return its address.
179254 class EmitResolverBlock : public rpc::Function {
180255 public:
181256 static const char *getName() { return "EmitResolverBlock"; }
189264 static const char *getName() { return "EmitTrampolineBlock"; }
190265 };
191266
192 class GetSymbolAddress
193 : public rpc::Function
194 JITTargetAddress(std::string SymbolName)> {
195 public:
196 static const char *getName() { return "GetSymbolAddress"; }
197 };
267 } // end namespace stubs
268
269 /// Miscelaneous RPC functions for dealing with remotes.
270 namespace utils {
198271
199272 /// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize,
200273 /// IndirectStubsSize).
206279 static const char *getName() { return "GetRemoteInfo"; }
207280 };
208281
209 class ReadMem
210 : public rpc::Function(JITTargetAddress Src,
211 uint64_t Size)> {
212 public:
213 static const char *getName() { return "ReadMem"; }
214 };
215
216 class RegisterEHFrames
217 : public rpc::Function
218 void(JITTargetAddress Addr, uint32_t Size)> {
219 public:
220 static const char *getName() { return "RegisterEHFrames"; }
221 };
222
223 class ReserveMem
224 : public rpc::Function
225 JITTargetAddress(ResourceIdMgr::ResourceId AllocID,
226 uint64_t Size, uint32_t Align)> {
227 public:
228 static const char *getName() { return "ReserveMem"; }
229 };
230
282 /// Get the address of a remote symbol.
283 class GetSymbolAddress
284 : public rpc::Function
285 JITTargetAddress(std::string SymbolName)> {
286 public:
287 static const char *getName() { return "GetSymbolAddress"; }
288 };
289
290 /// Request that the host execute a compile callback.
231291 class RequestCompile
232292 : public rpc::Function<
233293 RequestCompile, JITTargetAddress(JITTargetAddress TrampolineAddr)> {
235295 static const char *getName() { return "RequestCompile"; }
236296 };
237297
238 class SetProtections
239 : public rpc::Function
240 void(ResourceIdMgr::ResourceId AllocID,
241 JITTargetAddress Dst, uint32_t ProtFlags)> {
242 public:
243 static const char *getName() { return "SetProtections"; }
244 };
245
298 /// Notify the remote and terminate the session.
246299 class TerminateSession : public rpc::Function {
247300 public:
248301 static const char *getName() { return "TerminateSession"; }
249302 };
250303
251 class WriteMem
252 : public rpc::Function {
253 public:
254 static const char *getName() { return "WriteMem"; }
255 };
256
257 class WritePtr : public rpc::Function
258 JITTargetAddress Val)> {
259 public:
260 static const char *getName() { return "WritePtr"; }
261 };
304 } // namespace utils
305
306 class OrcRemoteTargetRPCAPI
307 : public rpc::SingleThreadedRPCEndpoint {
308 public:
309 // FIXME: Remove constructors once MSVC supports synthesizing move-ops.
310 OrcRemoteTargetRPCAPI(rpc::RawByteChannel &C)
311 : rpc::SingleThreadedRPCEndpoint(C, true) {}
262312 };
263313
264314 } // end namespace remote
4444 namespace remote {
4545
4646 template
47 class OrcRemoteTargetServer : public OrcRemoteTargetRPCAPI {
47 class OrcRemoteTargetServer
48 : public rpc::SingleThreadedRPCEndpoint {
4849 public:
4950 using SymbolLookupFtor =
5051 std::function;
5556 OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup,
5657 EHFrameRegistrationFtor EHFramesRegister,
5758 EHFrameRegistrationFtor EHFramesDeregister)
58 : OrcRemoteTargetRPCAPI(Channel), SymbolLookup(std::move(SymbolLookup)),
59 : rpc::SingleThreadedRPCEndpoint(Channel, true),
60 SymbolLookup(std::move(SymbolLookup)),
5961 EHFramesRegister(std::move(EHFramesRegister)),
6062 EHFramesDeregister(std::move(EHFramesDeregister)) {
6163 using ThisT = typename std::remove_reference::type;
62 addHandler(*this, &ThisT::handleCallIntVoid);
63 addHandler(*this, &ThisT::handleCallMain);
64 addHandler(*this, &ThisT::handleCallVoidVoid);
65 addHandler(*this,
66 &ThisT::handleCreateRemoteAllocator);
67 addHandler<CreateIndirectStubsOwner>(
64 addHandler<exec::CallIntVoid>(*this, &ThisT::handleCallIntVoid);
65 addHandler(*this, &ThisT::handleCallMain);
66 addHandler(*this, &ThisT::handleCallVoidVoid);
67 addHandler(*this,
68 &ThisT::handleCreateRemoteAllocator);
69 addHandler(
70 *this, &ThisT::handleDestroyRemoteAllocator);
71 addHandler(*this, &ThisT::handleReadMem);
72 addHandler(*this, &ThisT::handleReserveMem);
73 addHandler(*this, &ThisT::handleSetProtections);
74 addHandler(*this, &ThisT::handleWriteMem);
75 addHandler(*this, &ThisT::handleWritePtr);
76 addHandler(*this, &ThisT::handleRegisterEHFrames);
77 addHandler(*this, &ThisT::handleDeregisterEHFrames);
78 addHandler(
6879 *this, &ThisT::handleCreateIndirectStubsOwner);
69 addHandler(*this, &ThisT::handleDeregisterEHFrames);
70 addHandler(*this,
71 &ThisT::handleDestroyRemoteAllocator);
72 addHandler<DestroyIndirectStubsOwner>(
80 addHandler<stubs::DestroyIndirectStubsOwner>(
7381 *this, &ThisT::handleDestroyIndirectStubsOwner);
74 addHandler(*this, &ThisT::handleEmitIndirectStubs);
75 addHandler(*this, &ThisT::handleEmitResolverBlock);
76 addHandler(*this, &ThisT::handleEmitTrampolineBlock);
77 addHandler(*this, &ThisT::handleGetSymbolAddress);
78 addHandler(*this, &ThisT::handleGetRemoteInfo);
79 addHandler(*this, &ThisT::handleReadMem);
80 addHandler(*this, &ThisT::handleRegisterEHFrames);
81 addHandler(*this, &ThisT::handleReserveMem);
82 addHandler(*this, &ThisT::handleSetProtections);
83 addHandler(*this, &ThisT::handleTerminateSession);
84 addHandler(*this, &ThisT::handleWriteMem);
85 addHandler<WritePtr>(*this, &ThisT::handleWritePtr);
82 addHandler<stubs::EmitIndirectStubs>(*this,
83 &ThisT::handleEmitIndirectStubs);
84 addHandler(*this,
85 &ThisT::handleEmitResolverBlock);
86 addHandler(*this,
87 &ThisT::handleEmitTrampolineBlock);
88 addHandler(*this, &ThisT::handleGetSymbolAddress);
89 addHandler(*this, &ThisT::handleGetRemoteInfo);
90 addHandler(*this, &ThisT::handleTerminateSession);
8691 }
8792
8893 // FIXME: Remove move/copy ops once MSVC supports synthesizing move ops.
9398 OrcRemoteTargetServer &operator=(OrcRemoteTargetServer &&) = delete;
9499
95100 Expected requestCompile(JITTargetAddress TrampolineAddr) {
96 return callB<RequestCompile>(TrampolineAddr);
101 return callB<utils::RequestCompile>(TrampolineAddr);
97102 }
98103
99104 bool receivedTerminate() const { return TerminateFlag; }
606606 }
607607
608608 // Create a remote target client running over the channel.
609 typedef orc::remote::OrcRemoteTargetClient
610 MyRemote;
611 auto R = ExitOnErr(MyRemote::Create(*C));
609 typedef orc::remote::OrcRemoteTargetClient MyRemote;
610 auto R = ExitOnErr(MyRemote::Create(*C, ExitOnErr));
612611
613612 // Create a remote memory manager.
614 std::unique_ptr RemoteMM;
615 ExitOnErr(R->createRemoteMemoryManager(RemoteMM));
613 auto RemoteMM = ExitOnErr(R->createRemoteMemoryManager());
616614
617615 // Forward MCJIT's memory manager calls to the remote memory manager.
618616 static_cast(RTDyldMM)->setMemMgr(