1*bb72f073SLang Hames //===------- SimpleRemoteEPC.cpp -- Simple remote executor control --------===// 2*bb72f073SLang Hames // 3*bb72f073SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*bb72f073SLang Hames // See https://llvm.org/LICENSE.txt for license information. 5*bb72f073SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*bb72f073SLang Hames // 7*bb72f073SLang Hames //===----------------------------------------------------------------------===// 8*bb72f073SLang Hames 9*bb72f073SLang Hames #include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h" 10*bb72f073SLang Hames #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h" 11*bb72f073SLang Hames #include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h" 12*bb72f073SLang Hames #include "llvm/Support/FormatVariadic.h" 13*bb72f073SLang Hames 14*bb72f073SLang Hames #define DEBUG_TYPE "orc" 15*bb72f073SLang Hames 16*bb72f073SLang Hames namespace llvm { 17*bb72f073SLang Hames namespace orc { 18*bb72f073SLang Hames namespace shared { 19*bb72f073SLang Hames 20*bb72f073SLang Hames template <> 21*bb72f073SLang Hames class SPSSerializationTraits<SPSRemoteSymbolLookupSetElement, 22*bb72f073SLang Hames SymbolLookupSet::value_type> { 23*bb72f073SLang Hames public: 24*bb72f073SLang Hames static size_t size(const SymbolLookupSet::value_type &V) { 25*bb72f073SLang Hames return SPSArgList<SPSString, bool>::size( 26*bb72f073SLang Hames *V.first, V.second == SymbolLookupFlags::RequiredSymbol); 27*bb72f073SLang Hames } 28*bb72f073SLang Hames 29*bb72f073SLang Hames static bool serialize(SPSOutputBuffer &OB, 30*bb72f073SLang Hames const SymbolLookupSet::value_type &V) { 31*bb72f073SLang Hames return SPSArgList<SPSString, bool>::serialize( 32*bb72f073SLang Hames OB, *V.first, V.second == SymbolLookupFlags::RequiredSymbol); 33*bb72f073SLang Hames } 34*bb72f073SLang Hames }; 35*bb72f073SLang Hames 36*bb72f073SLang Hames template <> 37*bb72f073SLang Hames class TrivialSPSSequenceSerialization<SPSRemoteSymbolLookupSetElement, 38*bb72f073SLang Hames SymbolLookupSet> { 39*bb72f073SLang Hames public: 40*bb72f073SLang Hames static constexpr bool available = true; 41*bb72f073SLang Hames }; 42*bb72f073SLang Hames 43*bb72f073SLang Hames template <> 44*bb72f073SLang Hames class SPSSerializationTraits<SPSRemoteSymbolLookup, 45*bb72f073SLang Hames ExecutorProcessControl::LookupRequest> { 46*bb72f073SLang Hames using MemberSerialization = 47*bb72f073SLang Hames SPSArgList<SPSExecutorAddress, SPSRemoteSymbolLookupSet>; 48*bb72f073SLang Hames 49*bb72f073SLang Hames public: 50*bb72f073SLang Hames static size_t size(const ExecutorProcessControl::LookupRequest &LR) { 51*bb72f073SLang Hames return MemberSerialization::size(ExecutorAddress(LR.Handle), LR.Symbols); 52*bb72f073SLang Hames } 53*bb72f073SLang Hames 54*bb72f073SLang Hames static bool serialize(SPSOutputBuffer &OB, 55*bb72f073SLang Hames const ExecutorProcessControl::LookupRequest &LR) { 56*bb72f073SLang Hames return MemberSerialization::serialize(OB, ExecutorAddress(LR.Handle), 57*bb72f073SLang Hames LR.Symbols); 58*bb72f073SLang Hames } 59*bb72f073SLang Hames }; 60*bb72f073SLang Hames 61*bb72f073SLang Hames } // end namespace shared 62*bb72f073SLang Hames 63*bb72f073SLang Hames SimpleRemoteEPC::~SimpleRemoteEPC() { 64*bb72f073SLang Hames assert(Disconnected && "Destroyed without disconnection"); 65*bb72f073SLang Hames } 66*bb72f073SLang Hames 67*bb72f073SLang Hames Error SimpleRemoteEPC::setup(std::unique_ptr<SimpleRemoteEPCTransport> T, 68*bb72f073SLang Hames const SimpleRemoteEPCExecutorInfo &EI) { 69*bb72f073SLang Hames using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames; 70*bb72f073SLang Hames LLVM_DEBUG({ 71*bb72f073SLang Hames dbgs() << "SimpleRemoteEPC received setup message:\n" 72*bb72f073SLang Hames << " Triple: " << EI.TargetTriple << "\n" 73*bb72f073SLang Hames << " Page size: " << EI.PageSize << "\n" 74*bb72f073SLang Hames << " Bootstrap symbols:\n"; 75*bb72f073SLang Hames for (const auto &KV : EI.BootstrapSymbols) 76*bb72f073SLang Hames dbgs() << " " << KV.first() << ": " 77*bb72f073SLang Hames << formatv("{0:x16}", KV.second.getValue()) << "\n"; 78*bb72f073SLang Hames }); 79*bb72f073SLang Hames this->T = std::move(T); 80*bb72f073SLang Hames TargetTriple = Triple(EI.TargetTriple); 81*bb72f073SLang Hames PageSize = EI.PageSize; 82*bb72f073SLang Hames 83*bb72f073SLang Hames if (auto Err = EI.getBootstrapSymbols( 84*bb72f073SLang Hames {{JDI.JITDispatchContextAddress, ExecutorSessionObjectName}, 85*bb72f073SLang Hames {JDI.JITDispatchFunctionAddress, DispatchFnName}, 86*bb72f073SLang Hames {LoadDylibAddr, "__llvm_orc_load_dylib"}, 87*bb72f073SLang Hames {LookupSymbolsAddr, "__llvm_orc_lookup_symbols"}, 88*bb72f073SLang Hames {RunAsMainAddr, "__llvm_orc_run_as_main"}})) 89*bb72f073SLang Hames return Err; 90*bb72f073SLang Hames 91*bb72f073SLang Hames if (!MemMgr) 92*bb72f073SLang Hames if (auto Err = setupDefaultMemoryManager(EI)) 93*bb72f073SLang Hames return Err; 94*bb72f073SLang Hames if (!MemAccess) 95*bb72f073SLang Hames if (auto Err = setupDefaultMemoryAccess(EI)) 96*bb72f073SLang Hames return Err; 97*bb72f073SLang Hames 98*bb72f073SLang Hames return Error::success(); 99*bb72f073SLang Hames } 100*bb72f073SLang Hames 101*bb72f073SLang Hames Expected<tpctypes::DylibHandle> 102*bb72f073SLang Hames SimpleRemoteEPC::loadDylib(const char *DylibPath) { 103*bb72f073SLang Hames Expected<tpctypes::DylibHandle> H((tpctypes::DylibHandle())); 104*bb72f073SLang Hames if (auto Err = callSPSWrapper<shared::SPSLoadDylibSignature>( 105*bb72f073SLang Hames LoadDylibAddr.getValue(), H, JDI.JITDispatchContextAddress, 106*bb72f073SLang Hames StringRef(DylibPath), (uint64_t)0)) 107*bb72f073SLang Hames return std::move(Err); 108*bb72f073SLang Hames return H; 109*bb72f073SLang Hames } 110*bb72f073SLang Hames 111*bb72f073SLang Hames Expected<std::vector<tpctypes::LookupResult>> 112*bb72f073SLang Hames SimpleRemoteEPC::lookupSymbols(ArrayRef<LookupRequest> Request) { 113*bb72f073SLang Hames Expected<std::vector<tpctypes::LookupResult>> R( 114*bb72f073SLang Hames (std::vector<tpctypes::LookupResult>())); 115*bb72f073SLang Hames 116*bb72f073SLang Hames if (auto Err = callSPSWrapper<shared::SPSLookupSymbolsSignature>( 117*bb72f073SLang Hames LookupSymbolsAddr.getValue(), R, JDI.JITDispatchContextAddress, 118*bb72f073SLang Hames Request)) 119*bb72f073SLang Hames return std::move(Err); 120*bb72f073SLang Hames return R; 121*bb72f073SLang Hames } 122*bb72f073SLang Hames 123*bb72f073SLang Hames Expected<int32_t> SimpleRemoteEPC::runAsMain(JITTargetAddress MainFnAddr, 124*bb72f073SLang Hames ArrayRef<std::string> Args) { 125*bb72f073SLang Hames int64_t Result = 0; 126*bb72f073SLang Hames if (auto Err = callSPSWrapper<shared::SPSRunAsMainSignature>( 127*bb72f073SLang Hames RunAsMainAddr.getValue(), Result, ExecutorAddress(MainFnAddr), Args)) 128*bb72f073SLang Hames return std::move(Err); 129*bb72f073SLang Hames return Result; 130*bb72f073SLang Hames } 131*bb72f073SLang Hames 132*bb72f073SLang Hames void SimpleRemoteEPC::callWrapperAsync(SendResultFunction OnComplete, 133*bb72f073SLang Hames JITTargetAddress WrapperFnAddr, 134*bb72f073SLang Hames ArrayRef<char> ArgBuffer) { 135*bb72f073SLang Hames uint64_t SeqNo; 136*bb72f073SLang Hames { 137*bb72f073SLang Hames std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 138*bb72f073SLang Hames SeqNo = getNextSeqNo(); 139*bb72f073SLang Hames assert(!PendingCallWrapperResults.count(SeqNo) && "SeqNo already in use"); 140*bb72f073SLang Hames PendingCallWrapperResults[SeqNo] = std::move(OnComplete); 141*bb72f073SLang Hames } 142*bb72f073SLang Hames 143*bb72f073SLang Hames if (auto Err = T->sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo, 144*bb72f073SLang Hames ExecutorAddress(WrapperFnAddr), ArgBuffer)) { 145*bb72f073SLang Hames getExecutionSession().reportError(std::move(Err)); 146*bb72f073SLang Hames } 147*bb72f073SLang Hames } 148*bb72f073SLang Hames 149*bb72f073SLang Hames Error SimpleRemoteEPC::disconnect() { 150*bb72f073SLang Hames Disconnected = true; 151*bb72f073SLang Hames T->disconnect(); 152*bb72f073SLang Hames return Error::success(); 153*bb72f073SLang Hames } 154*bb72f073SLang Hames 155*bb72f073SLang Hames Expected<SimpleRemoteEPCTransportClient::HandleMessageAction> 156*bb72f073SLang Hames SimpleRemoteEPC::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, 157*bb72f073SLang Hames ExecutorAddress TagAddr, 158*bb72f073SLang Hames SimpleRemoteEPCArgBytesVector ArgBytes) { 159*bb72f073SLang Hames using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>; 160*bb72f073SLang Hames if (static_cast<UT>(OpC) < static_cast<UT>(SimpleRemoteEPCOpcode::FirstOpC) || 161*bb72f073SLang Hames static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC)) 162*bb72f073SLang Hames return make_error<StringError>("Unexpected opcode", 163*bb72f073SLang Hames inconvertibleErrorCode()); 164*bb72f073SLang Hames 165*bb72f073SLang Hames switch (OpC) { 166*bb72f073SLang Hames case SimpleRemoteEPCOpcode::Setup: 167*bb72f073SLang Hames if (auto Err = handleSetup(SeqNo, TagAddr, std::move(ArgBytes))) 168*bb72f073SLang Hames return std::move(Err); 169*bb72f073SLang Hames break; 170*bb72f073SLang Hames case SimpleRemoteEPCOpcode::Hangup: 171*bb72f073SLang Hames // FIXME: Put EPC into 'detached' state. 172*bb72f073SLang Hames return SimpleRemoteEPCTransportClient::EndSession; 173*bb72f073SLang Hames case SimpleRemoteEPCOpcode::Result: 174*bb72f073SLang Hames if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes))) 175*bb72f073SLang Hames return std::move(Err); 176*bb72f073SLang Hames break; 177*bb72f073SLang Hames case SimpleRemoteEPCOpcode::CallWrapper: 178*bb72f073SLang Hames handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes)); 179*bb72f073SLang Hames break; 180*bb72f073SLang Hames } 181*bb72f073SLang Hames return ContinueSession; 182*bb72f073SLang Hames } 183*bb72f073SLang Hames 184*bb72f073SLang Hames void SimpleRemoteEPC::handleDisconnect(Error Err) { 185*bb72f073SLang Hames PendingCallWrapperResultsMap TmpPending; 186*bb72f073SLang Hames 187*bb72f073SLang Hames { 188*bb72f073SLang Hames std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 189*bb72f073SLang Hames std::swap(TmpPending, PendingCallWrapperResults); 190*bb72f073SLang Hames } 191*bb72f073SLang Hames 192*bb72f073SLang Hames for (auto &KV : TmpPending) 193*bb72f073SLang Hames KV.second( 194*bb72f073SLang Hames shared::WrapperFunctionResult::createOutOfBandError("disconnecting")); 195*bb72f073SLang Hames 196*bb72f073SLang Hames if (Err) { 197*bb72f073SLang Hames // FIXME: Move ReportError to EPC. 198*bb72f073SLang Hames if (ES) 199*bb72f073SLang Hames ES->reportError(std::move(Err)); 200*bb72f073SLang Hames else 201*bb72f073SLang Hames logAllUnhandledErrors(std::move(Err), errs(), "SimpleRemoteEPC: "); 202*bb72f073SLang Hames } 203*bb72f073SLang Hames } 204*bb72f073SLang Hames 205*bb72f073SLang Hames void SimpleRemoteEPC::setMemoryManager( 206*bb72f073SLang Hames std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) { 207*bb72f073SLang Hames OwnedMemMgr = std::move(MemMgr); 208*bb72f073SLang Hames this->MemMgr = OwnedMemMgr.get(); 209*bb72f073SLang Hames } 210*bb72f073SLang Hames 211*bb72f073SLang Hames void SimpleRemoteEPC::setMemoryAccess(std::unique_ptr<MemoryAccess> MemAccess) { 212*bb72f073SLang Hames OwnedMemAccess = std::move(MemAccess); 213*bb72f073SLang Hames this->MemAccess = OwnedMemAccess.get(); 214*bb72f073SLang Hames } 215*bb72f073SLang Hames 216*bb72f073SLang Hames Error SimpleRemoteEPC::setupDefaultMemoryManager( 217*bb72f073SLang Hames const SimpleRemoteEPCExecutorInfo &EI) { 218*bb72f073SLang Hames 219*bb72f073SLang Hames EPCGenericJITLinkMemoryManager::FuncAddrs FAs; 220*bb72f073SLang Hames 221*bb72f073SLang Hames if (auto Err = EI.getBootstrapSymbols( 222*bb72f073SLang Hames {{FAs.Reserve, "__llvm_orc_memory_reserve"}, 223*bb72f073SLang Hames {FAs.Finalize, "__llvm_orc_memory_finalize"}, 224*bb72f073SLang Hames {FAs.Deallocate, "__llvm_orc_memory_deallocate"}})) 225*bb72f073SLang Hames return Err; 226*bb72f073SLang Hames 227*bb72f073SLang Hames setMemoryManager( 228*bb72f073SLang Hames std::make_unique<EPCGenericJITLinkMemoryManager>(*this, FAs)); 229*bb72f073SLang Hames return Error::success(); 230*bb72f073SLang Hames } 231*bb72f073SLang Hames 232*bb72f073SLang Hames Error SimpleRemoteEPC::setupDefaultMemoryAccess( 233*bb72f073SLang Hames const SimpleRemoteEPCExecutorInfo &EI) { 234*bb72f073SLang Hames 235*bb72f073SLang Hames return Error::success(); 236*bb72f073SLang Hames } 237*bb72f073SLang Hames 238*bb72f073SLang Hames Error SimpleRemoteEPC::handleSetup(uint64_t SeqNo, ExecutorAddress TagAddr, 239*bb72f073SLang Hames SimpleRemoteEPCArgBytesVector ArgBytes) { 240*bb72f073SLang Hames if (SeqNo != 0) 241*bb72f073SLang Hames return make_error<StringError>("Setup packet SeqNo not zero", 242*bb72f073SLang Hames inconvertibleErrorCode()); 243*bb72f073SLang Hames 244*bb72f073SLang Hames if (TagAddr) 245*bb72f073SLang Hames return make_error<StringError>("Setup packet TagAddr not zero", 246*bb72f073SLang Hames inconvertibleErrorCode()); 247*bb72f073SLang Hames 248*bb72f073SLang Hames std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 249*bb72f073SLang Hames auto I = PendingCallWrapperResults.find(0); 250*bb72f073SLang Hames assert(PendingCallWrapperResults.size() == 1 && 251*bb72f073SLang Hames I != PendingCallWrapperResults.end() && 252*bb72f073SLang Hames "Setup message handler not connectly set up"); 253*bb72f073SLang Hames auto SetupMsgHandler = std::move(I->second); 254*bb72f073SLang Hames PendingCallWrapperResults.erase(I); 255*bb72f073SLang Hames 256*bb72f073SLang Hames auto WFR = 257*bb72f073SLang Hames shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size()); 258*bb72f073SLang Hames SetupMsgHandler(std::move(WFR)); 259*bb72f073SLang Hames return Error::success(); 260*bb72f073SLang Hames } 261*bb72f073SLang Hames 262*bb72f073SLang Hames void SimpleRemoteEPC::prepareToReceiveSetupMessage( 263*bb72f073SLang Hames std::promise<MSVCPExpected<SimpleRemoteEPCExecutorInfo>> &ExecInfoP) { 264*bb72f073SLang Hames PendingCallWrapperResults[0] = 265*bb72f073SLang Hames [&](shared::WrapperFunctionResult SetupMsgBytes) { 266*bb72f073SLang Hames if (const char *ErrMsg = SetupMsgBytes.getOutOfBandError()) { 267*bb72f073SLang Hames ExecInfoP.set_value( 268*bb72f073SLang Hames make_error<StringError>(ErrMsg, inconvertibleErrorCode())); 269*bb72f073SLang Hames return; 270*bb72f073SLang Hames } 271*bb72f073SLang Hames using SPSSerialize = 272*bb72f073SLang Hames shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>; 273*bb72f073SLang Hames shared::SPSInputBuffer IB(SetupMsgBytes.data(), SetupMsgBytes.size()); 274*bb72f073SLang Hames SimpleRemoteEPCExecutorInfo EI; 275*bb72f073SLang Hames if (SPSSerialize::deserialize(IB, EI)) 276*bb72f073SLang Hames ExecInfoP.set_value(EI); 277*bb72f073SLang Hames else 278*bb72f073SLang Hames ExecInfoP.set_value(make_error<StringError>( 279*bb72f073SLang Hames "Could not deserialize setup message", inconvertibleErrorCode())); 280*bb72f073SLang Hames }; 281*bb72f073SLang Hames } 282*bb72f073SLang Hames 283*bb72f073SLang Hames Error SimpleRemoteEPC::handleResult(uint64_t SeqNo, ExecutorAddress TagAddr, 284*bb72f073SLang Hames SimpleRemoteEPCArgBytesVector ArgBytes) { 285*bb72f073SLang Hames SendResultFunction SendResult; 286*bb72f073SLang Hames 287*bb72f073SLang Hames if (TagAddr) 288*bb72f073SLang Hames return make_error<StringError>("Unexpected TagAddr in result message", 289*bb72f073SLang Hames inconvertibleErrorCode()); 290*bb72f073SLang Hames 291*bb72f073SLang Hames { 292*bb72f073SLang Hames std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 293*bb72f073SLang Hames auto I = PendingCallWrapperResults.find(SeqNo); 294*bb72f073SLang Hames if (I == PendingCallWrapperResults.end()) 295*bb72f073SLang Hames return make_error<StringError>("No call for sequence number " + 296*bb72f073SLang Hames Twine(SeqNo), 297*bb72f073SLang Hames inconvertibleErrorCode()); 298*bb72f073SLang Hames SendResult = std::move(I->second); 299*bb72f073SLang Hames PendingCallWrapperResults.erase(I); 300*bb72f073SLang Hames releaseSeqNo(SeqNo); 301*bb72f073SLang Hames } 302*bb72f073SLang Hames 303*bb72f073SLang Hames auto WFR = 304*bb72f073SLang Hames shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size()); 305*bb72f073SLang Hames SendResult(std::move(WFR)); 306*bb72f073SLang Hames return Error::success(); 307*bb72f073SLang Hames } 308*bb72f073SLang Hames 309*bb72f073SLang Hames void SimpleRemoteEPC::handleCallWrapper( 310*bb72f073SLang Hames uint64_t RemoteSeqNo, ExecutorAddress TagAddr, 311*bb72f073SLang Hames SimpleRemoteEPCArgBytesVector ArgBytes) { 312*bb72f073SLang Hames assert(ES && "No ExecutionSession attached"); 313*bb72f073SLang Hames ES->runJITDispatchHandler( 314*bb72f073SLang Hames [this, RemoteSeqNo](shared::WrapperFunctionResult WFR) { 315*bb72f073SLang Hames if (auto Err = 316*bb72f073SLang Hames T->sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo, 317*bb72f073SLang Hames ExecutorAddress(), {WFR.data(), WFR.size()})) 318*bb72f073SLang Hames getExecutionSession().reportError(std::move(Err)); 319*bb72f073SLang Hames }, 320*bb72f073SLang Hames TagAddr.getValue(), ArgBytes); 321*bb72f073SLang Hames } 322*bb72f073SLang Hames 323*bb72f073SLang Hames } // end namespace orc 324*bb72f073SLang Hames } // end namespace llvm 325