llvm.org GIT mirror llvm / 1806169
Revert 266581 (and follow-up 266588), it doesn't build on Windows. Three problems: 1. <future> can't be easily used. If you must use it, see include/Support/ThreadPool.h for how. 2. constexpr problems, even after 266588. 3. Move assignment operators can't be defaulted in MSVC2013. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266615 91177308-0d34-0410-b5e6-96231b3b80d8 Nico Weber 4 years ago
12 changed file(s) with 505 addition(s) and 922 deletion(s). Raw diff Collapse all Expand all
2525 RemoteMProtectAddrUnrecognized,
2626 RemoteIndirectStubsOwnerDoesNotExist,
2727 RemoteIndirectStubsOwnerIdAlreadyInUse,
28 UnexpectedRPCCall,
29 UnexpectedRPCResponse,
28 UnexpectedRPCCall
3029 };
3130
3231 std::error_code orcError(OrcErrorCode ErrCode);
3535 template
3636 class OrcRemoteTargetClient : public OrcRemoteTargetRPCAPI {
3737 public:
38
3938 /// Remote memory manager.
4039 class RCMemoryManager : public RuntimeDyld::MemoryManager {
4140 public:
105104 DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
106105
107106 if (CodeSize != 0) {
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
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;
115112 DEBUG(dbgs() << " code: "
116113 << format("0x%016x", Unmapped.back().RemoteCodeAddr)
117114 << " (" << CodeSize << " bytes, alignment " << CodeAlign
119116 }
120117
121118 if (RODataSize != 0) {
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
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;
129124 DEBUG(dbgs() << " ro-data: "
130125 << format("0x%016x", Unmapped.back().RemoteRODataAddr)
131126 << " (" << RODataSize << " bytes, alignment "
133128 }
134129
135130 if (RWDataSize != 0) {
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
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;
143136 DEBUG(dbgs() << " rw-data: "
144137 << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
145138 << " (" << RWDataSize << " bytes, alignment "
437430 TargetAddress PtrBase;
438431 unsigned NumStubsEmitted;
439432
440 if (auto StubInfoOrErr = Remote.emitIndirectStubs(Id, NewStubsRequired))
441 std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
442 else
443 return StubInfoOrErr.getError();
433 Remote.emitIndirectStubs(StubBase, PtrBase, NumStubsEmitted, Id,
434 NewStubsRequired);
444435
445436 unsigned NewBlockId = RemoteIndirectStubsInfos.size();
446437 RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted});
492483 void grow() override {
493484 TargetAddress BlockAddr = 0;
494485 uint32_t NumTrampolines = 0;
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 }
486 auto EC = Remote.emitTrampolineBlock(BlockAddr, NumTrampolines);
487 assert(!EC && "Failed to create trampolines");
501488
502489 uint32_t TrampolineSize = Remote.getTrampolineSize();
503490 for (unsigned I = 0; I < NumTrampolines; ++I)
515502 OrcRemoteTargetClient H(Channel, EC);
516503 if (EC)
517504 return EC;
518 return ErrorOr(std::move(H));
505 return H;
519506 }
520507
521508 /// Call the int(void) function at the given address in the target and return
522509 /// its result.
523 ErrorOr callIntVoid(TargetAddress Addr) {
510 std::error_code callIntVoid(int &Result, TargetAddress Addr) {
524511 DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n");
525512
526 auto Listen =
527 [&](RPCChannel &C, uint32_t Id) {
528 return listenForCompileRequests(C, Id);
529 };
530 return callSTHandling(Channel, Listen, Addr);
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 });
531528 }
532529
533530 /// Call the int(int, char*[]) function at the given address in the target and
534531 /// return its result.
535 ErrorOr callMain(TargetAddress Addr,
536 const std::vector &Args) {
532 std::error_code callMain(int &Result, TargetAddress Addr,
533 const std::vector &Args) {
537534 DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)
538535 << "\n");
539536
540 auto Listen =
541 [&](RPCChannel &C, uint32_t Id) {
542 return listenForCompileRequests(C, Id);
543 };
544 return callSTHandling(Channel, Listen, Addr, Args);
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 });
545552 }
546553
547554 /// Call the void() function at the given address in the target and wait for
550557 DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
551558 << "\n");
552559
553 auto Listen =
554 [&](RPCChannel &C, JITFuncId Id) {
555 return listenForCompileRequests(C, Id);
556 };
557 return callSTHandling(Channel, Listen, Addr);
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);
558571 }
559572
560573 /// Create an RCMemoryManager which will allocate its memory on the remote
564577 assert(!MM && "MemoryManager should be null before creation.");
565578
566579 auto Id = AllocatorIds.getNext();
567 if (auto EC = callST(Channel, Id))
580 if (auto EC = call(Channel, Id))
568581 return EC;
569582 MM = llvm::make_unique(*this, Id);
570583 return std::error_code();
576589 createIndirectStubsManager(std::unique_ptr &I) {
577590 assert(!I && "Indirect stubs manager should be null before creation.");
578591 auto Id = IndirectStubOwnerIds.getNext();
579 if (auto EC = callST(Channel, Id))
592 if (auto EC = call(Channel, Id))
580593 return EC;
581594 I = llvm::make_unique(*this, Id);
582595 return std::error_code();
585598 /// Search for symbols in the remote process. Note: This should be used by
586599 /// symbol resolvers *after* they've searched the local symbol table in the
587600 /// JIT stack.
588 ErrorOr getSymbolAddress(StringRef Name) {
601 std::error_code getSymbolAddress(TargetAddress &Addr, StringRef Name) {
589602 // Check for an 'out-of-band' error, e.g. from an MM destructor.
590603 if (ExistingError)
591604 return ExistingError;
592605
593 return callST(Channel, Name);
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 });
594616 }
595617
596618 /// Get the triple for the remote target.
597619 const std::string &getTargetTriple() const { return RemoteTargetTriple; }
598620
599 std::error_code terminateSession() {
600 return callST(Channel);
601 }
621 std::error_code terminateSession() { return call(Channel); }
602622
603623 private:
604624 OrcRemoteTargetClient(ChannelT &Channel, std::error_code &EC)
605625 : Channel(Channel) {
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();
626 if ((EC = call(Channel)))
627 return;
628
629 EC = expect(
630 Channel, readArgs(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
631 RemoteTrampolineSize, RemoteIndirectStubSize));
613632 }
614633
615634 std::error_code deregisterEHFrames(TargetAddress Addr, uint32_t Size) {
616 return callST(Channel, Addr, Size);
635 return call(Channel, Addr, Size);
617636 }
618637
619638 void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
620 if (auto EC = callST(Channel, Id)) {
639 if (auto EC = call(Channel, Id)) {
621640 // FIXME: This will be triggered by a removeModuleSet call: Propagate
622641 // error return up through that.
623642 llvm_unreachable("Failed to destroy remote allocator.");
627646
628647 std::error_code destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
629648 IndirectStubOwnerIds.release(Id);
630 return callST(Channel, Id);
631 }
632
633 ErrorOr>
634 emitIndirectStubs(ResourceIdMgr::ResourceId Id,
635 uint32_t NumStubsRequired) {
636 return callST(Channel, Id, NumStubsRequired);
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));
637662 }
638663
639664 std::error_code emitResolverBlock() {
641666 if (ExistingError)
642667 return ExistingError;
643668
644 return callST(Channel);
645 }
646
647 ErrorOr>
648 emitTrampolineBlock() {
669 return call(Channel);
670 }
671
672 std::error_code emitTrampolineBlock(TargetAddress &BlockAddr,
673 uint32_t &NumTrampolines) {
649674 // Check for an 'out-of-band' error, e.g. from an MM destructor.
650675 if (ExistingError)
651676 return ExistingError;
652677
653 return callST(Channel);
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 });
654687 }
655688
656689 uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
659692
660693 uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
661694
662 std::error_code listenForCompileRequests(RPCChannel &C, uint32_t &Id) {
695 std::error_code listenForCompileRequests(uint32_t &NextId) {
663696 // Check for an 'out-of-band' error, e.g. from an MM destructor.
664697 if (ExistingError)
665698 return ExistingError;
666699
667 if (Id == RequestCompileId) {
668 if (auto EC = handle(C, CompileCallback))
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)))
669706 return EC;
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) {
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) {
677720 // Check for an 'out-of-band' error, e.g. from an MM destructor.
678721 if (ExistingError)
679722 return ExistingError;
680723
681 return callST(Channel, Src, Size);
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();
682732 }
683733
684734 std::error_code registerEHFrames(TargetAddress &RAddr, uint32_t Size) {
685 return callST(Channel, RAddr, Size);
686 }
687
688 ErrorOr reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
689 uint32_t Align) {
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) {
690741
691742 // Check for an 'out-of-band' error, e.g. from an MM destructor.
692743 if (ExistingError)
693744 return ExistingError;
694745
695 return callST(Channel, Id, Size, Align);
746 if (std::error_code EC = call(Channel, Id, Size, Align))
747 return EC;
748
749 return expect(Channel, readArgs(RemoteAddr));
696750 }
697751
698752 std::error_code setProtections(ResourceIdMgr::ResourceId Id,
699753 TargetAddress RemoteSegAddr,
700754 unsigned ProtFlags) {
701 return callST(Channel, Id, RemoteSegAddr, ProtFlags);
755 return call(Channel, Id, RemoteSegAddr, ProtFlags);
702756 }
703757
704758 std::error_code writeMem(TargetAddress Addr, const char *Src, uint64_t Size) {
706760 if (ExistingError)
707761 return ExistingError;
708762
709 return callST(Channel, DirectBufferWriter(Src, Addr, Size));
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();
710772 }
711773
712774 std::error_code writePointer(TargetAddress Addr, TargetAddress PtrVal) {
714776 if (ExistingError)
715777 return ExistingError;
716778
717 return callST(Channel, Addr, PtrVal);
779 return call(Channel, Addr, PtrVal);
718780 }
719781
720782 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
6526 class OrcRemoteTargetRPCAPI : public RPC {
6627 protected:
67
6828 class ResourceIdMgr {
6929 public:
7030 typedef uint64_t ResourceId;
8444 };
8545
8646 public:
87 enum JITFuncId : uint32_t {
88 InvalidId = RPCFunctionIdTraits::InvalidId,
89 CallIntVoidId = RPCFunctionIdTraits::FirstValidId,
47 enum JITProcId : uint32_t {
48 InvalidId = 0,
49 CallIntVoidId,
50 CallIntVoidResponseId,
9051 CallMainId,
52 CallMainResponseId,
9153 CallVoidVoidId,
54 CallVoidVoidResponseId,
9255 CreateRemoteAllocatorId,
9356 CreateIndirectStubsOwnerId,
9457 DeregisterEHFramesId,
9558 DestroyRemoteAllocatorId,
9659 DestroyIndirectStubsOwnerId,
9760 EmitIndirectStubsId,
61 EmitIndirectStubsResponseId,
9862 EmitResolverBlockId,
9963 EmitTrampolineBlockId,
64 EmitTrampolineBlockResponseId,
10065 GetSymbolAddressId,
66 GetSymbolAddressResponseId,
10167 GetRemoteInfoId,
68 GetRemoteInfoResponseId,
10269 ReadMemId,
70 ReadMemResponseId,
10371 RegisterEHFramesId,
10472 ReserveMemId,
73 ReserveMemResponseId,
10574 RequestCompileId,
75 RequestCompileResponseId,
10676 SetProtectionsId,
10777 TerminateSessionId,
10878 WriteMemId,
10979 WritePtrId
11080 };
11181
112 static const char *getJITFuncIdName(JITFuncId Id);
82 static const char *getJITProcIdName(JITProcId Id);
11383
114 typedef Function(TargetAddress Addr)> CallIntVoid;
84 typedef Procedure(TargetAddress Addr)> CallIntVoid;
11585
116 typedef Function
117 std::vector Args)>
86 typedef Procedure)>
87 CallIntVoidResponse;
88
89 typedef Procedure
90 std::vector Args)>
11891 CallMain;
11992
120 typedef Function CallVoidVoid;
93 typedef Procedure CallMainResponse;
12194
122 typedef Function
123 void(ResourceIdMgr::ResourceId AllocatorID)>
95 typedef Procedure CallVoidVoid;
96
97 typedef Procedure CallVoidVoidResponse;
98
99 typedef Procedure
100 void(ResourceIdMgr::ResourceId AllocatorID)>
124101 CreateRemoteAllocator;
125102
126 typedef Function
127 void(ResourceIdMgr::ResourceId StubOwnerID)>
103 typedef Procedure
104 void(ResourceIdMgr::ResourceId StubOwnerID)>
128105 CreateIndirectStubsOwner;
129106
130 typedef Function
131 void(TargetAddress Addr, uint32_t Size)>
107 typedef Procedure
108 void(TargetAddress Addr, uint32_t Size)>
132109 DeregisterEHFrames;
133110
134 typedef Function
135 void(ResourceIdMgr::ResourceId AllocatorID)>
111 typedef Procedure
112 void(ResourceIdMgr::ResourceId AllocatorID)>
136113 DestroyRemoteAllocator;
137114
138 typedef Function
139 void(ResourceIdMgr::ResourceId StubsOwnerID)>
115 typedef Procedure
116 void(ResourceIdMgr::ResourceId StubsOwnerID)>
140117 DestroyIndirectStubsOwner;
141118
142 /// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted).
143 typedef Function
144 std::tuple(
145 ResourceIdMgr::ResourceId StubsOwnerID,
146 uint32_t NumStubsRequired)>
119 typedef Procedure
120 void(ResourceIdMgr::ResourceId StubsOwnerID,
121 uint32_t NumStubsRequired)>
147122 EmitIndirectStubs;
148123
149 typedef Function EmitResolverBlock;
124 typedef Procedure
125 void(TargetAddress StubsBaseAddr,
126 TargetAddress PtrsBaseAddr,
127 uint32_t NumStubsEmitted)>
128 EmitIndirectStubsResponse;
150129
151 /// EmitTrampolineBlock result is (BlockAddr, NumTrampolines).
152 typedef Function
153 std::tuple()> EmitTrampolineBlock;
130 typedef Procedure EmitResolverBlock;
154131
155 typedef Function
132 typedef Procedure EmitTrampolineBlock;
133
134 typedef Procedure
135 void(TargetAddress BlockAddr, uint32_t NumTrampolines)>
136 EmitTrampolineBlockResponse;
137
138 typedef Procedure
156139 GetSymbolAddress;
157140
158 /// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize,
159 /// IndirectStubsSize).
160 typedef Function
161 std::tuple
162 uint32_t>()> GetRemoteInfo;
141 typedef Procedure
142 GetSymbolAddressResponse;
163143
164 typedef Function
165 std::vector(TargetAddress Src, uint64_t Size)>
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
166153 ReadMem;
167154
168 typedef Function
169 void(TargetAddress Addr, uint32_t Size)>
155 typedef Procedure ReadMemResponse;
156
157 typedef Procedure
158 void(TargetAddress Addr, uint32_t Size)>
170159 RegisterEHFrames;
171160
172 typedef Function
173 TargetAddress(ResourceIdMgr::ResourceId AllocID,
174 uint64_t Size, uint32_t Align)>
161 typedef Procedure
162 void(ResourceIdMgr::ResourceId AllocID, uint64_t Size,
163 uint32_t Align)>
175164 ReserveMem;
176165
177 typedef Function
178 TargetAddress(TargetAddress TrampolineAddr)>
166 typedef ProcedureAddr)>
167 ReserveMemResponse;
168
169 typedef Procedure
179170 RequestCompile;
180171
181 typedef Function
182 void(ResourceIdMgr::ResourceId AllocID, TargetAddress Dst,
183 uint32_t ProtFlags)>
172 typedef Procedure)>
173 RequestCompileResponse;
174
175 typedef Procedure
176 void(ResourceIdMgr::ResourceId AllocID, TargetAddress Dst,
177 uint32_t ProtFlags)>
184178 SetProtections;
185179
186 typedef Function TerminateSession;
180 typedef Procedure TerminateSession;
187181
188 typedef Function
182 typedef Procedure
183 void(TargetAddress Dst, uint64_t Size /* Data to follow */)>
189184 WriteMem;
190185
191 typedef Function
186 typedef Procedure
192187 WritePtr;
193188 };
194189
4444 EHFramesRegister(std::move(EHFramesRegister)),
4545 EHFramesDeregister(std::move(EHFramesDeregister)) {}
4646
47 std::error_code getNextFuncId(JITFuncId &Id) {
47 std::error_code getNextProcId(JITProcId &Id) {
4848 return deserialize(Channel, Id);
4949 }
5050
51 std::error_code handleKnownFunction(JITFuncId Id) {
51 std::error_code handleKnownProcedure(JITProcId Id) {
5252 typedef OrcRemoteTargetServer ThisT;
5353
54 DEBUG(dbgs() << "Handling known proc: " << getJITFuncIdName(Id) << "\n");
54 DEBUG(dbgs() << "Handling known proc: " << getJITProcIdName(Id) << "\n");
5555
5656 switch (Id) {
5757 case CallIntVoidId:
110110 llvm_unreachable("Unhandled JIT RPC procedure Id.");
111111 }
112112
113 ErrorOr requestCompile(TargetAddress TrampolineAddr) {
114 auto Listen =
115 [&](RPCChannel &C, uint32_t Id) {
116 return handleKnownFunction(static_cast(Id));
117 };
118
119 return callSTHandling(Channel, Listen, TrampolineAddr);
120 }
121
122 void handleTerminateSession() {
123 handle(Channel, [](){ return std::error_code(); });
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.");
124134 }
125135
126136 private:
164174 static std::error_code doNothing() { return std::error_code(); }
165175
166176 static TargetAddress reenter(void *JITTargetAddr, void *TrampolineAddr) {
177 TargetAddress CompiledFnAddr = 0;
178
167179 auto T = static_cast(JITTargetAddr);
168 auto AddrOrErr = T->requestCompile(
169 static_cast(
170 reinterpret_cast(TrampolineAddr)));
171 // FIXME: Allow customizable failure substitution functions.
172 assert(AddrOrErr && "Compile request failed");
173 return *AddrOrErr;
174 }
175
176 ErrorOr handleCallIntVoid(TargetAddress Addr) {
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) {
177189 typedef int (*IntVoidFnTy)();
178190 IntVoidFnTy Fn =
179191 reinterpret_cast(static_cast(Addr));
182194 int Result = Fn();
183195 DEBUG(dbgs() << " Result = " << Result << "\n");
184196
185 return Result;
186 }
187
188 ErrorOr handleCallMain(TargetAddress Addr,
189 std::vector Args) {
197 return call(Channel, Result);
198 }
199
200 std::error_code handleCallMain(TargetAddress Addr,
201 std::vector Args) {
190202 typedef int (*MainFnTy)(int, const char *[]);
191203
192204 MainFnTy Fn = reinterpret_cast(static_cast(Addr));
201213 int Result = Fn(ArgC, ArgV.get());
202214 DEBUG(dbgs() << " Result = " << Result << "\n");
203215
204 return Result;
216 return call(Channel, Result);
205217 }
206218
207219 std::error_code handleCallVoidVoid(TargetAddress Addr) {
213225 Fn();
214226 DEBUG(dbgs() << " Complete.\n");
215227
216 return std::error_code();
228 return call(Channel);
217229 }
218230
219231 std::error_code handleCreateRemoteAllocator(ResourceIdMgr::ResourceId Id) {
260272 return std::error_code();
261273 }
262274
263 ErrorOr>
264 handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id,
265 uint32_t NumStubsRequired) {
275 std::error_code handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id,
276 uint32_t NumStubsRequired) {
266277 DEBUG(dbgs() << " ISMgr " << Id << " request " << NumStubsRequired
267278 << " stubs.\n");
268279
284295 auto &BlockList = StubOwnerItr->second;
285296 BlockList.push_back(std::move(IS));
286297
287 return std::make_tuple(StubsBase, PtrsBase, NumStubsEmitted);
298 return call(Channel, StubsBase, PtrsBase,
299 NumStubsEmitted);
288300 }
289301
290302 std::error_code handleEmitResolverBlock() {
303315 sys::Memory::MF_EXEC);
304316 }
305317
306 ErrorOr>
307 handleEmitTrampolineBlock() {
318 std::error_code handleEmitTrampolineBlock() {
308319 std::error_code EC;
309320 auto TrampolineBlock =
310321 sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
313324 if (EC)
314325 return EC;
315326
316 uint32_t NumTrampolines =
327 unsigned NumTrampolines =
317328 (sys::Process::getPageSize() - TargetT::PointerSize) /
318329 TargetT::TrampolineSize;
319330
327338
328339 TrampolineBlocks.push_back(std::move(TrampolineBlock));
329340
330 auto TrampolineBaseAddr =
331 static_cast(reinterpret_cast(TrampolineMem));
332
333 return std::make_tuple(TrampolineBaseAddr, NumTrampolines);
334 }
335
336 ErrorOr handleGetSymbolAddress(const std::string &Name) {
341 return call(
342 Channel,
343 static_cast(reinterpret_cast(TrampolineMem)),
344 NumTrampolines);
345 }
346
347 std::error_code handleGetSymbolAddress(const std::string &Name) {
337348 TargetAddress Addr = SymbolLookup(Name);
338349 DEBUG(dbgs() << " Symbol '" << Name << "' = " << format("0x%016x", Addr)
339350 << "\n");
340 return Addr;
341 }
342
343 ErrorOr>
344 handleGetRemoteInfo() {
351 return call(Channel, Addr);
352 }
353
354 std::error_code handleGetRemoteInfo() {
345355 std::string ProcessTriple = sys::getProcessTriple();
346356 uint32_t PointerSize = TargetT::PointerSize;
347357 uint32_t PageSize = sys::Process::getPageSize();
353363 << " page size = " << PageSize << "\n"
354364 << " trampoline size = " << TrampolineSize << "\n"
355365 << " indirect stub size = " << IndirectStubSize << "\n");
356 return std::make_tuple(ProcessTriple, PointerSize, PageSize ,TrampolineSize,
357 IndirectStubSize);
358 }
359
360 ErrorOr>
361 handleReadMem(TargetAddress RSrc, uint64_t Size) {
366 return call(Channel, ProcessTriple, PointerSize,
367 PageSize, TrampolineSize,
368 IndirectStubSize);
369 }
370
371 std::error_code handleReadMem(TargetAddress RSrc, uint64_t Size) {
362372 char *Src = reinterpret_cast(static_cast(RSrc));
363373
364374 DEBUG(dbgs() << " Reading " << Size << " bytes from "
365375 << format("0x%016x", RSrc) << "\n");
366376
367 std::vector Buffer;
368 Buffer.resize(Size);
369 for (char *P = Src; Size != 0; --Size)
370 Buffer.push_back(*P++);
371
372 return Buffer;
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();
373384 }
374385
375386 std::error_code handleRegisterEHFrames(TargetAddress TAddr, uint32_t Size) {
380391 return std::error_code();
381392 }
382393
383 ErrorOr
384 handleReserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
385 uint32_t Align) {
394 std::error_code handleReserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
395 uint32_t Align) {
386396 auto I = Allocators.find(Id);
387397 if (I == Allocators.end())
388398 return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
397407 TargetAddress AllocAddr =
398408 static_cast(reinterpret_cast(LocalAllocAddr));
399409
400 return AllocAddr;
410 return call(Channel, AllocAddr);
401411 }
402412
403413 std::error_code handleSetProtections(ResourceIdMgr::ResourceId Id,
414424 return Allocator.setProtections(LocalAddr, Flags);
415425 }
416426
417 std::error_code handleWriteMem(DirectBufferWriter DBW) {
418 DEBUG(dbgs() << " Writing " << DBW.getSize() << " bytes to "
419 << format("0x%016x", DBW.getDst()) << "\n");
420 return std::error_code();
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);
421432 }
422433
423434 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"
87 #include "llvm/Support/Endian.h"
98
10 #include
119 #include
1210
1311 namespace llvm {
2725
2826 /// Flush the stream if possible.
2927 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;
3928 };
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 }
6829
6930 /// RPC channel serialization for a variadic list of arguments.
7031 template
71 std::error_code serializeSeq(RPCChannel &C, const T &Arg, const Ts &... Args) {
32 std::error_code serialize_seq(RPCChannel &C, const T &Arg, const Ts &... Args) {
7233 if (auto EC = serialize(C, Arg))
7334 return EC;
74 return serializeSeq(C, Args...);
35 return serialize_seq(C, Args...);
7536 }
7637
7738 /// RPC channel serialization for an (empty) variadic list of arguments.
78 inline std::error_code serializeSeq(RPCChannel &C) {
39 inline std::error_code serialize_seq(RPCChannel &C) {
7940 return std::error_code();
8041 }
8142
8243 /// RPC channel deserialization for a variadic list of arguments.
8344 template
84 std::error_code deserializeSeq(RPCChannel &C, T &Arg, Ts &... Args) {
45 std::error_code deserialize_seq(RPCChannel &C, T &Arg, Ts &... Args) {
8546 if (auto EC = deserialize(C, Arg))
8647 return EC;
87 return deserializeSeq(C, Args...);
48 return deserialize_seq(C, Args...);
8849 }
8950
9051 /// RPC channel serialization for an (empty) variadic list of arguments.
91 inline std::error_code deserializeSeq(RPCChannel &C) {
52 inline std::error_code deserialize_seq(RPCChannel &C) {
9253 return std::error_code();
9354 }
9455
176137 return C.readBytes(&S[0], Count);
177138 }
178139
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
207140 /// RPC channel serialization for ArrayRef.
208141 template
209142 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"
1716 #include "llvm/ADT/STLExtras.h"
1817 #include "llvm/ExecutionEngine/Orc/OrcError.h"
19 #include "llvm/Support/ErrorOr.h"
20 #include
21 #include
2218
2319 namespace llvm {
2420 namespace orc {
2521 namespace remote {
26
27 /// Describes reserved RPC Function Ids.
28 ///
29 /// The default implementation will serve for integer and enum function id
30 /// types. If you want to use a custom type as your FunctionId you can
31 /// specialize this class and provide unique values for InvalidId,
32 /// ResponseId and FirstValidId.
33
34 template
35 class RPCFunctionIdTraits {
36 public:
37 static constexpr T InvalidId = static_cast(0);
38 static constexpr T ResponseId = static_cast(1);
39 static constexpr T FirstValidId = static_cast(2);
40 };
4122
4223 // Base class containing utilities that require partial specialization.
4324 // These cannot be included in RPC, as template class members cannot be
4425 // partially specialized.
4526 class RPCBase {
4627 protected:
47
48 // RPC Function description type.
49 //
50 // This class provides the information and operations needed to support the
51 // RPC primitive operations (call, expect, etc) for a given function. It
52 // is specialized for void and non-void functions to deal with the differences
53 // betwen the two. Both specializations have the same interface:
54 //
55 // Id - The function's unique identifier.
56 // OptionalReturn - The return type for asyncronous calls.
57 // ErrorReturn - The return type for synchronous calls.
58 // optionalToErrorReturn - Conversion from a valid OptionalReturn to an
59 // ErrorReturn.
60 // readResult - Deserialize a result from a channel.
61 // abandon - Abandon a promised (asynchronous) result.
62 // respond - Retun a result on the channel.
63 template
64 class FunctionHelper {};
65
66 // RPC Function description specialization for non-void functions.
67 template FunctionIdT, FunctionIdT FuncId, typename RetT,
28 template ProcedureIdT, ProcedureIdT ProcId, typename FnT>
29 class ProcedureHelper {
30 public:
31 static const ProcedureIdT Id = ProcId;
32 };
33
34 template class CallHelper;
35
36 template
6837 typename... ArgTs>
69 class FunctionHelper {
70 public:
71
72 static_assert(FuncId != RPCFunctionIdTraits::InvalidId &&
73 FuncId != RPCFunctionIdTraits::ResponseId,
74 "Cannot define custom function with InvalidId or ResponseId. "
75 "Please use RPCFunctionTraits::FirstValidId.");
76
77 static const FunctionIdT Id = FuncId;
78
79 typedef Optional OptionalReturn;
80
81 typedef ErrorOr ErrorReturn;
82
83 static ErrorReturn optionalToErrorReturn(OptionalReturn &&V) {
84 assert(V && "Return value not available");
85 return std::move(*V);
86 }
87
88 template
89 static std::error_code readResult(ChannelT &C,
90 std::promise &P) {
91 RetT Val;
92 auto EC = deserialize(C, Val);
93 // FIXME: Join error EC2 from endReceiveMessage with the deserialize
94 // error once we switch to using Error.
95 auto EC2 = endReceiveMessage(C);
96 (void)EC2;
97
98 if (EC) {
99 P.set_value(OptionalReturn());
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))
10043 return EC;
101 }
102 P.set_value(std::move(Val));
103 return std::error_code();
104 }
105
106 static void abandon(std::promise &P) {
107 P.set_value(OptionalReturn());
108 }
109
110 template
111 static std::error_code respond(ChannelT &C, SequenceNumberT SeqNo,
112 const ErrorReturn &Result) {
113 FunctionIdT ResponseId =
114 RPCFunctionIdTraits::ResponseId;
115
116 // If the handler returned an error then bail out with that.
117 if (!Result)
118 return Result.getError();
119
120 // Otherwise open a new message on the channel and send the result.
121 if (auto EC = startSendMessage(C))
122 return EC;
123 if (auto EC = serializeSeq(C, ResponseId, SeqNo, *Result))
124 return EC;
125 return endSendMessage(C);
126 }
127 };
128
129 // RPC Function description specialization for void functions.
130 template
131 class FunctionHelper {
132 public:
133
134 static_assert(FuncId != RPCFunctionIdTraits::InvalidId &&
135 FuncId != RPCFunctionIdTraits::ResponseId,
136 "Cannot define custom function with InvalidId or ResponseId. "
137 "Please use RPCFunctionTraits::FirstValidId.");
138
139 static const FunctionIdT Id = FuncId;
140
141 typedef bool OptionalReturn;
142 typedef std::error_code ErrorReturn;
143
144 static ErrorReturn optionalToErrorReturn(OptionalReturn &&V) {
145 assert(V && "Return value not available");
146 return std::error_code();
147 }
148
149 template
150 static std::error_code readResult(ChannelT &C,
151 std::promise &P) {
152 // Void functions don't have anything to deserialize, so we're good.
153 P.set_value(true);
154 return endReceiveMessage(C);
155 }
156
157 static void abandon(std::promise &P) {
158 P.set_value(false);
159 }
160
161 template
162 static std::error_code respond(ChannelT &C, SequenceNumberT SeqNo,
163 const ErrorReturn &Result) {
164 const FunctionIdT ResponseId =
165 RPCFunctionIdTraits::ResponseId;
166
167 // If the handler returned an error then bail out with that.
168 if (Result)
169 return Result;
170
171 // Otherwise open a new message on the channel and send the result.
172 if (auto EC = startSendMessage(C))
173 return EC;
174 if (auto EC = serializeSeq(C, ResponseId, SeqNo))
175 return EC;
176 return endSendMessage(C);
177 }
178 };
179
180 // Helper for the call primitive.
181 template
182 class CallHelper;
183
184 template
185 FunctionIdT FuncId, typename RetT, typename... ArgTs>
186 class CallHelper
187 FunctionHelper> {
188 public:
189 static std::error_code call(ChannelT &C, SequenceNumberT SeqNo,
190 const ArgTs &... Args) {
191 if (auto EC = startSendMessage(C))
192 return EC;
193 if (auto EC = serializeSeq(C, FuncId, SeqNo, Args...))
194 return EC;
195 return endSendMessage(C);
196 }
197 };
198
199 // Helper for handle primitive.
200 template
201 class HandlerHelper;
202
203 template
204 FunctionIdT FuncId, typename RetT, typename... ArgTs>
205 class HandlerHelper
206 FunctionHelper> {
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> {
20756 public:
20857 template
20958 static std::error_code handle(ChannelT &C, HandlerT Handler) {
21160 }
21261
21362 private:
214
215 typedef FunctionHelper Func;
216
21763 template
21864 static std::error_code readAndHandle(ChannelT &C, HandlerT Handler,
21965 llvm::index_sequence _) {
22066 std::tuple RPCArgs;
221 SequenceNumberT SeqNo;
22267 // GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning
22368 // for RPCArgs. Void cast RPCArgs to work around this for now.
22469 // FIXME: Remove this workaround once we can assume a working GCC version.
22570 (void)RPCArgs;
226 if (auto EC = deserializeSeq(C, SeqNo, std::get(RPCArgs)...))
71 if (auto EC = deserialize_seq(C, std::get(RPCArgs)...))
22772 return EC;
228
229 // We've deserialized the arguments, so unlock the channel for reading
230 // before we call the handler. This allows recursive RPC calls.
231 if (auto EC = endReceiveMessage(C))
232 return EC;
233
234 return Func::template respond(
235 C, SeqNo, Handler(std::get(RPCArgs)...));
236 }
237
238 };
239
240 // Helper for wrapping member functions up as functors.
241 template
242 class MemberFnWrapper {
243 public:
244 typedef RetT(ClassT::*MethodT)(ArgTs...);
73 return Handler(std::get(RPCArgs)...);
74 }
75 };
76
77 template class MemberFnWrapper {
78 public:
79 typedef std::error_code (ClassT::*MethodT)(ArgTs...);
24580 MemberFnWrapper(ClassT &Instance, MethodT Method)
24681 : Instance(Instance), Method(Method) {}
247 RetT operator()(ArgTs &... Args) { return (Instance.*Method)(Args...); }
82 std::error_code operator()(ArgTs &... Args) {
83 return (Instance.*Method)(Args...);
84 }
85
24886 private:
24987 ClassT &Instance;
25088 MethodT Method;
25189 };
25290
253 // Helper that provides a Functor for deserializing arguments.
25491 template class ReadArgs {
25592 public:
25693 std::error_code operator()() { return std::error_code(); }
274111
275112 /// Contains primitive utilities for defining, calling and handling calls to
276113 /// remote procedures. ChannelT is a bidirectional stream conforming to the
277 /// RPCChannel interface (see RPCChannel.h), and FunctionIdT is a procedure
114 /// RPCChannel interface (see RPCChannel.h), and ProcedureIdT is a procedure
278115 /// identifier type that must be serializable on ChannelT.
279116 ///
280117 /// These utilities support the construction of very primitive RPC utilities.
291128 ///
292129 /// Overview (see comments individual types/methods for details):
293130 ///
294 /// Function :
131 /// Procedure :
295132 ///
296133 /// associates a unique serializable id with an argument list.
297134 ///
298135 ///
299 /// call(Channel, Args...) :
300 ///
301 /// Calls the remote procedure 'Func' by serializing Func's id followed by its
136 /// call(Channel, Args...) :
137 ///
138 /// Calls the remote procedure 'Proc' by serializing Proc's id followed by its
302139 /// arguments and sending the resulting bytes to 'Channel'.
303140 ///
304141 ///
305 /// handle(Channel, :
306 ///
307 /// Handles a call to 'Func' by deserializing its arguments and calling the
308 /// given functor. This assumes that the id for 'Func' has already been
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
309146 /// deserialized.
310147 ///
311 /// expect<Func>(Channel, :
148 /// expect<Proc>(Channel, :
312149 ///
313150 /// The same as 'handle', except that the procedure id should not have been
314 /// read yet. Expect will deserialize the id and assert that it matches Func's
151 /// read yet. Expect will deserialize the id and assert that it matches Proc's
315152 /// id. If it does not, and unexpected RPC call error is returned.
316 template
317 typename SequenceNumberT = uint16_t>
153
154 template
318155 class RPC : public RPCBase {
319156 public:
320
321 RPC() = default;
322 RPC(const RPC&) = delete;
323 RPC& operator=(const RPC&) = delete;
324 RPC(RPC &&Other) : SequenceNumberMgr(std::move(Other.SequenceNumberMgr)), OutstandingResults(std::move(Other.OutstandingResults)) {}
325 RPC& operator=(RPC&&) = default;
326
327157 /// Utility class for defining/referring to RPC procedures.
328158 ///
329159 /// Typedefs of this utility are used when calling/handling remote procedures.
330160 ///
331 /// FuncId should be a unique value of FunctionIdT (i.e. not used with any
332 /// other Function typedef in the RPC API being defined.
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.
333163 ///
334164 /// the template argument Ts... gives the argument list for the remote
335165 /// procedure.
336166 ///
337167 /// E.g.
338168 ///
339 /// typedef Function<0, bool> Func1;
340 /// typedef Function<1, std::string, std::vector> Func2;
341 ///
342 /// if (auto EC = call(Channel, true))
169 /// typedef Procedure<0, bool> Proc1;
170 /// typedef Procedure<1, std::string, std::vector> Proc2;
171 ///
172 /// if (auto EC = call(Channel, true))
343173 /// /* handle EC */;
344174 ///
345 /// if (auto EC = expect<Func2>(Channel,
175 /// if (auto EC = expect<Proc2>(Channel,
346176 /// [](std::string &S, std::vector &V) {
347177 /// // Stuff.
348178 /// return std::error_code();
349179 /// })
350180 /// /* handle EC */;
351181 ///
352 template
353 using Function = FunctionHelper;
354
355 /// Return type for asynchronous call primitives.
356 template
357 using AsyncCallResult =
358 std::pair, SequenceNumberT>;
182 template
183 using Procedure = ProcedureHelper;
359184
360185 /// Serialize Args... to channel C, but do not call C.send().
361186 ///
362 /// For void functions returns a std::future. For functions that
363 /// return an R, returns a std::future>.
364 template
365 ErrorOr>
366 appendCallAsync(ChannelT &C, const ArgTs &... Args) {
367 auto SeqNo = SequenceNumberMgr.getSequenceNumber();
368 std::promise Promise;
369 auto Result = Promise.get_future();
370 OutstandingResults[SeqNo] = std::move(Promise);
371
372 if (auto EC =
373 CallHelper::call(C, SeqNo,
374 Args...)) {
375 abandonOutstandingResults();
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...);
192 }
193
194 /// 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...))
376198 return EC;
377 } else
378 return AsyncCallResult(std::move(Result), SeqNo);
379 }
380
381 /// Serialize Args... to channel C and call C.send().
382 template
383 ErrorOr>
384 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 =
391 CallHelper::call(C, SeqNo, Args...)) {
392 abandonOutstandingResults();
393 return EC;
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
418 callST(ChannelT &C, const ArgTs &... Args) {
419 return callSTHandling(C, handleNone, Args...);
420 }
421
422 /// Start receiving a new function call.
423 ///
424 /// Calls startReceiveMessage on the channel, then deserializes a FunctionId
425 /// into Id.
426 std::error_code startReceivingFunction(ChannelT &C, FunctionIdT &Id) {
427 if (auto EC = startReceiveMessage(C))
428 return EC;
429
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) {
430204 return deserialize(C, Id);
431205 }
432206
433 /// Deserialize args for Func from C and call Handler. The signature of
207 /// Deserialize args for Proc from C and call Handler. The signature of
434208 /// handler must conform to 'std::error_code(Args...)' where Args... matches
435 /// the arguments used in the Func typedef.
436 template
209 /// the arguments used in the Proc typedef.
210 template
437211 static std::error_code handle(ChannelT &C, HandlerT Handler) {
438 return HandlerHelperSequenceNumberT, Func>::handle(C, Handler);
212 return HandlerHelperProc>::handle(C, Handler);
439213 }
440214
441215 /// Helper version of 'handle' for calling member functions.
442 template Func, typename ClassT, typename RetT, typename... ArgTs>
216 template Proc, typename ClassT, typename... ArgTs>
443217 static std::error_code
444218 handle(ChannelT &C, ClassT &Instance,
445 RetT (ClassT::*HandlerMethod)(ArgTs...)) {
446 return handle(
447 C,
448 MemberFnWrapper(Instance, HandlerMethod));
449 }
450
451 /// Deserialize a FunctionIdT from C and verify it matches the id for Func.
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.
452225 /// If the id does match, deserialize the arguments and call the handler
453226 /// (similarly to handle).
454227 /// If the id does not match, return an unexpect RPC call error and do not
455228 /// deserialize any further bytes.
456 template
457 std::error_code expect(ChannelT &C, HandlerT Handler) {
458 FunctionIdT FuncId;
459 if (auto EC = startReceivingFunction(C, FuncId))
460 return std::move(EC);
461 if (FuncId != Func::Id)
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)
462235 return orcError(OrcErrorCode::UnexpectedRPCCall);
463 return handle<Func>(C, Handler);
236 return handle<Proc>(C, Handler);
464237 }
465238
466239 /// Helper version of expect for calling member functions.
467 template Func, typename ClassT, typename... ArgTs>
240 template Proc, typename ClassT, typename... ArgTs>
468241 static std::error_code
469242 expect(ChannelT &C, ClassT &Instance,
470243 std::error_code (ClassT::*HandlerMethod)(ArgTs...)) {
471 return expect<Func>(
244 return expect<Proc>(
472245 C, MemberFnWrapper(Instance, HandlerMethod));
473246 }
474247
477250 /// channel.
478251 /// E.g.
479252 ///
480 /// typedef Function<0, bool, int> Func1;
253 /// typedef Procedure<0, bool, int> Proc1;
481254 ///
482255 /// ...
483256 /// bool B;
484257 /// int I;
485 /// if (auto EC = expect<Func1>(Channel, readArgs(B, I)))
258 /// if (auto EC = expect<Proc1>(Channel, readArgs(B, I)))
486259 /// /* Handle Args */ ;
487260 ///
488261 template
489262 static ReadArgs readArgs(ArgTs &... Args) {
490263 return ReadArgs(Args...);
491264 }
492
493 /// Read a response from Channel.
494 /// This should be called from the receive loop to retrieve results.
495 std::error_code handleResponse(ChannelT &C, SequenceNumberT &SeqNo) {
496 if (auto EC = deserialize(C, SeqNo)) {
497 abandonOutstandingResults();
498 return EC;
499 }
500
501 auto I = OutstandingResults.find(SeqNo);
502 if (I == OutstandingResults.end()) {
503 abandonOutstandingResults();
504 return orcError(OrcErrorCode::UnexpectedRPCResponse);
505 }
506
507 if (auto EC = I->second->readResult(C)) {
508 abandonOutstandingResults();
509 // FIXME: Release sequence numbers?
510 return EC;
511 }
512
513 OutstandingResults.erase(I);
514 SequenceNumberMgr.releaseSequenceNumber(SeqNo);
515
516 return std::error_code();
517 }
518
519 // Loop waiting for a result with the given sequence number.
520 // This can be used as a receive loop if the user doesn't have a default.
521 template
522 std::error_code waitForResult(ChannelT &C, SequenceNumberT TgtSeqNo,
523 HandleOtherFtor &HandleOther = handleNone) {
524 bool GotTgtResult = false;
525
526 while (!GotTgtResult) {
527 FunctionIdT Id =
528 RPCFunctionIdTraits::InvalidId;
529 if (auto EC = startReceivingFunction(C, Id))
530 return EC;
531 if (Id == RPCFunctionIdTraits::ResponseId) {
532 SequenceNumberT SeqNo;
533 if (auto EC = handleResponse(C, SeqNo))
534 return EC;
535 GotTgtResult = (SeqNo == TgtSeqNo);
536 } else if (auto EC = HandleOther(C, Id))
537 return EC;
538 }
539
540 return std::error_code();
541 }
542
543 // Default handler for 'other' (non-response) functions when waiting for a
544 // result from the channel.
545 static std::error_code handleNone(ChannelT&, FunctionIdT) {
546 return orcError(OrcErrorCode::UnexpectedRPCCall);
547 };
548
549 private:
550
551 // Manage sequence numbers.
552 class SequenceNumberManager {
553 public:
554
555 SequenceNumberManager() = default;
556
557 SequenceNumberManager(SequenceNumberManager &&Other)
558 : NextSequenceNumber(std::move(Other.NextSequenceNumber)),
559 FreeSequenceNumbers(std::move(Other.FreeSequenceNumbers)) {}
560
561 SequenceNumberManager& operator=(SequenceNumberManager &&Other) {
562 NextSequenceNumber = std::move(Other.NextSequenceNumber);
563 FreeSequenceNumbers = std::move(Other.FreeSequenceNumbers);
564 }
565
566 void reset() {
567 std::lock_guard Lock(SeqNoLock);
568 NextSequenceNumber = 0;
569 FreeSequenceNumbers.clear();
570 }
571
572 SequenceNumberT getSequenceNumber() {
573 std::lock_guard Lock(SeqNoLock);
574 if (FreeSequenceNumbers.empty())
575 return NextSequenceNumber++;
576 auto SequenceNumber = FreeSequenceNumbers.back();
577 FreeSequenceNumbers.pop_back();
578 return SequenceNumber;
579 }
580
581 void releaseSequenceNumber(SequenceNumberT SequenceNumber) {
582 std::lock_guard Lock(SeqNoLock);
583 FreeSequenceNumbers.push_back(SequenceNumber);
584 }
585
586 private:
587 std::mutex SeqNoLock;
588 SequenceNumberT NextSequenceNumber = 0;
589 std::vector FreeSequenceNumbers;
590 };
591
592 // Base class for results that haven't been returned from the other end of the
593 // RPC connection yet.
594 class OutstandingResult {
595 public:
596 virtual ~OutstandingResult() {}
597 virtual std::error_code readResult(ChannelT &C) = 0;
598 virtual void abandon() = 0;
599 };
600
601 // Outstanding results for a specific function.
602 template
603 class OutstandingResultImpl : public OutstandingResult {
604 private:
605 public:
606 OutstandingResultImpl(std::promise &&P)
607 : P(std::move(P)) {}
608
609 std::error_code readResult(ChannelT &C) override {
610 return Func::readResult(C, P);
611 }
612
613 void abandon() override { Func::abandon(P); }
614
615 private:
616 std::promise P;
617 };
618
619 // Create an outstanding result for the given function.
620 template
621 std::unique_ptr
622 createOutstandingResult(std::promise &&P) {
623 return llvm::make_unique>(std::move(P));
624 }
625
626 // Abandon all outstanding results.
627 void abandonOutstandingResults() {
628 for (auto &KV : OutstandingResults)
629 KV.second->abandon();
630 OutstandingResults.clear();
631 SequenceNumberMgr.reset();
632 }
633
634 SequenceNumberManager SequenceNumberMgr;
635 std::map>
636 OutstandingResults;
637265 };
638266
639267 } // 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";
4240 }
4341 llvm_unreachable("Unhandled error code");
4442 }
1212 namespace orc {
1313 namespace remote {
1414
15 #define FUNCNAME(X) \
15 #define PROCNAME(X) \
1616 case X ## Id: \
1717 return #X
1818
19 const char *OrcRemoteTargetRPCAPI::getJITFuncIdName(JITFuncId Id) {
19 const char *OrcRemoteTargetRPCAPI::getJITProcIdName(JITProcId Id) {
2020 switch (Id) {
2121 case InvalidId:
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);
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);
4454 };
4555 return nullptr;
4656 }
4757
48 #undef FUNCNAME
58 #undef PROCNAME
4959
5060 } // end namespace remote
5161 } // end namespace orc
5353 JITServer Server(Channel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames);
5454
5555 while (1) {
56 JITServer::JITFuncId Id = JITServer::InvalidId;
57 if (auto EC = Server.getNextFuncId(Id)) {
56 JITServer::JITProcId Id = JITServer::InvalidId;
57 if (auto EC = Server.getNextProcId(Id)) {
5858 errs() << "Error: " << EC.message() << "\n";
5959 return 1;
6060 }
6262 case JITServer::TerminateSessionId:
6363 return 0;
6464 default:
65 if (auto EC = Server.handleKnownFunction(Id)) {
65 if (auto EC = Server.handleKnownProcedure(Id)) {
6666 errs() << "Error: " << EC.message() << "\n";
6767 return 1;
6868 }
1515
1616 #include "llvm/ExecutionEngine/Orc/RPCChannel.h"
1717 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
18 #include
1918
2019 #if !defined(_MSC_VER) && !defined(__MINGW32__)
2120 #include
581581 // Reset errno to zero on entry to main.
582582 errno = 0;
583583
584 int Result = -1;
584 int Result;
585585
586586 // Sanity check use of remote-jit: LLI currently only supports use of the
587587 // remote JIT on Unix platforms.
680680 static_cast(RTDyldMM)->setResolver(
681681 orc::createLambdaResolver(
682682 [&](const std::string &Name) {
683 if (auto AddrOrErr = R->getSymbolAddress(Name))
684 return RuntimeDyld::SymbolInfo(*AddrOrErr, JITSymbolFlags::Exported);
685 else {
686 errs() << "Failure during symbol lookup: "
687 << AddrOrErr.getError().message() << "\n";
688 exit(1);
689 }
683 orc::TargetAddress Addr = 0;
684 if (auto EC = R->getSymbolAddress(Addr, Name)) {
685 errs() << "Failure during symbol lookup: " << EC.message() << "\n";
686 exit(1);
687 }
688 return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported);
690689 },
691690 [](const std::string &Name) { return nullptr; }
692691 ));
698697 EE->finalizeObject();
699698 DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
700699 << format("%llx", Entry) << "\n");
701 if (auto ResultOrErr = R->callIntVoid(Entry))
702 Result = *ResultOrErr;
703 else
704 errs() << "ERROR: " << ResultOrErr.getError().message() << "\n";
700 if (auto EC = R->callIntVoid(Result, Entry))
701 errs() << "ERROR: " << EC.message() << "\n";
705702
706703 // Like static constructors, the remote target MCJIT support doesn't handle
707704 // this yet. It could. FIXME.
4343 class DummyRPC : public testing::Test,
4444 public RPC {
4545 public:
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;
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;
5150 };
5251
5352
54 TEST_F(DummyRPC, TestAsyncBasicVoid) {
53 TEST_F(DummyRPC, TestBasic) {
5554 std::queue Queue;
5655 QueueChannel C(Queue);
5756
58 // Make an async call.
59 auto ResOrErr = callAsync(C, true);
60 EXPECT_TRUE(!!ResOrErr) << "Simple call over queue failed";
57 {
58 // Make a call to Proc1.
59 auto EC = call(C, true);
60 EXPECT_FALSE(EC) << "Simple call over queue failed";
61 }
6162
6263 {
6364 // Expect a call to Proc1.
64 auto EC = expect<BasicVoid>(C,
65 auto EC = expect<Proc1>(C,
6566 [&](bool &B) {
6667 EXPECT_EQ(B, true)
6768 << "Bool serialization broken";
6970 });
7071 EXPECT_FALSE(EC) << "Simple expect over queue failed";
7172 }
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.";
11373 }
11474
11575 TEST_F(DummyRPC, TestSerialization) {
11676 std::queue Queue;
11777 QueueChannel C(Queue);
11878
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";
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 }
13596
13697 {
13798 // Expect a call to Proc1.
174135 });
175136 EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed";
176137 }
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.";
187138 }