1 //===------- SimpleRemoteEPC.cpp -- Simple remote executor control --------===// 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 #include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h" 10 #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h" 11 #include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h" 12 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" 13 #include "llvm/Support/FormatVariadic.h" 14 15 #define DEBUG_TYPE "orc" 16 17 namespace llvm { 18 namespace orc { 19 20 SimpleRemoteEPC::~SimpleRemoteEPC() { 21 #ifndef NDEBUG 22 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 23 assert(Disconnected && "Destroyed without disconnection"); 24 #endif // NDEBUG 25 } 26 27 Expected<tpctypes::DylibHandle> 28 SimpleRemoteEPC::loadDylib(const char *DylibPath) { 29 return DylibMgr->open(DylibPath, 0); 30 } 31 32 Expected<std::vector<tpctypes::LookupResult>> 33 SimpleRemoteEPC::lookupSymbols(ArrayRef<LookupRequest> Request) { 34 std::vector<tpctypes::LookupResult> Result; 35 36 for (auto &Element : Request) { 37 if (auto R = DylibMgr->lookup(Element.Handle, Element.Symbols)) { 38 Result.push_back({}); 39 Result.back().reserve(R->size()); 40 for (auto Addr : *R) 41 Result.back().push_back(Addr.getValue()); 42 } else 43 return R.takeError(); 44 } 45 return std::move(Result); 46 } 47 48 Expected<int32_t> SimpleRemoteEPC::runAsMain(JITTargetAddress MainFnAddr, 49 ArrayRef<std::string> Args) { 50 int64_t Result = 0; 51 if (auto Err = callSPSWrapper<rt::SPSRunAsMainSignature>( 52 RunAsMainAddr.getValue(), Result, ExecutorAddr(MainFnAddr), Args)) 53 return std::move(Err); 54 return Result; 55 } 56 57 void SimpleRemoteEPC::callWrapperAsync(SendResultFunction OnComplete, 58 JITTargetAddress WrapperFnAddr, 59 ArrayRef<char> ArgBuffer) { 60 uint64_t SeqNo; 61 { 62 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 63 SeqNo = getNextSeqNo(); 64 assert(!PendingCallWrapperResults.count(SeqNo) && "SeqNo already in use"); 65 PendingCallWrapperResults[SeqNo] = std::move(OnComplete); 66 } 67 68 if (auto Err = T->sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo, 69 ExecutorAddr(WrapperFnAddr), ArgBuffer)) { 70 getExecutionSession().reportError(std::move(Err)); 71 } 72 } 73 74 Error SimpleRemoteEPC::disconnect() { 75 T->disconnect(); 76 std::unique_lock<std::mutex> Lock(SimpleRemoteEPCMutex); 77 DisconnectCV.wait(Lock, [this] { return Disconnected; }); 78 return std::move(DisconnectErr); 79 } 80 81 Expected<SimpleRemoteEPCTransportClient::HandleMessageAction> 82 SimpleRemoteEPC::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, 83 ExecutorAddr TagAddr, 84 SimpleRemoteEPCArgBytesVector ArgBytes) { 85 using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>; 86 if (static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC)) 87 return make_error<StringError>("Unexpected opcode", 88 inconvertibleErrorCode()); 89 90 switch (OpC) { 91 case SimpleRemoteEPCOpcode::Setup: 92 if (auto Err = handleSetup(SeqNo, TagAddr, std::move(ArgBytes))) 93 return std::move(Err); 94 break; 95 case SimpleRemoteEPCOpcode::Hangup: 96 // FIXME: Put EPC into 'detached' state. 97 return SimpleRemoteEPCTransportClient::EndSession; 98 case SimpleRemoteEPCOpcode::Result: 99 if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes))) 100 return std::move(Err); 101 break; 102 case SimpleRemoteEPCOpcode::CallWrapper: 103 handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes)); 104 break; 105 } 106 return ContinueSession; 107 } 108 109 void SimpleRemoteEPC::handleDisconnect(Error Err) { 110 PendingCallWrapperResultsMap TmpPending; 111 112 { 113 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 114 std::swap(TmpPending, PendingCallWrapperResults); 115 } 116 117 for (auto &KV : TmpPending) 118 KV.second( 119 shared::WrapperFunctionResult::createOutOfBandError("disconnecting")); 120 121 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 122 DisconnectErr = joinErrors(std::move(DisconnectErr), std::move(Err)); 123 Disconnected = true; 124 DisconnectCV.notify_all(); 125 } 126 127 Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>> 128 SimpleRemoteEPC::createMemoryManager() { 129 EPCGenericJITLinkMemoryManager::SymbolAddrs SAs; 130 if (auto Err = getBootstrapSymbols( 131 {{SAs.Allocator, rt::SimpleExecutorMemoryManagerInstanceName}, 132 {SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName}, 133 {SAs.Finalize, rt::SimpleExecutorMemoryManagerFinalizeWrapperName}, 134 {SAs.Deallocate, 135 rt::SimpleExecutorMemoryManagerDeallocateWrapperName}})) 136 return std::move(Err); 137 138 return std::make_unique<EPCGenericJITLinkMemoryManager>(*this, SAs); 139 } 140 141 Expected<std::unique_ptr<ExecutorProcessControl::MemoryAccess>> 142 SimpleRemoteEPC::createMemoryAccess() { 143 144 return nullptr; 145 } 146 147 Error SimpleRemoteEPC::handleSetup(uint64_t SeqNo, ExecutorAddr TagAddr, 148 SimpleRemoteEPCArgBytesVector ArgBytes) { 149 if (SeqNo != 0) 150 return make_error<StringError>("Setup packet SeqNo not zero", 151 inconvertibleErrorCode()); 152 153 if (TagAddr) 154 return make_error<StringError>("Setup packet TagAddr not zero", 155 inconvertibleErrorCode()); 156 157 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 158 auto I = PendingCallWrapperResults.find(0); 159 assert(PendingCallWrapperResults.size() == 1 && 160 I != PendingCallWrapperResults.end() && 161 "Setup message handler not connectly set up"); 162 auto SetupMsgHandler = std::move(I->second); 163 PendingCallWrapperResults.erase(I); 164 165 auto WFR = 166 shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size()); 167 SetupMsgHandler(std::move(WFR)); 168 return Error::success(); 169 } 170 171 void SimpleRemoteEPC::prepareToReceiveSetupMessage( 172 std::promise<MSVCPExpected<SimpleRemoteEPCExecutorInfo>> &ExecInfoP) { 173 PendingCallWrapperResults[0] = 174 [&](shared::WrapperFunctionResult SetupMsgBytes) { 175 if (const char *ErrMsg = SetupMsgBytes.getOutOfBandError()) { 176 ExecInfoP.set_value( 177 make_error<StringError>(ErrMsg, inconvertibleErrorCode())); 178 return; 179 } 180 using SPSSerialize = 181 shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>; 182 shared::SPSInputBuffer IB(SetupMsgBytes.data(), SetupMsgBytes.size()); 183 SimpleRemoteEPCExecutorInfo EI; 184 if (SPSSerialize::deserialize(IB, EI)) 185 ExecInfoP.set_value(EI); 186 else 187 ExecInfoP.set_value(make_error<StringError>( 188 "Could not deserialize setup message", inconvertibleErrorCode())); 189 }; 190 } 191 192 Error SimpleRemoteEPC::setup(std::unique_ptr<SimpleRemoteEPCTransport> T, 193 SimpleRemoteEPCExecutorInfo EI) { 194 using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames; 195 LLVM_DEBUG({ 196 dbgs() << "SimpleRemoteEPC received setup message:\n" 197 << " Triple: " << EI.TargetTriple << "\n" 198 << " Page size: " << EI.PageSize << "\n" 199 << " Bootstrap symbols:\n"; 200 for (const auto &KV : EI.BootstrapSymbols) 201 dbgs() << " " << KV.first() << ": " 202 << formatv("{0:x16}", KV.second.getValue()) << "\n"; 203 }); 204 this->T = std::move(T); 205 TargetTriple = Triple(EI.TargetTriple); 206 PageSize = EI.PageSize; 207 BootstrapSymbols = std::move(EI.BootstrapSymbols); 208 209 if (auto Err = getBootstrapSymbols( 210 {{JDI.JITDispatchContext, ExecutorSessionObjectName}, 211 {JDI.JITDispatchFunction, DispatchFnName}, 212 {RunAsMainAddr, rt::RunAsMainWrapperName}})) 213 return Err; 214 215 if (auto DM = 216 EPCGenericDylibManager::CreateWithDefaultBootstrapSymbols(*this)) 217 DylibMgr = std::make_unique<EPCGenericDylibManager>(std::move(*DM)); 218 else 219 return DM.takeError(); 220 221 if (auto MemMgr = createMemoryManager()) { 222 OwnedMemMgr = std::move(*MemMgr); 223 this->MemMgr = OwnedMemMgr.get(); 224 } else 225 return MemMgr.takeError(); 226 227 if (auto MemAccess = createMemoryAccess()) { 228 OwnedMemAccess = std::move(*MemAccess); 229 this->MemAccess = OwnedMemAccess.get(); 230 } else 231 return MemAccess.takeError(); 232 233 return Error::success(); 234 } 235 236 Error SimpleRemoteEPC::handleResult(uint64_t SeqNo, ExecutorAddr TagAddr, 237 SimpleRemoteEPCArgBytesVector ArgBytes) { 238 SendResultFunction SendResult; 239 240 if (TagAddr) 241 return make_error<StringError>("Unexpected TagAddr in result message", 242 inconvertibleErrorCode()); 243 244 { 245 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 246 auto I = PendingCallWrapperResults.find(SeqNo); 247 if (I == PendingCallWrapperResults.end()) 248 return make_error<StringError>("No call for sequence number " + 249 Twine(SeqNo), 250 inconvertibleErrorCode()); 251 SendResult = std::move(I->second); 252 PendingCallWrapperResults.erase(I); 253 releaseSeqNo(SeqNo); 254 } 255 256 auto WFR = 257 shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size()); 258 SendResult(std::move(WFR)); 259 return Error::success(); 260 } 261 262 void SimpleRemoteEPC::handleCallWrapper( 263 uint64_t RemoteSeqNo, ExecutorAddr TagAddr, 264 SimpleRemoteEPCArgBytesVector ArgBytes) { 265 assert(ES && "No ExecutionSession attached"); 266 ES->runJITDispatchHandler( 267 [this, RemoteSeqNo](shared::WrapperFunctionResult WFR) { 268 if (auto Err = 269 T->sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo, 270 ExecutorAddr(), {WFR.data(), WFR.size()})) 271 getExecutionSession().reportError(std::move(Err)); 272 }, 273 TagAddr.getValue(), ArgBytes); 274 } 275 276 } // end namespace orc 277 } // end namespace llvm 278