1 //===---- SimpleRemoteEPC.h - Simple remote executor control ----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Simple remote executor process control. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_EXECUTIONENGINE_ORC_SIMPLEREMOTEEPC_H 14 #define LLVM_EXECUTIONENGINE_ORC_SIMPLEREMOTEEPC_H 15 16 #include "llvm/ADT/DenseMap.h" 17 #include "llvm/ADT/FunctionExtras.h" 18 #include "llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h" 19 #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h" 20 #include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h" 21 #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" 22 #include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h" 23 #include "llvm/Support/Error.h" 24 #include "llvm/Support/MSVCErrorWorkarounds.h" 25 26 #include <future> 27 28 namespace llvm { 29 namespace orc { 30 31 class SimpleRemoteEPC : public ExecutorProcessControl, 32 public SimpleRemoteEPCTransportClient { 33 public: 34 /// A setup object containing callbacks to construct a memory manager and 35 /// memory access object. Both are optional. If not specified, 36 /// EPCGenericJITLinkMemoryManager and EPCGenericMemoryAccess will be used. 37 struct Setup { 38 using CreateMemoryManagerFn = 39 Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>( 40 SimpleRemoteEPC &); 41 using CreateMemoryAccessFn = 42 Expected<std::unique_ptr<MemoryAccess>>(SimpleRemoteEPC &); 43 44 unique_function<CreateMemoryManagerFn> CreateMemoryManager; 45 unique_function<CreateMemoryAccessFn> CreateMemoryAccess; 46 }; 47 48 /// Create a SimpleRemoteEPC using the given transport type and args. 49 template <typename TransportT, typename... TransportTCtorArgTs> 50 static Expected<std::unique_ptr<SimpleRemoteEPC>> Create(std::unique_ptr<TaskDispatcher> D,Setup S,TransportTCtorArgTs &&...TransportTCtorArgs)51 Create(std::unique_ptr<TaskDispatcher> D, Setup S, 52 TransportTCtorArgTs &&...TransportTCtorArgs) { 53 std::unique_ptr<SimpleRemoteEPC> SREPC( 54 new SimpleRemoteEPC(std::make_shared<SymbolStringPool>(), 55 std::move(D))); 56 auto T = TransportT::Create( 57 *SREPC, std::forward<TransportTCtorArgTs>(TransportTCtorArgs)...); 58 if (!T) 59 return T.takeError(); 60 SREPC->T = std::move(*T); 61 if (auto Err = SREPC->setup(std::move(S))) 62 return joinErrors(std::move(Err), SREPC->disconnect()); 63 return std::move(SREPC); 64 } 65 66 SimpleRemoteEPC(const SimpleRemoteEPC &) = delete; 67 SimpleRemoteEPC &operator=(const SimpleRemoteEPC &) = delete; 68 SimpleRemoteEPC(SimpleRemoteEPC &&) = delete; 69 SimpleRemoteEPC &operator=(SimpleRemoteEPC &&) = delete; 70 ~SimpleRemoteEPC(); 71 72 Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override; 73 74 void lookupSymbolsAsync(ArrayRef<LookupRequest> Request, 75 SymbolLookupCompleteFn F) override; 76 77 Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr, 78 ArrayRef<std::string> Args) override; 79 80 Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) override; 81 82 Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override; 83 84 void callWrapperAsync(ExecutorAddr WrapperFnAddr, 85 IncomingWFRHandler OnComplete, 86 ArrayRef<char> ArgBuffer) override; 87 88 Error disconnect() override; 89 90 Expected<HandleMessageAction> 91 handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr, 92 SimpleRemoteEPCArgBytesVector ArgBytes) override; 93 94 void handleDisconnect(Error Err) override; 95 96 private: SimpleRemoteEPC(std::shared_ptr<SymbolStringPool> SSP,std::unique_ptr<TaskDispatcher> D)97 SimpleRemoteEPC(std::shared_ptr<SymbolStringPool> SSP, 98 std::unique_ptr<TaskDispatcher> D) 99 : ExecutorProcessControl(std::move(SSP), std::move(D)) {} 100 101 static Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>> 102 createDefaultMemoryManager(SimpleRemoteEPC &SREPC); 103 static Expected<std::unique_ptr<MemoryAccess>> 104 createDefaultMemoryAccess(SimpleRemoteEPC &SREPC); 105 106 Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, 107 ExecutorAddr TagAddr, ArrayRef<char> ArgBytes); 108 109 Error handleSetup(uint64_t SeqNo, ExecutorAddr TagAddr, 110 SimpleRemoteEPCArgBytesVector ArgBytes); 111 Error setup(Setup S); 112 113 Error handleResult(uint64_t SeqNo, ExecutorAddr TagAddr, 114 SimpleRemoteEPCArgBytesVector ArgBytes); 115 void handleCallWrapper(uint64_t RemoteSeqNo, ExecutorAddr TagAddr, 116 SimpleRemoteEPCArgBytesVector ArgBytes); 117 Error handleHangup(SimpleRemoteEPCArgBytesVector ArgBytes); 118 getNextSeqNo()119 uint64_t getNextSeqNo() { return NextSeqNo++; } releaseSeqNo(uint64_t SeqNo)120 void releaseSeqNo(uint64_t SeqNo) {} 121 122 using PendingCallWrapperResultsMap = 123 DenseMap<uint64_t, IncomingWFRHandler>; 124 125 std::mutex SimpleRemoteEPCMutex; 126 std::condition_variable DisconnectCV; 127 bool Disconnected = false; 128 Error DisconnectErr = Error::success(); 129 130 std::unique_ptr<SimpleRemoteEPCTransport> T; 131 std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr; 132 std::unique_ptr<MemoryAccess> OwnedMemAccess; 133 134 std::unique_ptr<EPCGenericDylibManager> DylibMgr; 135 ExecutorAddr RunAsMainAddr; 136 ExecutorAddr RunAsVoidFunctionAddr; 137 ExecutorAddr RunAsIntFunctionAddr; 138 139 uint64_t NextSeqNo = 0; 140 PendingCallWrapperResultsMap PendingCallWrapperResults; 141 }; 142 143 } // end namespace orc 144 } // end namespace llvm 145 146 #endif // LLVM_EXECUTIONENGINE_ORC_SIMPLEREMOTEEPC_H 147