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