llvm.org GIT mirror llvm / 6320b78
[Orc] Re-commit r266581 with fixes for MSVC, and format cleanups. Fixes: (1) Removes constexpr (unsupported in MSVC) (2) Move constructors (remove explicitly defaulted ones) (3) <future> - Add warning suppression for MSVC. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266663 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 4 years ago
12 changed file(s) with 924 addition(s) and 515 deletion(s). Raw diff Collapse all Expand all
2525 RemoteMProtectAddrUnrecognized,
2626 RemoteIndirectStubsOwnerDoesNotExist,
2727 RemoteIndirectStubsOwnerIdAlreadyInUse,
28 UnexpectedRPCCall
28 UnexpectedRPCCall,
29 UnexpectedRPCResponse,
2930 };
3031
3132 std::error_code orcError(OrcErrorCode ErrCode);
3535 template
3636 class OrcRemoteTargetClient : public OrcRemoteTargetRPCAPI {
3737 public:
38
3839 /// Remote memory manager.
3940 class RCMemoryManager : public RuntimeDyld::MemoryManager {
4041 public:
104105 DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
105106
106107 if (CodeSize != 0) {
107 std::error_code EC = Client.reserveMem(Unmapped.back().RemoteCodeAddr,
108 Id, CodeSize, CodeAlign);
109 // FIXME; Add error to poll.
110 assert(!EC && "Failed reserving remote memory.");
111 (void)EC;
108 if (auto AddrOrErr = Client.reserveMem(Id, CodeSize, CodeAlign))
109 Unmapped.back().RemoteCodeAddr = *AddrOrErr;
110 else {
111 // FIXME; Add error to poll.
112 assert(!AddrOrErr.getError() && "Failed reserving remote memory.");
113 }
114
112115 DEBUG(dbgs() << " code: "
113116 << format("0x%016x", Unmapped.back().RemoteCodeAddr)
114117 << " (" << CodeSize << " bytes, alignment " << CodeAlign
116119 }
117120
118121 if (RODataSize != 0) {
119 std::error_code EC = Client.reserveMem(Unmapped.back().RemoteRODataAddr,
120 Id, RODataSize, RODataAlign);
121 // FIXME; Add error to poll.
122 assert(!EC && "Failed reserving remote memory.");
123 (void)EC;
122 if (auto AddrOrErr = Client.reserveMem(Id, RODataSize, RODataAlign))
123 Unmapped.back().RemoteRODataAddr = *AddrOrErr;
124 else {
125 // FIXME; Add error to poll.
126 assert(!AddrOrErr.getError() && "Failed reserving remote memory.");
127 }
128
124129 DEBUG(dbgs() << " ro-data: "
125130 << format("0x%016x", Unmapped.back().RemoteRODataAddr)
126131 << " (" << RODataSize << " bytes, alignment "
128133 }
129134
130135 if (RWDataSize != 0) {
131 std::error_code EC = Client.reserveMem(Unmapped.back().RemoteRWDataAddr,
132 Id, RWDataSize, RWDataAlign);
133 // FIXME; Add error to poll.
134 assert(!EC && "Failed reserving remote memory.");
135 (void)EC;
136 if (auto AddrOrErr = Client.reserveMem(Id, RWDataSize, RWDataAlign))
137 Unmapped.back().RemoteRWDataAddr = *AddrOrErr;
138 else {
139 // FIXME; Add error to poll.
140 assert(!AddrOrErr.getError() && "Failed reserving remote memory.");
141 }
142
136143 DEBUG(dbgs() << " rw-data: "
137144 << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
138145 << " (" << RWDataSize << " bytes, alignment "
430437 TargetAddress PtrBase;
431438 unsigned NumStubsEmitted;
432439
433 Remote.emitIndirectStubs(StubBase, PtrBase, NumStubsEmitted, Id,
434 NewStubsRequired);
440 if (auto StubInfoOrErr = Remote.emitIndirectStubs(Id, NewStubsRequired))
441 std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
442 else
443 return StubInfoOrErr.getError();
435444
436445 unsigned NewBlockId = RemoteIndirectStubsInfos.size();
437446 RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted});
483492 void grow() override {
484493 TargetAddress BlockAddr = 0;
485494 uint32_t NumTrampolines = 0;
486 auto EC = Remote.emitTrampolineBlock(BlockAddr, NumTrampolines);
487 assert(!EC && "Failed to create trampolines");
495 if (auto TrampolineInfoOrErr = Remote.emitTrampolineBlock())
496 std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
497 else {
498 // FIXME: Return error.
499 llvm_unreachable("Failed to create trampolines");
500 }
488501
489502 uint32_t TrampolineSize = Remote.getTrampolineSize();
490503 for (unsigned I = 0; I < NumTrampolines; ++I)
502515 OrcRemoteTargetClient H(Channel, EC);
503516 if (EC)
504517 return EC;
505 return H;
518 return ErrorOr(std::move(H));
506519 }
507520
508521 /// Call the int(void) function at the given address in the target and return
509522 /// its result.
510 std::error_code callIntVoid(int &Result, TargetAddress Addr) {
523 ErrorOr callIntVoid(TargetAddress Addr) {
511524 DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n");
512525
513 if (auto EC = call(Channel, Addr))
514 return EC;
515
516 unsigned NextProcId;
517 if (auto EC = listenForCompileRequests(NextProcId))
518 return EC;
519
520 if (NextProcId != CallIntVoidResponseId)
521 return orcError(OrcErrorCode::UnexpectedRPCCall);
522
523 return handle(Channel, [&](int R) {
524 Result = R;
525 DEBUG(dbgs() << "Result: " << R << "\n");
526 return std::error_code();
527 });
526 auto Listen =
527 [&](RPCChannel &C, uint32_t Id) {
528 return listenForCompileRequests(C, Id);
529 };
530 return callSTHandling(Channel, Listen, Addr);
528531 }
529532
530533 /// Call the int(int, char*[]) function at the given address in the target and
531534 /// return its result.
532 std::error_code callMain(int &Result, TargetAddress Addr,
533 const std::vector &Args) {
535 ErrorOr callMain(TargetAddress Addr,
536 const std::vector &Args) {
534537 DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)
535538 << "\n");
536539
537 if (auto EC = call(Channel, Addr, Args))
538 return EC;
539
540 unsigned NextProcId;
541 if (auto EC = listenForCompileRequests(NextProcId))
542 return EC;
543
544 if (NextProcId != CallMainResponseId)
545 return orcError(OrcErrorCode::UnexpectedRPCCall);
546
547 return handle(Channel, [&](int R) {
548 Result = R;
549 DEBUG(dbgs() << "Result: " << R << "\n");
550 return std::error_code();
551 });
540 auto Listen =
541 [&](RPCChannel &C, uint32_t Id) {
542 return listenForCompileRequests(C, Id);
543 };
544 return callSTHandling(Channel, Listen, Addr, Args);
552545 }
553546
554547 /// Call the void() function at the given address in the target and wait for
557550 DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
558551 << "\n");
559552
560 if (auto EC = call(Channel, Addr))
561 return EC;
562
563 unsigned NextProcId;
564 if (auto EC = listenForCompileRequests(NextProcId))
565 return EC;
566
567 if (NextProcId != CallVoidVoidResponseId)
568 return orcError(OrcErrorCode::UnexpectedRPCCall);
569
570 return handle(Channel, doNothing);
553 auto Listen =
554 [&](RPCChannel &C, JITFuncId Id) {
555 return listenForCompileRequests(C, Id);
556 };
557 return callSTHandling(Channel, Listen, Addr);
571558 }
572559
573560 /// Create an RCMemoryManager which will allocate its memory on the remote
577564 assert(!MM && "MemoryManager should be null before creation.");
578565
579566 auto Id = AllocatorIds.getNext();
580 if (auto EC = call(Channel, Id))
567 if (auto EC = callST(Channel, Id))
581568 return EC;
582569 MM = llvm::make_unique(*this, Id);
583570 return std::error_code();
589576 createIndirectStubsManager(std::unique_ptr &I) {
590577 assert(!I && "Indirect stubs manager should be null before creation.");
591578 auto Id = IndirectStubOwnerIds.getNext();
592 if (auto EC = call(Channel, Id))
579 if (auto EC = callST(Channel, Id))
593580 return EC;
594581 I = llvm::make_unique(*this, Id);
595582 return std::error_code();
598585 /// Search for symbols in the remote process. Note: This should be used by
599586 /// symbol resolvers *after* they've searched the local symbol table in the
600587 /// JIT stack.
601 std::error_code getSymbolAddress(TargetAddress &Addr, StringRef Name) {
588 ErrorOr getSymbolAddress(StringRef Name) {
602589 // Check for an 'out-of-band' error, e.g. from an MM destructor.
603590 if (ExistingError)
604591 return ExistingError;
605592
606 // Request remote symbol address.
607 if (auto EC = call(Channel, Name))
608 return EC;
609
610 return expect(Channel, [&](TargetAddress &A) {
611 Addr = A;
612 DEBUG(dbgs() << "Remote address lookup " << Name << " = "
613 << format("0x%016x", Addr) << "\n");
614 return std::error_code();
615 });
593 return callST(Channel, Name);
616594 }
617595
618596 /// Get the triple for the remote target.
619597 const std::string &getTargetTriple() const { return RemoteTargetTriple; }
620598
621 std::error_code terminateSession() { return call(Channel); }
599 std::error_code terminateSession() {
600 return callST(Channel);
601 }
622602
623603 private:
624604 OrcRemoteTargetClient(ChannelT &Channel, std::error_code &EC)
625605 : Channel(Channel) {
626 if ((EC = call(Channel)))
627 return;
628
629 EC = expect(
630 Channel, readArgs(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
631 RemoteTrampolineSize, RemoteIndirectStubSize));
606 if (auto RIOrErr = callST(Channel)) {
607 std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
608 RemoteTrampolineSize, RemoteIndirectStubSize) =
609 *RIOrErr;
610 EC = std::error_code();
611 } else
612 EC = RIOrErr.getError();
632613 }
633614
634615 std::error_code deregisterEHFrames(TargetAddress Addr, uint32_t Size) {
635 return call(Channel, Addr, Size);
616 return callST(Channel, Addr, Size);
636617 }
637618
638619 void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
639 if (auto EC = call(Channel, Id)) {
620 if (auto EC = callST(Channel, Id)) {
640621 // FIXME: This will be triggered by a removeModuleSet call: Propagate
641622 // error return up through that.
642623 llvm_unreachable("Failed to destroy remote allocator.");
646627
647628 std::error_code destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
648629 IndirectStubOwnerIds.release(Id);
649 return call(Channel, Id);
650 }
651
652 std::error_code emitIndirectStubs(TargetAddress &StubBase,
653 TargetAddress &PtrBase,
654 uint32_t &NumStubsEmitted,
655 ResourceIdMgr::ResourceId Id,
656 uint32_t NumStubsRequired) {
657 if (auto EC = call(Channel, Id, NumStubsRequired))
658 return EC;
659
660 return expect(
661 Channel, readArgs(StubBase, PtrBase, NumStubsEmitted));
630 return callST(Channel, Id);
631 }
632
633 ErrorOr>
634 emitIndirectStubs(ResourceIdMgr::ResourceId Id,
635 uint32_t NumStubsRequired) {
636 return callST(Channel, Id, NumStubsRequired);
662637 }
663638
664639 std::error_code emitResolverBlock() {
666641 if (ExistingError)
667642 return ExistingError;
668643
669 return call(Channel);
670 }
671
672 std::error_code emitTrampolineBlock(TargetAddress &BlockAddr,
673 uint32_t &NumTrampolines) {
644 return callST(Channel);
645 }
646
647 ErrorOr>
648 emitTrampolineBlock() {
674649 // Check for an 'out-of-band' error, e.g. from an MM destructor.
675650 if (ExistingError)
676651 return ExistingError;
677652
678 if (auto EC = call(Channel))
679 return EC;
680
681 return expect(
682 Channel, [&](TargetAddress BAddr, uint32_t NTrampolines) {
683 BlockAddr = BAddr;
684 NumTrampolines = NTrampolines;
685 return std::error_code();
686 });
653 return callST(Channel);
687654 }
688655
689656 uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
692659
693660 uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
694661
695 std::error_code listenForCompileRequests(uint32_t &NextId) {
662 std::error_code listenForCompileRequests(RPCChannel &C, uint32_t &Id) {
696663 // Check for an 'out-of-band' error, e.g. from an MM destructor.
697664 if (ExistingError)
698665 return ExistingError;
699666
700 if (auto EC = getNextProcId(Channel, NextId))
701 return EC;
702
703 while (NextId == RequestCompileId) {
704 TargetAddress TrampolineAddr = 0;
705 if (auto EC = handle(Channel, readArgs(TrampolineAddr)))
667 if (Id == RequestCompileId) {
668 if (auto EC = handle(C, CompileCallback))
706669 return EC;
707
708 TargetAddress ImplAddr = CompileCallback(TrampolineAddr);
709 if (auto EC = call(Channel, ImplAddr))
710 return EC;
711
712 if (auto EC = getNextProcId(Channel, NextId))
713 return EC;
714 }
715
716 return std::error_code();
717 }
718
719 std::error_code readMem(char *Dst, TargetAddress Src, uint64_t Size) {
670 return std::error_code();
671 }
672 // else
673 return orcError(OrcErrorCode::UnexpectedRPCCall);
674 }
675
676 ErrorOr> readMem(char *Dst, TargetAddress Src, uint64_t Size) {
720677 // Check for an 'out-of-band' error, e.g. from an MM destructor.
721678 if (ExistingError)
722679 return ExistingError;
723680
724 if (auto EC = call(Channel, Src, Size))
725 return EC;
726
727 if (auto EC = expect(
728 Channel, [&]() { return Channel.readBytes(Dst, Size); }))
729 return EC;
730
731 return std::error_code();
681 return callST(Channel, Src, Size);
732682 }
733683
734684 std::error_code registerEHFrames(TargetAddress &RAddr, uint32_t Size) {
735 return call(Channel, RAddr, Size);
736 }
737
738 std::error_code reserveMem(TargetAddress &RemoteAddr,
739 ResourceIdMgr::ResourceId Id, uint64_t Size,
740 uint32_t Align) {
685 return callST(Channel, RAddr, Size);
686 }
687
688 ErrorOr reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
689 uint32_t Align) {
741690
742691 // Check for an 'out-of-band' error, e.g. from an MM destructor.
743692 if (ExistingError)
744693 return ExistingError;
745694
746 if (std::error_code EC = call(Channel, Id, Size, Align))
747 return EC;
748
749 return expect(Channel, readArgs(RemoteAddr));
695 return callST(Channel, Id, Size, Align);
750696 }
751697
752698 std::error_code setProtections(ResourceIdMgr::ResourceId Id,
753699 TargetAddress RemoteSegAddr,
754700 unsigned ProtFlags) {
755 return call(Channel, Id, RemoteSegAddr, ProtFlags);
701 return callST(Channel, Id, RemoteSegAddr, ProtFlags);
756702 }
757703
758704 std::error_code writeMem(TargetAddress Addr, const char *Src, uint64_t Size) {
760706 if (ExistingError)
761707 return ExistingError;
762708
763 // Make the send call.
764 if (auto EC = call(Channel, Addr, Size))
765 return EC;
766
767 // Follow this up with the section contents.
768 if (auto EC = Channel.appendBytes(Src, Size))
769 return EC;
770
771 return Channel.send();
709 return callST(Channel, DirectBufferWriter(Src, Addr, Size));
772710 }
773711
774712 std::error_code writePointer(TargetAddress Addr, TargetAddress PtrVal) {
776714 if (ExistingError)
777715 return ExistingError;
778716
779 return call(Channel, Addr, PtrVal);
717 return callST(Channel, Addr, PtrVal);
780718 }
781719
782720 static std::error_code doNothing() { return std::error_code(); }
2323 namespace orc {
2424 namespace remote {
2525
26 class DirectBufferWriter {
27 public:
28 DirectBufferWriter() = default;
29 DirectBufferWriter(const char *Src, TargetAddress Dst, uint64_t Size)
30 : Src(Src), Dst(Dst), Size(Size) {}
31
32 const char *getSrc() const { return Src; }
33 TargetAddress getDst() const { return Dst; }
34 uint64_t getSize() const { return Size; }
35 private:
36 const char *Src;
37 TargetAddress Dst;
38 uint64_t Size;
39 };
40
41 inline std::error_code serialize(RPCChannel &C,
42 const DirectBufferWriter &DBW) {
43 if (auto EC = serialize(C, DBW.getDst()))
44 return EC;
45 if (auto EC = serialize(C, DBW.getSize()))
46 return EC;
47 return C.appendBytes(DBW.getSrc(), DBW.getSize());
48 }
49
50 inline std::error_code deserialize(RPCChannel &C,
51 DirectBufferWriter &DBW) {
52 TargetAddress Dst;
53 if (auto EC = deserialize(C, Dst))
54 return EC;
55 uint64_t Size;
56 if (auto EC = deserialize(C, Size))
57 return EC;
58 char *Addr = reinterpret_cast(static_cast(Dst));
59
60 DBW = DirectBufferWriter(0, Dst, Size);
61
62 return C.readBytes(Addr, Size);
63 }
64
2665 class OrcRemoteTargetRPCAPI : public RPC {
2766 protected:
67
2868 class ResourceIdMgr {
2969 public:
3070 typedef uint64_t ResourceId;
4484 };
4585
4686 public:
47 enum JITProcId : uint32_t {
48 InvalidId = 0,
49 CallIntVoidId,
50 CallIntVoidResponseId,
87 enum JITFuncId : uint32_t {
88 InvalidId = RPCFunctionIdTraits::InvalidId,
89 CallIntVoidId = RPCFunctionIdTraits::FirstValidId,
5190 CallMainId,
52 CallMainResponseId,
5391 CallVoidVoidId,
54 CallVoidVoidResponseId,
5592 CreateRemoteAllocatorId,
5693 CreateIndirectStubsOwnerId,
5794 DeregisterEHFramesId,
5895 DestroyRemoteAllocatorId,
5996 DestroyIndirectStubsOwnerId,
6097 EmitIndirectStubsId,
61 EmitIndirectStubsResponseId,
6298 EmitResolverBlockId,
6399 EmitTrampolineBlockId,
64 EmitTrampolineBlockResponseId,
65100 GetSymbolAddressId,
66 GetSymbolAddressResponseId,
67101 GetRemoteInfoId,
68 GetRemoteInfoResponseId,
69102 ReadMemId,
70 ReadMemResponseId,
71103 RegisterEHFramesId,
72104 ReserveMemId,
73 ReserveMemResponseId,
74105 RequestCompileId,
75 RequestCompileResponseId,
76106 SetProtectionsId,
77107 TerminateSessionId,
78108 WriteMemId,
79109 WritePtrId
80110 };
81111
82 static const char *getJITProcIdName(JITProcId Id);
83
84 typedef Procedure CallIntVoid;
85
86 typedef Procedure
87 CallIntVoidResponse;
88
89 typedef Procedure
90 std::vector Args)>
112 static const char *getJITFuncIdName(JITFuncId Id);
113
114 typedef Function CallIntVoid;
115
116 typedef Function
117 std::vector Args)>
91118 CallMain;
92119
93 typedef Procedure CallMainResponse;
94
95 typedef Procedure CallVoidVoid;
96
97 typedef Procedure CallVoidVoidResponse;
98
99 typedef Procedure
100 void(ResourceIdMgr::ResourceId AllocatorID)>
120 typedef Function CallVoidVoid;
121
122 typedef Function
123 void(ResourceIdMgr::ResourceId AllocatorID)>
101124 CreateRemoteAllocator;
102125
103 typedef Procedure
104 void(ResourceIdMgr::ResourceId StubOwnerID)>
126 typedef Function
127 void(ResourceIdMgr::ResourceId StubOwnerID)>
105128 CreateIndirectStubsOwner;
106129
107 typedef Procedure
108 void(TargetAddress Addr, uint32_t Size)>
130 typedef Function
131 void(TargetAddress Addr, uint32_t Size)>
109132 DeregisterEHFrames;
110133
111 typedef Procedure
112 void(ResourceIdMgr::ResourceId AllocatorID)>
134 typedef Function
135 void(ResourceIdMgr::ResourceId AllocatorID)>
113136 DestroyRemoteAllocator;
114137
115 typedef Procedure
116 void(ResourceIdMgr::ResourceId StubsOwnerID)>
138 typedef Function
139 void(ResourceIdMgr::ResourceId StubsOwnerID)>
117140 DestroyIndirectStubsOwner;
118141
119 typedef Procedure
120 void(ResourceIdMgr::ResourceId StubsOwnerID,
121 uint32_t NumStubsRequired)>
142 /// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted).
143 typedef Function
144 std::tuple(
145 ResourceIdMgr::ResourceId StubsOwnerID,
146 uint32_t NumStubsRequired)>
122147 EmitIndirectStubs;
123148
124 typedef Procedure
125 void(TargetAddress StubsBaseAddr,
126 TargetAddress PtrsBaseAddr,
127 uint32_t NumStubsEmitted)>
128 EmitIndirectStubsResponse;
129
130 typedef Procedure EmitResolverBlock;
131
132 typedef Procedure EmitTrampolineBlock;
133
134 typedef Procedure
135 void(TargetAddress BlockAddr, uint32_t NumTrampolines)>
136 EmitTrampolineBlockResponse;
137
138 typedef Procedure
149 typedef Function EmitResolverBlock;
150
151 /// EmitTrampolineBlock result is (BlockAddr, NumTrampolines).
152 typedef Function
153 std::tuple()> EmitTrampolineBlock;
154
155 typedef Function
139156 GetSymbolAddress;
140157
141 typedef Procedure
142 GetSymbolAddressResponse;
143
144 typedef Procedure GetRemoteInfo;
145
146 typedef Procedure
147 void(std::string Triple, uint32_t PointerSize,
148 uint32_t PageSize, uint32_t TrampolineSize,
149 uint32_t IndirectStubSize)>
150 GetRemoteInfoResponse;
151
152 typedef Procedure
158 /// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize,
159 /// IndirectStubsSize).
160 typedef Function
161 std::tuple
162 uint32_t>()> GetRemoteInfo;
163
164 typedef Function
165 std::vector(TargetAddress Src, uint64_t Size)>
153166 ReadMem;
154167
155 typedef Procedure ReadMemResponse;
156
157 typedef Procedure
158 void(TargetAddress Addr, uint32_t Size)>
168 typedef Function
169 void(TargetAddress Addr, uint32_t Size)>
159170 RegisterEHFrames;
160171
161 typedef Procedure
162 void(ResourceIdMgr::ResourceId AllocID, uint64_t Size,
163 uint32_t Align)>
172 typedef Function
173 TargetAddress(ResourceIdMgr::ResourceId AllocID,
174 uint64_t Size, uint32_t Align)>
164175 ReserveMem;
165176
166 typedef Procedure
167 ReserveMemResponse;
168
169 typedef Procedure
177 typedef Function
178 TargetAddress(TargetAddress TrampolineAddr)>
170179 RequestCompile;
171180
172 typedef Procedure
173 RequestCompileResponse;
174
175 typedef Procedure
176 void(ResourceIdMgr::ResourceId AllocID, TargetAddress Dst,
177 uint32_t ProtFlags)>
181 typedef Function
182 void(ResourceIdMgr::ResourceId AllocID, TargetAddress Dst,
183 uint32_t ProtFlags)>
178184 SetProtections;
179185
180 typedef Procedure TerminateSession;
181
182 typedef Procedure
183 void(TargetAddress Dst, uint64_t Size /* Data to follow */)>
186 typedef Function TerminateSession;
187
188 typedef Function
184189 WriteMem;
185190
186 typedef Procedure
191 typedef Function
187192 WritePtr;
188193 };
189194
4444 EHFramesRegister(std::move(EHFramesRegister)),
4545 EHFramesDeregister(std::move(EHFramesDeregister)) {}
4646
47 std::error_code getNextProcId(JITProcId &Id) {
48 return deserialize(Channel, Id);
49 }
50
51 std::error_code handleKnownProcedure(JITProcId Id) {
47 std::error_code handleKnownFunction(JITFuncId Id) {
5248 typedef OrcRemoteTargetServer ThisT;
5349
54 DEBUG(dbgs() << "Handling known proc: " << getJITProcIdName(Id) << "\n");
50 DEBUG(dbgs() << "Handling known proc: " << getJITFuncIdName(Id) << "\n");
5551
5652 switch (Id) {
5753 case CallIntVoidId:
110106 llvm_unreachable("Unhandled JIT RPC procedure Id.");
111107 }
112108
113 std::error_code requestCompile(TargetAddress &CompiledFnAddr,
114 TargetAddress TrampolineAddr) {
115 if (auto EC = call(Channel, TrampolineAddr))
116 return EC;
117
118 while (1) {
119 JITProcId Id = InvalidId;
120 if (auto EC = getNextProcId(Id))
121 return EC;
122
123 switch (Id) {
124 case RequestCompileResponseId:
125 return handle(Channel,
126 readArgs(CompiledFnAddr));
127 default:
128 if (auto EC = handleKnownProcedure(Id))
129 return EC;
130 }
131 }
132
133 llvm_unreachable("Fell through request-compile command loop.");
109 ErrorOr requestCompile(TargetAddress TrampolineAddr) {
110 auto Listen =
111 [&](RPCChannel &C, uint32_t Id) {
112 return handleKnownFunction(static_cast(Id));
113 };
114
115 return callSTHandling(Channel, Listen, TrampolineAddr);
116 }
117
118 void handleTerminateSession() {
119 handle(Channel, [](){ return std::error_code(); });
134120 }
135121
136122 private:
174160 static std::error_code doNothing() { return std::error_code(); }
175161
176162 static TargetAddress reenter(void *JITTargetAddr, void *TrampolineAddr) {
177 TargetAddress CompiledFnAddr = 0;
178
179163 auto T = static_cast(JITTargetAddr);
180 auto EC = T->requestCompile(
181 CompiledFnAddr, static_cast(
182 reinterpret_cast(TrampolineAddr)));
183 assert(!EC && "Compile request failed");
184 (void)EC;
185 return CompiledFnAddr;
186 }
187
188 std::error_code handleCallIntVoid(TargetAddress Addr) {
164 auto AddrOrErr = T->requestCompile(
165 static_cast(
166 reinterpret_cast(TrampolineAddr)));
167 // FIXME: Allow customizable failure substitution functions.
168 assert(AddrOrErr && "Compile request failed");
169 return *AddrOrErr;
170 }
171
172 ErrorOr handleCallIntVoid(TargetAddress Addr) {
189173 typedef int (*IntVoidFnTy)();
190174 IntVoidFnTy Fn =
191175 reinterpret_cast(static_cast(Addr));
194178 int Result = Fn();
195179 DEBUG(dbgs() << " Result = " << Result << "\n");
196180
197 return call(Channel, Result);
198 }
199
200 std::error_code handleCallMain(TargetAddress Addr,
201 std::vector Args) {
181 return Result;
182 }
183
184 ErrorOr handleCallMain(TargetAddress Addr,
185 std::vector Args) {
202186 typedef int (*MainFnTy)(int, const char *[]);
203187
204188 MainFnTy Fn = reinterpret_cast(static_cast(Addr));
213197 int Result = Fn(ArgC, ArgV.get());
214198 DEBUG(dbgs() << " Result = " << Result << "\n");
215199
216 return call(Channel, Result);
200 return Result;
217201 }
218202
219203 std::error_code handleCallVoidVoid(TargetAddress Addr) {
225209 Fn();
226210 DEBUG(dbgs() << " Complete.\n");
227211
228 return call(Channel);
212 return std::error_code();
229213 }
230214
231215 std::error_code handleCreateRemoteAllocator(ResourceIdMgr::ResourceId Id) {
272256 return std::error_code();
273257 }
274258
275 std::error_code handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id,
276 uint32_t NumStubsRequired) {
259 ErrorOr>
260 handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id,
261 uint32_t NumStubsRequired) {
277262 DEBUG(dbgs() << " ISMgr " << Id << " request " << NumStubsRequired
278263 << " stubs.\n");
279264
295280 auto &BlockList = StubOwnerItr->second;
296281 BlockList.push_back(std::move(IS));
297282
298 return call(Channel, StubsBase, PtrsBase,
299 NumStubsEmitted);
283 return std::make_tuple(StubsBase, PtrsBase, NumStubsEmitted);
300284 }
301285
302286 std::error_code handleEmitResolverBlock() {
315299 sys::Memory::MF_EXEC);
316300 }
317301
318 std::error_code handleEmitTrampolineBlock() {
302 ErrorOr>
303 handleEmitTrampolineBlock() {
319304 std::error_code EC;
320305 auto TrampolineBlock =
321306 sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
324309 if (EC)
325310 return EC;
326311
327 unsigned NumTrampolines =
312 uint32_t NumTrampolines =
328313 (sys::Process::getPageSize() - TargetT::PointerSize) /
329314 TargetT::TrampolineSize;
330315
338323
339324 TrampolineBlocks.push_back(std::move(TrampolineBlock));
340325
341 return call(
342 Channel,
343 static_cast(reinterpret_cast(TrampolineMem)),
344 NumTrampolines);
345 }
346
347 std::error_code handleGetSymbolAddress(const std::string &Name) {
326 auto TrampolineBaseAddr =
327 static_cast(reinterpret_cast(TrampolineMem));
328
329 return std::make_tuple(TrampolineBaseAddr, NumTrampolines);
330 }
331
332 ErrorOr handleGetSymbolAddress(const std::string &Name) {
348333 TargetAddress Addr = SymbolLookup(Name);
349334 DEBUG(dbgs() << " Symbol '" << Name << "' = " << format("0x%016x", Addr)
350335 << "\n");
351 return call(Channel, Addr);
352 }
353
354 std::error_code handleGetRemoteInfo() {
336 return Addr;
337 }
338
339 ErrorOr>
340 handleGetRemoteInfo() {
355341 std::string ProcessTriple = sys::getProcessTriple();
356342 uint32_t PointerSize = TargetT::PointerSize;
357343 uint32_t PageSize = sys::Process::getPageSize();
363349 << " page size = " << PageSize << "\n"
364350 << " trampoline size = " << TrampolineSize << "\n"
365351 << " indirect stub size = " << IndirectStubSize << "\n");
366 return call(Channel, ProcessTriple, PointerSize,
367 PageSize, TrampolineSize,
368 IndirectStubSize);
369 }
370
371 std::error_code handleReadMem(TargetAddress RSrc, uint64_t Size) {
352 return std::make_tuple(ProcessTriple, PointerSize, PageSize ,TrampolineSize,
353 IndirectStubSize);
354 }
355
356 ErrorOr>
357 handleReadMem(TargetAddress RSrc, uint64_t Size) {
372358 char *Src = reinterpret_cast(static_cast(RSrc));
373359
374360 DEBUG(dbgs() << " Reading " << Size << " bytes from "
375361 << format("0x%016x", RSrc) << "\n");
376362
377 if (auto EC = call(Channel))
378 return EC;
379
380 if (auto EC = Channel.appendBytes(Src, Size))
381 return EC;
382
383 return Channel.send();
363 std::vector Buffer;
364 Buffer.resize(Size);
365 for (char *P = Src; Size != 0; --Size)
366 Buffer.push_back(*P++);
367
368 return Buffer;
384369 }
385370
386371 std::error_code handleRegisterEHFrames(TargetAddress TAddr, uint32_t Size) {
391376 return std::error_code();
392377 }
393378
394 std::error_code handleReserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
395 uint32_t Align) {
379 ErrorOr
380 handleReserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
381 uint32_t Align) {
396382 auto I = Allocators.find(Id);
397383 if (I == Allocators.end())
398384 return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
407393 TargetAddress AllocAddr =
408394 static_cast(reinterpret_cast(LocalAllocAddr));
409395
410 return call(Channel, AllocAddr);
396 return AllocAddr;
411397 }
412398
413399 std::error_code handleSetProtections(ResourceIdMgr::ResourceId Id,
424410 return Allocator.setProtections(LocalAddr, Flags);
425411 }
426412
427 std::error_code handleWriteMem(TargetAddress RDst, uint64_t Size) {
428 char *Dst = reinterpret_cast(static_cast(RDst));
429 DEBUG(dbgs() << " Writing " << Size << " bytes to "
430 << format("0x%016x", RDst) << "\n");
431 return Channel.readBytes(Dst, Size);
413 std::error_code handleWriteMem(DirectBufferWriter DBW) {
414 DEBUG(dbgs() << " Writing " << DBW.getSize() << " bytes to "
415 << format("0x%016x", DBW.getDst()) << "\n");
416 return std::error_code();
432417 }
433418
434419 std::error_code handleWritePtr(TargetAddress Addr, TargetAddress PtrVal) {
44
55 #include "OrcError.h"
66 #include "llvm/ADT/ArrayRef.h"
7 #include "llvm/ADT/STLExtras.h"
78 #include "llvm/Support/Endian.h"
89
10 #include
911 #include
1012
1113 namespace llvm {
2527
2628 /// Flush the stream if possible.
2729 virtual std::error_code send() = 0;
30
31 /// Get the lock for stream reading.
32 std::mutex& getReadLock() { return readLock; }
33
34 /// Get the lock for stream writing.
35 std::mutex& getWriteLock() { return writeLock; }
36
37 private:
38 std::mutex readLock, writeLock;
2839 };
40
41 /// Notify the channel that we're starting a message send.
42 /// Locks the channel for writing.
43 inline std::error_code startSendMessage(RPCChannel &C) {
44 C.getWriteLock().lock();
45 return std::error_code();
46 }
47
48 /// Notify the channel that we're ending a message send.
49 /// Unlocks the channel for writing.
50 inline std::error_code endSendMessage(RPCChannel &C) {
51 C.getWriteLock().unlock();
52 return std::error_code();
53 }
54
55 /// Notify the channel that we're starting a message receive.
56 /// Locks the channel for reading.
57 inline std::error_code startReceiveMessage(RPCChannel &C) {
58 C.getReadLock().lock();
59 return std::error_code();
60 }
61
62 /// Notify the channel that we're ending a message receive.
63 /// Unlocks the channel for reading.
64 inline std::error_code endReceiveMessage(RPCChannel &C) {
65 C.getReadLock().unlock();
66 return std::error_code();
67 }
2968
3069 /// RPC channel serialization for a variadic list of arguments.
3170 template
32 std::error_code serialize_seq(RPCChannel &C, const T &Arg, const Ts &... Args) {
71 std::error_code serializeSeq(RPCChannel &C, const T &Arg, const Ts &... Args) {
3372 if (auto EC = serialize(C, Arg))
3473 return EC;
35 return serialize_seq(C, Args...);
74 return serializeSeq(C, Args...);
3675 }
3776
3877 /// RPC channel serialization for an (empty) variadic list of arguments.
39 inline std::error_code serialize_seq(RPCChannel &C) {
78 inline std::error_code serializeSeq(RPCChannel &C) {
4079 return std::error_code();
4180 }
4281
4382 /// RPC channel deserialization for a variadic list of arguments.
4483 template
45 std::error_code deserialize_seq(RPCChannel &C, T &Arg, Ts &... Args) {
84 std::error_code deserializeSeq(RPCChannel &C, T &Arg, Ts &... Args) {
4685 if (auto EC = deserialize(C, Arg))
4786 return EC;
48 return deserialize_seq(C, Args...);
87 return deserializeSeq(C, Args...);
4988 }
5089
5190 /// RPC channel serialization for an (empty) variadic list of arguments.
52 inline std::error_code deserialize_seq(RPCChannel &C) {
91 inline std::error_code deserializeSeq(RPCChannel &C) {
5392 return std::error_code();
5493 }
5594
137176 return C.readBytes(&S[0], Count);
138177 }
139178
179 // Serialization helper for std::tuple.
180 template
181 inline std::error_code serializeTupleHelper(RPCChannel &C,
182 const TupleT &V,
183 llvm::index_sequence _) {
184 return serializeSeq(C, std::get(V)...);
185 }
186
187 /// RPC channel serialization for std::tuple.
188 template
189 inline std::error_code serialize(RPCChannel &C, const std::tuple &V) {
190 return serializeTupleHelper(C, V, llvm::index_sequence_for());
191 }
192
193 // Serialization helper for std::tuple.
194 template
195 inline std::error_code deserializeTupleHelper(RPCChannel &C,
196 TupleT &V,
197 llvm::index_sequence _) {
198 return deserializeSeq(C, std::get(V)...);
199 }
200
201 /// RPC channel deserialization for std::tuple.
202 template
203 inline std::error_code deserialize(RPCChannel &C, std::tuple &V) {
204 return deserializeTupleHelper(C, V, llvm::index_sequence_for());
205 }
206
140207 /// RPC channel serialization for ArrayRef.
141208 template
142209 std::error_code serialize(RPCChannel &C, const ArrayRef &A) {
1313 #ifndef LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
1414 #define LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
1515
16 #include "llvm/ADT/Optional.h"
1617 #include "llvm/ADT/STLExtras.h"
1718 #include "llvm/ExecutionEngine/Orc/OrcError.h"
19 #include "llvm/Support/ErrorOr.h"
20
21 #ifdef _MSC_VER
22 // concrt.h depends on eh.h for __uncaught_exception declaration
23 // even if we disable exceptions.
24 #include
25
26 // Disable warnings from ppltasks.h transitively included by .
27 #pragma warning(push)
28 #pragma warning(disable : 4530)
29 #pragma warning(disable : 4062)
30 #endif
31
32 #include
33
34 #ifdef _MSC_VER
35 #pragma warning(pop)
36 #endif
37
38 #include
1839
1940 namespace llvm {
2041 namespace orc {
2142 namespace remote {
43
44 /// Describes reserved RPC Function Ids.
45 ///
46 /// The default implementation will serve for integer and enum function id
47 /// types. If you want to use a custom type as your FunctionId you can
48 /// specialize this class and provide unique values for InvalidId,
49 /// ResponseId and FirstValidId.
50
51 template class RPCFunctionIdTraits {
52 public:
53 static const T InvalidId = static_cast(0);
54 static const T ResponseId = static_cast(1);
55 static const T FirstValidId = static_cast(2);
56 };
2257
2358 // Base class containing utilities that require partial specialization.
2459 // These cannot be included in RPC, as template class members cannot be
2560 // partially specialized.
2661 class RPCBase {
2762 protected:
28 template
29 class ProcedureHelper {
30 public:
31 static const ProcedureIdT Id = ProcId;
32 };
33
34 template class CallHelper;
35
36 template
63 // RPC Function description type.
64 //
65 // This class provides the information and operations needed to support the
66 // RPC primitive operations (call, expect, etc) for a given function. It
67 // is specialized for void and non-void functions to deal with the differences
68 // betwen the two. Both specializations have the same interface:
69 //
70 // Id - The function's unique identifier.
71 // OptionalReturn - The return type for asyncronous calls.
72 // ErrorReturn - The return type for synchronous calls.
73 // optionalToErrorReturn - Conversion from a valid OptionalReturn to an
74 // ErrorReturn.
75 // readResult - Deserialize a result from a channel.
76 // abandon - Abandon a promised (asynchronous) result.
77 // respond - Retun a result on the channel.
78 template
79 class FunctionHelper {};
80
81 // RPC Function description specialization for non-void functions.
82 template
3783 typename... ArgTs>
38 class CallHelper
39 ProcedureHelper> {
40 public:
41 static std::error_code call(ChannelT &C, const ArgTs &... Args) {
42 if (auto EC = serialize(C, ProcId))
43 return EC;
44 // If you see a compile-error on this line you're probably calling a
45 // function with the wrong signature.
46 return serialize_seq(C, Args...);
47 }
48 };
49
50 template class HandlerHelper;
51
52 template
53 typename... ArgTs>
54 class HandlerHelper
55 ProcedureHelper> {
84 class FunctionHelper> {
85 public:
86 static_assert(FuncId != RPCFunctionIdTraits::InvalidId &&
87 FuncId != RPCFunctionIdTraits::ResponseId,
88 "Cannot define custom function with InvalidId or ResponseId. "
89 "Please use RPCFunctionTraits::FirstValidId.");
90
91 static const FunctionIdT Id = FuncId;
92
93 typedef Optional OptionalReturn;
94
95 typedef ErrorOr ErrorReturn;
96
97 static ErrorReturn optionalToErrorReturn(OptionalReturn &&V) {
98 assert(V && "Return value not available");
99 return std::move(*V);
100 }
101
102 template
103 static std::error_code readResult(ChannelT &C,
104 std::promise &P) {
105 RetT Val;
106 auto EC = deserialize(C, Val);
107 // FIXME: Join error EC2 from endReceiveMessage with the deserialize
108 // error once we switch to using Error.
109 auto EC2 = endReceiveMessage(C);
110 (void)EC2;
111
112 if (EC) {
113 P.set_value(OptionalReturn());
114 return EC;
115 }
116 P.set_value(std::move(Val));
117 return std::error_code();
118 }
119
120 static void abandon(std::promise &P) {
121 P.set_value(OptionalReturn());
122 }
123
124 template
125 static std::error_code respond(ChannelT &C, SequenceNumberT SeqNo,
126 const ErrorReturn &Result) {
127 FunctionIdT ResponseId = RPCFunctionIdTraits::ResponseId;
128
129 // If the handler returned an error then bail out with that.
130 if (!Result)
131 return Result.getError();
132
133 // Otherwise open a new message on the channel and send the result.
134 if (auto EC = startSendMessage(C))
135 return EC;
136 if (auto EC = serializeSeq(C, ResponseId, SeqNo, *Result))
137 return EC;
138 return endSendMessage(C);
139 }
140 };
141
142 // RPC Function description specialization for void functions.
143 template
144 class FunctionHelper {
145 public:
146 static_assert(FuncId != RPCFunctionIdTraits::InvalidId &&
147 FuncId != RPCFunctionIdTraits::ResponseId,
148 "Cannot define custom function with InvalidId or ResponseId. "
149 "Please use RPCFunctionTraits::FirstValidId.");
150
151 static const FunctionIdT Id = FuncId;
152
153 typedef bool OptionalReturn;
154 typedef std::error_code ErrorReturn;
155
156 static ErrorReturn optionalToErrorReturn(OptionalReturn &&V) {
157 assert(V && "Return value not available");
158 return std::error_code();
159 }
160
161 template
162 static std::error_code readResult(ChannelT &C,
163 std::promise &P) {
164 // Void functions don't have anything to deserialize, so we're good.
165 P.set_value(true);
166 return endReceiveMessage(C);
167 }
168
169 static void abandon(std::promise &P) { P.set_value(false); }
170
171 template
172 static std::error_code respond(ChannelT &C, SequenceNumberT SeqNo,
173 const ErrorReturn &Result) {
174 const FunctionIdT ResponseId =
175 RPCFunctionIdTraits::ResponseId;
176
177 // If the handler returned an error then bail out with that.
178 if (Result)
179 return Result;
180
181 // Otherwise open a new message on the channel and send the result.
182 if (auto EC = startSendMessage(C))
183 return EC;
184 if (auto EC = serializeSeq(C, ResponseId, SeqNo))
185 return EC;
186 return endSendMessage(C);
187 }
188 };
189
190 // Helper for the call primitive.
191 template
192 class CallHelper;
193
194 template
195 FunctionIdT FuncId, typename RetT, typename... ArgTs>
196 class CallHelper
197 FunctionHelper> {
198 public:
199 static std::error_code call(ChannelT &C, SequenceNumberT SeqNo,
200 const ArgTs &... Args) {
201 if (auto EC = startSendMessage(C))
202 return EC;
203 if (auto EC = serializeSeq(C, FuncId, SeqNo, Args...))
204 return EC;
205 return endSendMessage(C);
206 }
207 };
208
209 // Helper for handle primitive.
210 template
211 class HandlerHelper;
212
213 template
214 FunctionIdT FuncId, typename RetT, typename... ArgTs>
215 class HandlerHelper
216 FunctionHelper> {
56217 public:
57218 template
58219 static std::error_code handle(ChannelT &C, HandlerT Handler) {
60221 }
61222
62223 private:
224 typedef FunctionHelper Func;
225
63226 template
64227 static std::error_code readAndHandle(ChannelT &C, HandlerT Handler,
65228 llvm::index_sequence _) {
66229 std::tuple RPCArgs;
230 SequenceNumberT SeqNo;
67231 // GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning
68232 // for RPCArgs. Void cast RPCArgs to work around this for now.
69233 // FIXME: Remove this workaround once we can assume a working GCC version.
70234 (void)RPCArgs;
71 if (auto EC = deserialize_seq(C, std::get(RPCArgs)...))
72 return EC;
73 return Handler(std::get(RPCArgs)...);
74 }
75 };
76
77 template class MemberFnWrapper {
78 public:
79 typedef std::error_code (ClassT::*MethodT)(ArgTs...);
235 if (auto EC = deserializeSeq(C, SeqNo, std::get(RPCArgs)...))
236 return EC;
237
238 // We've deserialized the arguments, so unlock the channel for reading
239 // before we call the handler. This allows recursive RPC calls.
240 if (auto EC = endReceiveMessage(C))
241 return EC;
242
243 return Func::template respond(
244 C, SeqNo, Handler(std::get(RPCArgs)...));
245 }
246 };
247
248 // Helper for wrapping member functions up as functors.
249 template
250 class MemberFnWrapper {
251 public:
252 typedef RetT (ClassT::*MethodT)(ArgTs...);
80253 MemberFnWrapper(ClassT &Instance, MethodT Method)
81254 : Instance(Instance), Method(Method) {}
82 std::error_code operator()(ArgTs &... Args) {
83 return (Instance.*Method)(Args...);
84 }
255 RetT operator()(ArgTs &... Args) { return (Instance.*Method)(Args...); }
85256
86257 private:
87258 ClassT &Instance;
88259 MethodT Method;
89260 };
90261
262 // Helper that provides a Functor for deserializing arguments.
91263 template class ReadArgs {
92264 public:
93265 std::error_code operator()() { return std::error_code(); }
111283
112284 /// Contains primitive utilities for defining, calling and handling calls to
113285 /// remote procedures. ChannelT is a bidirectional stream conforming to the
114 /// RPCChannel interface (see RPCChannel.h), and ProcedureIdT is a procedure
286 /// RPCChannel interface (see RPCChannel.h), and FunctionIdT is a procedure
115287 /// identifier type that must be serializable on ChannelT.
116288 ///
117289 /// These utilities support the construction of very primitive RPC utilities.
128300 ///
129301 /// Overview (see comments individual types/methods for details):
130302 ///
131 /// Procedure :
303 /// Function :
132304 ///
133305 /// associates a unique serializable id with an argument list.
134306 ///
135307 ///
136 /// call(Channel, Args...) :
137 ///
138 /// Calls the remote procedure 'Proc' by serializing Proc's id followed by its
308 /// call(Channel, Args...) :
309 ///
310 /// Calls the remote procedure 'Func' by serializing Func's id followed by its
139311 /// arguments and sending the resulting bytes to 'Channel'.
140312 ///
141313 ///
142 /// handle(Channel, :
143 ///
144 /// Handles a call to 'Proc' by deserializing its arguments and calling the
145 /// given functor. This assumes that the id for 'Proc' has already been
314 /// handle(Channel, :
315 ///
316 /// Handles a call to 'Func' by deserializing its arguments and calling the
317 /// given functor. This assumes that the id for 'Func' has already been
146318 /// deserialized.
147319 ///
148 /// expect<Proc>(Channel, :
320 /// expect<Func>(Channel, :
149321 ///
150322 /// The same as 'handle', except that the procedure id should not have been
151 /// read yet. Expect will deserialize the id and assert that it matches Proc's
323 /// read yet. Expect will deserialize the id and assert that it matches Func's
152324 /// id. If it does not, and unexpected RPC call error is returned.
153
154 template ProcedureIdT = uint32_t>
325 template FunctionIdT = uint32_t,
326 typename SequenceNumberT = uint16_t>
155327 class RPC : public RPCBase {
156328 public:
157329 /// Utility class for defining/referring to RPC procedures.
158330 ///
159331 /// Typedefs of this utility are used when calling/handling remote procedures.
160332 ///
161 /// ProcId should be a unique value of ProcedureIdT (i.e. not used with any
162 /// other Procedure typedef in the RPC API being defined.
333 /// FuncId should be a unique value of FunctionIdT (i.e. not used with any
334 /// other Function typedef in the RPC API being defined.
163335 ///
164336 /// the template argument Ts... gives the argument list for the remote
165337 /// procedure.
166338 ///
167339 /// E.g.
168340 ///
169 /// typedef Procedure<0, bool> Proc1;
170 /// typedef Procedure<1, std::string, std::vector> Proc2;
171 ///
172 /// if (auto EC = call(Channel, true))
341 /// typedef Function<0, bool> Func1;
342 /// typedef Function<1, std::string, std::vector> Func2;
343 ///
344 /// if (auto EC = call(Channel, true))
173345 /// /* handle EC */;
174346 ///
175 /// if (auto EC = expect<Proc2>(Channel,
347 /// if (auto EC = expect<Func2>(Channel,
176348 /// [](std::string &S, std::vector &V) {
177349 /// // Stuff.
178350 /// return std::error_code();
179351 /// })
180352 /// /* handle EC */;
181353 ///
182 template
183 using Procedure = ProcedureHelper;
354 template
355 using Function = FunctionHelper;
356
357 /// Return type for asynchronous call primitives.
358 template
359 using AsyncCallResult =
360 std::pair, SequenceNumberT>;
184361
185362 /// Serialize Args... to channel C, but do not call C.send().
186363 ///
187 /// For buffered channels, this can be used to queue up several calls before
188 /// flushing the channel.
189 template
190 static std::error_code appendCall(ChannelT &C, const ArgTs &... Args) {
191 return CallHelper::call(C, Args...);
364 /// For void functions returns a std::future. For functions that
365 /// return an R, returns a std::future>.
366 template
367 ErrorOr> appendCallAsync(ChannelT &C,
368 const ArgTs &... Args) {
369 auto SeqNo = SequenceNumberMgr.getSequenceNumber();
370 std::promise Promise;
371 auto Result = Promise.get_future();
372 OutstandingResults[SeqNo] = std::move(Promise);
373
374 if (auto EC = CallHelper::call(C, SeqNo,
375 Args...)) {
376 abandonOutstandingResults();
377 return EC;
378 } else
379 return AsyncCallResult(std::move(Result), SeqNo);
192380 }
193381
194382 /// Serialize Args... to channel C and call C.send().
195 template
196 static std::error_code call(ChannelT &C, const ArgTs &... Args) {
197 if (auto EC = appendCall(C, Args...))
383 template
384 ErrorOr> callAsync(ChannelT &C, const ArgTs &... Args) {
385 auto SeqNo = SequenceNumberMgr.getSequenceNumber();
386 std::promise Promise;
387 auto Result = Promise.get_future();
388 OutstandingResults[SeqNo] =
389 createOutstandingResult(std::move(Promise));
390 if (auto EC = CallHelper::call(C, SeqNo,
391 Args...)) {
392 abandonOutstandingResults();
198393 return EC;
199 return C.send();
200 }
201
202 /// Deserialize and return an enum whose underlying type is ProcedureIdT.
203 static std::error_code getNextProcId(ChannelT &C, ProcedureIdT &Id) {
394 }
395 if (auto EC = C.send()) {
396 abandonOutstandingResults();
397 return EC;
398 }
399 return AsyncCallResult(std::move(Result), SeqNo);
400 }
401
402 /// This can be used in single-threaded mode.
403 template
404 typename Func::ErrorReturn
405 callSTHandling(ChannelT &C, HandleFtor &HandleOther, const ArgTs &... Args) {
406 if (auto ResultAndSeqNoOrErr = callAsync(C, Args...)) {
407 auto &ResultAndSeqNo = *ResultAndSeqNoOrErr;
408 if (auto EC = waitForResult(C, ResultAndSeqNo.second, HandleOther))
409 return EC;
410 return Func::optionalToErrorReturn(ResultAndSeqNo.first.get());
411 } else
412 return ResultAndSeqNoOrErr.getError();
413 }
414
415 // This can be used in single-threaded mode.
416 template
417 typename Func::ErrorReturn callST(ChannelT &C, const ArgTs &... Args) {
418 return callSTHandling(C, handleNone, Args...);
419 }
420
421 /// Start receiving a new function call.
422 ///
423 /// Calls startReceiveMessage on the channel, then deserializes a FunctionId
424 /// into Id.
425 std::error_code startReceivingFunction(ChannelT &C, FunctionIdT &Id) {
426 if (auto EC = startReceiveMessage(C))
427 return EC;
428
204429 return deserialize(C, Id);
205430 }
206431
207 /// Deserialize args for Proc from C and call Handler. The signature of
432 /// Deserialize args for Func from C and call Handler. The signature of
208433 /// handler must conform to 'std::error_code(Args...)' where Args... matches
209 /// the arguments used in the Proc typedef.
210 template
434 /// the arguments used in the Func typedef.
435 template
211436 static std::error_code handle(ChannelT &C, HandlerT Handler) {
212 return HandlerHelperProc>::handle(C, Handler);
437 return HandlerHelperSequenceNumberT, Func>::handle(C, Handler);
213438 }
214439
215440 /// Helper version of 'handle' for calling member functions.
216 template
217 static std::error_code
218 handle(ChannelT &C, ClassT &Instance,
219 std::error_code (ClassT::*HandlerMethod)(ArgTs...)) {
220 return handle(
221 C, MemberFnWrapper(Instance, HandlerMethod));
222 }
223
224 /// Deserialize a ProcedureIdT from C and verify it matches the id for Proc.
441 template
442 static std::error_code handle(ChannelT &C, ClassT &Instance,
443 RetT (ClassT::*HandlerMethod)(ArgTs...)) {
444 return handle(
445 C, MemberFnWrapper(Instance, HandlerMethod));
446 }
447
448 /// Deserialize a FunctionIdT from C and verify it matches the id for Func.
225449 /// If the id does match, deserialize the arguments and call the handler
226450 /// (similarly to handle).
227451 /// If the id does not match, return an unexpect RPC call error and do not
228452 /// deserialize any further bytes.
229 template
230 static std::error_code expect(ChannelT &C, HandlerT Handler) {
231 ProcedureIdT ProcId;
232 if (auto EC = getNextProcId(C, ProcId))
233 return EC;
234 if (ProcId != Proc::Id)
453 template
454 std::error_code expect(ChannelT &C, HandlerT Handler) {
455 FunctionIdT FuncId;
456 if (auto EC = startReceivingFunction(C, FuncId))
457 return std::move(EC);
458 if (FuncId != Func::Id)
235459 return orcError(OrcErrorCode::UnexpectedRPCCall);
236 return handle<Proc>(C, Handler);
460 return handle<Func>(C, Handler);
237461 }
238462
239463 /// Helper version of expect for calling member functions.
240 template Proc, typename ClassT, typename... ArgTs>
464 template Func, typename ClassT, typename... ArgTs>
241465 static std::error_code
242466 expect(ChannelT &C, ClassT &Instance,
243467 std::error_code (ClassT::*HandlerMethod)(ArgTs...)) {
244 return expect<Proc>(
468 return expect<Func>(
245469 C, MemberFnWrapper(Instance, HandlerMethod));
246470 }
247471
250474 /// channel.
251475 /// E.g.
252476 ///
253 /// typedef Procedure<0, bool, int> Proc1;
477 /// typedef Function<0, bool, int> Func1;
254478 ///
255479 /// ...
256480 /// bool B;
257481 /// int I;
258 /// if (auto EC = expect<Proc1>(Channel, readArgs(B, I)))
482 /// if (auto EC = expect<Func1>(Channel, readArgs(B, I)))
259483 /// /* Handle Args */ ;
260484 ///
261485 template
262486 static ReadArgs readArgs(ArgTs &... Args) {
263487 return ReadArgs(Args...);
264488 }
489
490 /// Read a response from Channel.
491 /// This should be called from the receive loop to retrieve results.
492 std::error_code handleResponse(ChannelT &C, SequenceNumberT &SeqNo) {
493 if (auto EC = deserialize(C, SeqNo)) {
494 abandonOutstandingResults();
495 return EC;
496 }
497
498 auto I = OutstandingResults.find(SeqNo);
499 if (I == OutstandingResults.end()) {
500 abandonOutstandingResults();
501 return orcError(OrcErrorCode::UnexpectedRPCResponse);
502 }
503
504 if (auto EC = I->second->readResult(C)) {
505 abandonOutstandingResults();
506 // FIXME: Release sequence numbers?
507 return EC;
508 }
509
510 OutstandingResults.erase(I);
511 SequenceNumberMgr.releaseSequenceNumber(SeqNo);
512
513 return std::error_code();
514 }
515
516 // Loop waiting for a result with the given sequence number.
517 // This can be used as a receive loop if the user doesn't have a default.
518 template
519 std::error_code waitForResult(ChannelT &C, SequenceNumberT TgtSeqNo,
520 HandleOtherFtor &HandleOther = handleNone) {
521 bool GotTgtResult = false;
522
523 while (!GotTgtResult) {
524 FunctionIdT Id = RPCFunctionIdTraits::InvalidId;
525 if (auto EC = startReceivingFunction(C, Id))
526 return EC;
527 if (Id == RPCFunctionIdTraits::ResponseId) {
528 SequenceNumberT SeqNo;
529 if (auto EC = handleResponse(C, SeqNo))
530 return EC;
531 GotTgtResult = (SeqNo == TgtSeqNo);
532 } else if (auto EC = HandleOther(C, Id))
533 return EC;
534 }
535
536 return std::error_code();
537 }
538
539 // Default handler for 'other' (non-response) functions when waiting for a
540 // result from the channel.
541 static std::error_code handleNone(ChannelT &, FunctionIdT) {
542 return orcError(OrcErrorCode::UnexpectedRPCCall);
543 };
544
545 private:
546 // Manage sequence numbers.
547 class SequenceNumberManager {
548 public:
549 SequenceNumberManager() = default;
550
551 SequenceNumberManager(SequenceNumberManager &&Other)
552 : NextSequenceNumber(std::move(Other.NextSequenceNumber)),
553 FreeSequenceNumbers(std::move(Other.FreeSequenceNumbers)) {}
554
555 SequenceNumberManager &operator=(SequenceNumberManager &&Other) {
556 NextSequenceNumber = std::move(Other.NextSequenceNumber);
557 FreeSequenceNumbers = std::move(Other.FreeSequenceNumbers);
558 }
559
560 void reset() {
561 std::lock_guard Lock(SeqNoLock);
562 NextSequenceNumber = 0;
563 FreeSequenceNumbers.clear();
564 }
565
566 SequenceNumberT getSequenceNumber() {
567 std::lock_guard Lock(SeqNoLock);
568 if (FreeSequenceNumbers.empty())
569 return NextSequenceNumber++;
570 auto SequenceNumber = FreeSequenceNumbers.back();
571 FreeSequenceNumbers.pop_back();
572 return SequenceNumber;
573 }
574
575 void releaseSequenceNumber(SequenceNumberT SequenceNumber) {
576 std::lock_guard Lock(SeqNoLock);
577 FreeSequenceNumbers.push_back(SequenceNumber);
578 }
579
580 private:
581 std::mutex SeqNoLock;
582 SequenceNumberT NextSequenceNumber = 0;
583 std::vector FreeSequenceNumbers;
584 };
585
586 // Base class for results that haven't been returned from the other end of the
587 // RPC connection yet.
588 class OutstandingResult {
589 public:
590 virtual ~OutstandingResult() {}
591 virtual std::error_code readResult(ChannelT &C) = 0;
592 virtual void abandon() = 0;
593 };
594
595 // Outstanding results for a specific function.
596 template
597 class OutstandingResultImpl : public OutstandingResult {
598 private:
599 public:
600 OutstandingResultImpl(std::promise &&P)
601 : P(std::move(P)) {}
602
603 std::error_code readResult(ChannelT &C) override {
604 return Func::readResult(C, P);
605 }
606
607 void abandon() override { Func::abandon(P); }
608
609 private:
610 std::promise P;
611 };
612
613 // Create an outstanding result for the given function.
614 template
615 std::unique_ptr
616 createOutstandingResult(std::promise &&P) {
617 return llvm::make_unique>(std::move(P));
618 }
619
620 // Abandon all outstanding results.
621 void abandonOutstandingResults() {
622 for (auto &KV : OutstandingResults)
623 KV.second->abandon();
624 OutstandingResults.clear();
625 SequenceNumberMgr.reset();
626 }
627
628 SequenceNumberManager SequenceNumberMgr;
629 std::map>
630 OutstandingResults;
265631 };
266632
267633 } // end namespace remote
3737 return "Remote indirect stubs owner Id already in use";
3838 case OrcErrorCode::UnexpectedRPCCall:
3939 return "Unexpected RPC call";
40 case OrcErrorCode::UnexpectedRPCResponse:
41 return "Unexpected RPC response";
4042 }
4143 llvm_unreachable("Unhandled error code");
4244 }
1212 namespace orc {
1313 namespace remote {
1414
15 #define PROCNAME(X) \
15 #define FUNCNAME(X) \
1616 case X ## Id: \
1717 return #X
1818
19 const char *OrcRemoteTargetRPCAPI::getJITProcIdName(JITProcId Id) {
19 const char *OrcRemoteTargetRPCAPI::getJITFuncIdName(JITFuncId Id) {
2020 switch (Id) {
2121 case InvalidId:
22 return "*** Invalid JITProcId ***";
23 PROCNAME(CallIntVoid);
24 PROCNAME(CallIntVoidResponse);
25 PROCNAME(CallMain);
26 PROCNAME(CallMainResponse);
27 PROCNAME(CallVoidVoid);
28 PROCNAME(CallVoidVoidResponse);
29 PROCNAME(CreateRemoteAllocator);
30 PROCNAME(CreateIndirectStubsOwner);
31 PROCNAME(DeregisterEHFrames);
32 PROCNAME(DestroyRemoteAllocator);
33 PROCNAME(DestroyIndirectStubsOwner);
34 PROCNAME(EmitIndirectStubs);
35 PROCNAME(EmitIndirectStubsResponse);
36 PROCNAME(EmitResolverBlock);
37 PROCNAME(EmitTrampolineBlock);
38 PROCNAME(EmitTrampolineBlockResponse);
39 PROCNAME(GetSymbolAddress);
40 PROCNAME(GetSymbolAddressResponse);
41 PROCNAME(GetRemoteInfo);
42 PROCNAME(GetRemoteInfoResponse);
43 PROCNAME(ReadMem);
44 PROCNAME(ReadMemResponse);
45 PROCNAME(RegisterEHFrames);
46 PROCNAME(ReserveMem);
47 PROCNAME(ReserveMemResponse);
48 PROCNAME(RequestCompile);
49 PROCNAME(RequestCompileResponse);
50 PROCNAME(SetProtections);
51 PROCNAME(TerminateSession);
52 PROCNAME(WriteMem);
53 PROCNAME(WritePtr);
22 return "*** Invalid JITFuncId ***";
23 FUNCNAME(CallIntVoid);
24 FUNCNAME(CallMain);
25 FUNCNAME(CallVoidVoid);
26 FUNCNAME(CreateRemoteAllocator);
27 FUNCNAME(CreateIndirectStubsOwner);
28 FUNCNAME(DeregisterEHFrames);
29 FUNCNAME(DestroyRemoteAllocator);
30 FUNCNAME(DestroyIndirectStubsOwner);
31 FUNCNAME(EmitIndirectStubs);
32 FUNCNAME(EmitResolverBlock);
33 FUNCNAME(EmitTrampolineBlock);
34 FUNCNAME(GetSymbolAddress);
35 FUNCNAME(GetRemoteInfo);
36 FUNCNAME(ReadMem);
37 FUNCNAME(RegisterEHFrames);
38 FUNCNAME(ReserveMem);
39 FUNCNAME(RequestCompile);
40 FUNCNAME(SetProtections);
41 FUNCNAME(TerminateSession);
42 FUNCNAME(WriteMem);
43 FUNCNAME(WritePtr);
5444 };
5545 return nullptr;
5646 }
5747
58 #undef PROCNAME
48 #undef FUNCNAME
5949
6050 } // end namespace remote
6151 } // end namespace orc
5353 JITServer Server(Channel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames);
5454
5555 while (1) {
56 JITServer::JITProcId Id = JITServer::InvalidId;
57 if (auto EC = Server.getNextProcId(Id)) {
56 uint32_t RawId;
57 if (auto EC = Server.startReceivingFunction(Channel, RawId)) {
5858 errs() << "Error: " << EC.message() << "\n";
5959 return 1;
6060 }
61 auto Id = static_cast(RawId);
6162 switch (Id) {
6263 case JITServer::TerminateSessionId:
64 Server.handleTerminateSession();
6365 return 0;
6466 default:
65 if (auto EC = Server.handleKnownProcedure(Id)) {
67 if (auto EC = Server.handleKnownFunction(Id)) {
6668 errs() << "Error: " << EC.message() << "\n";
6769 return 1;
6870 }
1515
1616 #include "llvm/ExecutionEngine/Orc/RPCChannel.h"
1717 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
18 #include
1819
1920 #if !defined(_MSC_VER) && !defined(__MINGW32__)
2021 #include
569569 // Reset errno to zero on entry to main.
570570 errno = 0;
571571
572 int Result;
572 int Result = -1;
573573
574574 // Sanity check use of remote-jit: LLI currently only supports use of the
575575 // remote JIT on Unix platforms.
668668 static_cast(RTDyldMM)->setResolver(
669669 orc::createLambdaResolver(
670670 [&](const std::string &Name) {
671 orc::TargetAddress Addr = 0;
672 if (auto EC = R->getSymbolAddress(Addr, Name)) {
673 errs() << "Failure during symbol lookup: " << EC.message() << "\n";
674 exit(1);
675 }
676 return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported);
671 if (auto AddrOrErr = R->getSymbolAddress(Name))
672 return RuntimeDyld::SymbolInfo(*AddrOrErr, JITSymbolFlags::Exported);
673 else {
674 errs() << "Failure during symbol lookup: "
675 << AddrOrErr.getError().message() << "\n";
676 exit(1);
677 }
677678 },
678679 [](const std::string &Name) { return nullptr; }
679680 ));
685686 EE->finalizeObject();
686687 DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
687688 << format("%llx", Entry) << "\n");
688 if (auto EC = R->callIntVoid(Result, Entry))
689 errs() << "ERROR: " << EC.message() << "\n";
689 if (auto ResultOrErr = R->callIntVoid(Entry))
690 Result = *ResultOrErr;
691 else
692 errs() << "ERROR: " << ResultOrErr.getError().message() << "\n";
690693
691694 // Like static constructors, the remote target MCJIT support doesn't handle
692695 // this yet. It could. FIXME.
4343 class DummyRPC : public testing::Test,
4444 public RPC {
4545 public:
46 typedef Procedure<1, void(bool)> Proc1;
47 typedef Procedure<2, void(int8_t, uint8_t, int16_t, uint16_t,
48 int32_t, uint32_t, int64_t, uint64_t,
49 bool, std::string, std::vector)> AllTheTypes;
46 typedef Function<2, void(bool)> BasicVoid;
47 typedef Function<3, int32_t(bool)> BasicInt;
48 typedef Function<4, void(int8_t, uint8_t, int16_t, uint16_t,
49 int32_t, uint32_t, int64_t, uint64_t,
50 bool, std::string, std::vector)> AllTheTypes;
5051 };
5152
5253
53 TEST_F(DummyRPC, TestBasic) {
54 TEST_F(DummyRPC, TestAsyncBasicVoid) {
5455 std::queue Queue;
5556 QueueChannel C(Queue);
5657
57 {
58 // Make a call to Proc1.
59 auto EC = call(C, true);
60 EXPECT_FALSE(EC) << "Simple call over queue failed";
61 }
58 // Make an async call.
59 auto ResOrErr = callAsync(C, true);
60 EXPECT_TRUE(!!ResOrErr) << "Simple call over queue failed";
6261
6362 {
6463 // Expect a call to Proc1.
65 auto EC = expect<Proc1>(C,
64 auto EC = expect<BasicVoid>(C,
6665 [&](bool &B) {
6766 EXPECT_EQ(B, true)
6867 << "Bool serialization broken";
7069 });
7170 EXPECT_FALSE(EC) << "Simple expect over queue failed";
7271 }
72
73 {
74 // Wait for the result.
75 auto EC = waitForResult(C, ResOrErr->second, handleNone);
76 EXPECT_FALSE(EC) << "Could not read result.";
77 }
78
79 // Verify that the function returned ok.
80 auto Val = ResOrErr->first.get();
81 EXPECT_TRUE(Val) << "Remote void function failed to execute.";
82 }
83
84 TEST_F(DummyRPC, TestAsyncBasicInt) {
85 std::queue Queue;
86 QueueChannel C(Queue);
87
88 // Make an async call.
89 auto ResOrErr = callAsync(C, false);
90 EXPECT_TRUE(!!ResOrErr) << "Simple call over queue failed";
91
92 {
93 // Expect a call to Proc1.
94 auto EC = expect(C,
95 [&](bool &B) {
96 EXPECT_EQ(B, false)
97 << "Bool serialization broken";
98 return 42;
99 });
100 EXPECT_FALSE(EC) << "Simple expect over queue failed";
101 }
102
103 {
104 // Wait for the result.
105 auto EC = waitForResult(C, ResOrErr->second, handleNone);
106 EXPECT_FALSE(EC) << "Could not read result.";
107 }
108
109 // Verify that the function returned ok.
110 auto Val = ResOrErr->first.get();
111 EXPECT_TRUE(!!Val) << "Remote int function failed to execute.";
112 EXPECT_EQ(*Val, 42) << "Remote int function return wrong value.";
73113 }
74114
75115 TEST_F(DummyRPC, TestSerialization) {
76116 std::queue Queue;
77117 QueueChannel C(Queue);
78118
79 {
80 // Make a call to Proc1.
81 std::vector v({42, 7});
82 auto EC = call(C,
83 -101,
84 250,
85 -10000,
86 10000,
87 -1000000000,
88 1000000000,
89 -10000000000,
90 10000000000,
91 true,
92 "foo",
93 v);
94 EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed";
95 }
119 // Make a call to Proc1.
120 std::vector v({42, 7});
121 auto ResOrErr = callAsync(C,
122 -101,
123 250,
124 -10000,
125 10000,
126 -1000000000,
127 1000000000,
128 -10000000000,
129 10000000000,
130 true,
131 "foo",
132 v);
133 EXPECT_TRUE(!!ResOrErr)
134 << "Big (serialization test) call over queue failed";
96135
97136 {
98137 // Expect a call to Proc1.
135174 });
136175 EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed";
137176 }
177
178 {
179 // Wait for the result.
180 auto EC = waitForResult(C, ResOrErr->second, handleNone);
181 EXPECT_FALSE(EC) << "Could not read result.";
182 }
183
184 // Verify that the function returned ok.
185 auto Val = ResOrErr->first.get();
186 EXPECT_TRUE(Val) << "Remote void function failed to execute.";
138187 }