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 private DylibManager { 34 public: 35 /// A setup object containing callbacks to construct a memory manager and 36 /// memory access object. Both are optional. If not specified, 37 /// EPCGenericJITLinkMemoryManager and EPCGenericMemoryAccess will be used. 38 struct Setup { 39 using CreateMemoryManagerFn = 40 Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>( 41 SimpleRemoteEPC &); 42 using CreateMemoryAccessFn = 43 Expected<std::unique_ptr<MemoryAccess>>(SimpleRemoteEPC &); 44 45 unique_function<CreateMemoryManagerFn> CreateMemoryManager; 46 unique_function<CreateMemoryAccessFn> CreateMemoryAccess; 47 }; 48 49 /// Create a SimpleRemoteEPC using the given transport type and args. 50 template <typename TransportT, typename... TransportTCtorArgTs> 51 static Expected<std::unique_ptr<SimpleRemoteEPC>> 52 Create(std::unique_ptr<TaskDispatcher> D, Setup S, 53 TransportTCtorArgTs &&...TransportTCtorArgs) { 54 std::unique_ptr<SimpleRemoteEPC> SREPC( 55 new SimpleRemoteEPC(std::make_shared<SymbolStringPool>(), 56 std::move(D))); 57 auto T = TransportT::Create( 58 *SREPC, std::forward<TransportTCtorArgTs>(TransportTCtorArgs)...); 59 if (!T) 60 return T.takeError(); 61 SREPC->T = std::move(*T); 62 if (auto Err = SREPC->setup(std::move(S))) 63 return joinErrors(std::move(Err), SREPC->disconnect()); 64 return std::move(SREPC); 65 } 66 67 SimpleRemoteEPC(const SimpleRemoteEPC &) = delete; 68 SimpleRemoteEPC &operator=(const SimpleRemoteEPC &) = delete; 69 SimpleRemoteEPC(SimpleRemoteEPC &&) = delete; 70 SimpleRemoteEPC &operator=(SimpleRemoteEPC &&) = delete; 71 ~SimpleRemoteEPC(); 72 73 Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr, 74 ArrayRef<std::string> Args) override; 75 76 Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) override; 77 78 Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override; 79 80 void callWrapperAsync(ExecutorAddr WrapperFnAddr, 81 IncomingWFRHandler OnComplete, 82 ArrayRef<char> ArgBuffer) override; 83 84 Error disconnect() override; 85 86 Expected<HandleMessageAction> 87 handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr, 88 SimpleRemoteEPCArgBytesVector ArgBytes) override; 89 90 void handleDisconnect(Error Err) override; 91 92 private: 93 SimpleRemoteEPC(std::shared_ptr<SymbolStringPool> SSP, 94 std::unique_ptr<TaskDispatcher> D) 95 : ExecutorProcessControl(std::move(SSP), std::move(D)) { 96 this->DylibMgr = this; 97 } 98 99 static Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>> 100 createDefaultMemoryManager(SimpleRemoteEPC &SREPC); 101 static Expected<std::unique_ptr<MemoryAccess>> 102 createDefaultMemoryAccess(SimpleRemoteEPC &SREPC); 103 104 Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, 105 ExecutorAddr TagAddr, ArrayRef<char> ArgBytes); 106 107 Error handleSetup(uint64_t SeqNo, ExecutorAddr TagAddr, 108 SimpleRemoteEPCArgBytesVector ArgBytes); 109 Error setup(Setup S); 110 111 Error handleResult(uint64_t SeqNo, ExecutorAddr TagAddr, 112 SimpleRemoteEPCArgBytesVector ArgBytes); 113 void handleCallWrapper(uint64_t RemoteSeqNo, ExecutorAddr TagAddr, 114 SimpleRemoteEPCArgBytesVector ArgBytes); 115 Error handleHangup(SimpleRemoteEPCArgBytesVector ArgBytes); 116 117 uint64_t getNextSeqNo() { return NextSeqNo++; } 118 void releaseSeqNo(uint64_t SeqNo) {} 119 120 Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override; 121 122 void lookupSymbolsAsync(ArrayRef<LookupRequest> Request, 123 SymbolLookupCompleteFn F) override; 124 125 using PendingCallWrapperResultsMap = 126 DenseMap<uint64_t, IncomingWFRHandler>; 127 128 std::mutex SimpleRemoteEPCMutex; 129 std::condition_variable DisconnectCV; 130 bool Disconnected = false; 131 Error DisconnectErr = Error::success(); 132 133 std::unique_ptr<SimpleRemoteEPCTransport> T; 134 std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr; 135 std::unique_ptr<MemoryAccess> OwnedMemAccess; 136 137 std::unique_ptr<EPCGenericDylibManager> EPCDylibMgr; 138 ExecutorAddr RunAsMainAddr; 139 ExecutorAddr RunAsVoidFunctionAddr; 140 ExecutorAddr RunAsIntFunctionAddr; 141 142 uint64_t NextSeqNo = 0; 143 PendingCallWrapperResultsMap PendingCallWrapperResults; 144 }; 145 146 } // end namespace orc 147 } // end namespace llvm 148 149 #endif // LLVM_EXECUTIONENGINE_ORC_SIMPLEREMOTEEPC_H 150