1fe6060f1SDimitry Andric //===---- ExecutorProcessControl.cpp -- Executor process control APIs -----===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric 9fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" 10fe6060f1SDimitry Andric 11fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/Orc/Core.h" 12fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h" 13fe6060f1SDimitry Andric #include "llvm/Support/FormatVariadic.h" 14fe6060f1SDimitry Andric #include "llvm/Support/Host.h" 15fe6060f1SDimitry Andric #include "llvm/Support/Process.h" 16fe6060f1SDimitry Andric 17fe6060f1SDimitry Andric #define DEBUG_TYPE "orc" 18fe6060f1SDimitry Andric 19fe6060f1SDimitry Andric namespace llvm { 20fe6060f1SDimitry Andric namespace orc { 21fe6060f1SDimitry Andric 2281ad6265SDimitry Andric ExecutorProcessControl::MemoryAccess::~MemoryAccess() = default; 23fe6060f1SDimitry Andric 2481ad6265SDimitry Andric ExecutorProcessControl::~ExecutorProcessControl() = default; 25fe6060f1SDimitry Andric 26fe6060f1SDimitry Andric SelfExecutorProcessControl::SelfExecutorProcessControl( 27349cc55cSDimitry Andric std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D, 28349cc55cSDimitry Andric Triple TargetTriple, unsigned PageSize, 29349cc55cSDimitry Andric std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) 30349cc55cSDimitry Andric : ExecutorProcessControl(std::move(SSP), std::move(D)) { 31fe6060f1SDimitry Andric 32fe6060f1SDimitry Andric OwnedMemMgr = std::move(MemMgr); 33fe6060f1SDimitry Andric if (!OwnedMemMgr) 34349cc55cSDimitry Andric OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>( 35349cc55cSDimitry Andric sys::Process::getPageSizeEstimate()); 36fe6060f1SDimitry Andric 37fe6060f1SDimitry Andric this->TargetTriple = std::move(TargetTriple); 38fe6060f1SDimitry Andric this->PageSize = PageSize; 39fe6060f1SDimitry Andric this->MemMgr = OwnedMemMgr.get(); 40fe6060f1SDimitry Andric this->MemAccess = this; 41349cc55cSDimitry Andric this->JDI = {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager), 42349cc55cSDimitry Andric ExecutorAddr::fromPtr(this)}; 43fe6060f1SDimitry Andric if (this->TargetTriple.isOSBinFormatMachO()) 44fe6060f1SDimitry Andric GlobalManglingPrefix = '_'; 45fe6060f1SDimitry Andric } 46fe6060f1SDimitry Andric 47fe6060f1SDimitry Andric Expected<std::unique_ptr<SelfExecutorProcessControl>> 48fe6060f1SDimitry Andric SelfExecutorProcessControl::Create( 49fe6060f1SDimitry Andric std::shared_ptr<SymbolStringPool> SSP, 50349cc55cSDimitry Andric std::unique_ptr<TaskDispatcher> D, 51fe6060f1SDimitry Andric std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) { 52fe6060f1SDimitry Andric 53fe6060f1SDimitry Andric if (!SSP) 54fe6060f1SDimitry Andric SSP = std::make_shared<SymbolStringPool>(); 55fe6060f1SDimitry Andric 56349cc55cSDimitry Andric if (!D) { 57349cc55cSDimitry Andric #if LLVM_ENABLE_THREADS 58349cc55cSDimitry Andric D = std::make_unique<DynamicThreadPoolTaskDispatcher>(); 59349cc55cSDimitry Andric #else 60349cc55cSDimitry Andric D = std::make_unique<InPlaceTaskDispatcher>(); 61349cc55cSDimitry Andric #endif 62349cc55cSDimitry Andric } 63349cc55cSDimitry Andric 64fe6060f1SDimitry Andric auto PageSize = sys::Process::getPageSize(); 65fe6060f1SDimitry Andric if (!PageSize) 66fe6060f1SDimitry Andric return PageSize.takeError(); 67fe6060f1SDimitry Andric 68fe6060f1SDimitry Andric Triple TT(sys::getProcessTriple()); 69fe6060f1SDimitry Andric 70fe6060f1SDimitry Andric return std::make_unique<SelfExecutorProcessControl>( 71349cc55cSDimitry Andric std::move(SSP), std::move(D), std::move(TT), *PageSize, 72349cc55cSDimitry Andric std::move(MemMgr)); 73fe6060f1SDimitry Andric } 74fe6060f1SDimitry Andric 75fe6060f1SDimitry Andric Expected<tpctypes::DylibHandle> 76fe6060f1SDimitry Andric SelfExecutorProcessControl::loadDylib(const char *DylibPath) { 77fe6060f1SDimitry Andric std::string ErrMsg; 78*bdd1243dSDimitry Andric auto Dylib = sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg); 79*bdd1243dSDimitry Andric if (!Dylib.isValid()) 80fe6060f1SDimitry Andric return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 81*bdd1243dSDimitry Andric return ExecutorAddr::fromPtr(Dylib.getOSSpecificHandle()); 82fe6060f1SDimitry Andric } 83fe6060f1SDimitry Andric 84fe6060f1SDimitry Andric Expected<std::vector<tpctypes::LookupResult>> 85fe6060f1SDimitry Andric SelfExecutorProcessControl::lookupSymbols(ArrayRef<LookupRequest> Request) { 86fe6060f1SDimitry Andric std::vector<tpctypes::LookupResult> R; 87fe6060f1SDimitry Andric 88fe6060f1SDimitry Andric for (auto &Elem : Request) { 89*bdd1243dSDimitry Andric sys::DynamicLibrary Dylib(Elem.Handle.toPtr<void *>()); 90*bdd1243dSDimitry Andric R.push_back(std::vector<ExecutorAddr>()); 91fe6060f1SDimitry Andric for (auto &KV : Elem.Symbols) { 92fe6060f1SDimitry Andric auto &Sym = KV.first; 93fe6060f1SDimitry Andric std::string Tmp((*Sym).data() + !!GlobalManglingPrefix, 94fe6060f1SDimitry Andric (*Sym).size() - !!GlobalManglingPrefix); 95*bdd1243dSDimitry Andric void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str()); 96fe6060f1SDimitry Andric if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) { 97fe6060f1SDimitry Andric // FIXME: Collect all failing symbols before erroring out. 98fe6060f1SDimitry Andric SymbolNameVector MissingSymbols; 99fe6060f1SDimitry Andric MissingSymbols.push_back(Sym); 100349cc55cSDimitry Andric return make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols)); 101fe6060f1SDimitry Andric } 102*bdd1243dSDimitry Andric R.back().push_back(ExecutorAddr::fromPtr(Addr)); 103fe6060f1SDimitry Andric } 104fe6060f1SDimitry Andric } 105fe6060f1SDimitry Andric 106fe6060f1SDimitry Andric return R; 107fe6060f1SDimitry Andric } 108fe6060f1SDimitry Andric 109fe6060f1SDimitry Andric Expected<int32_t> 110349cc55cSDimitry Andric SelfExecutorProcessControl::runAsMain(ExecutorAddr MainFnAddr, 111fe6060f1SDimitry Andric ArrayRef<std::string> Args) { 112fe6060f1SDimitry Andric using MainTy = int (*)(int, char *[]); 113349cc55cSDimitry Andric return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args); 114fe6060f1SDimitry Andric } 115fe6060f1SDimitry Andric 116*bdd1243dSDimitry Andric Expected<int32_t> 117*bdd1243dSDimitry Andric SelfExecutorProcessControl::runAsVoidFunction(ExecutorAddr VoidFnAddr) { 118*bdd1243dSDimitry Andric using VoidTy = int (*)(); 119*bdd1243dSDimitry Andric return orc::runAsVoidFunction(VoidFnAddr.toPtr<VoidTy>()); 120*bdd1243dSDimitry Andric } 121*bdd1243dSDimitry Andric 122*bdd1243dSDimitry Andric Expected<int32_t> 123*bdd1243dSDimitry Andric SelfExecutorProcessControl::runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) { 124*bdd1243dSDimitry Andric using IntTy = int (*)(int); 125*bdd1243dSDimitry Andric return orc::runAsIntFunction(IntFnAddr.toPtr<IntTy>(), Arg); 126*bdd1243dSDimitry Andric } 127*bdd1243dSDimitry Andric 128349cc55cSDimitry Andric void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr, 129349cc55cSDimitry Andric IncomingWFRHandler SendResult, 130fe6060f1SDimitry Andric ArrayRef<char> ArgBuffer) { 131fe6060f1SDimitry Andric using WrapperFnTy = 132349cc55cSDimitry Andric shared::CWrapperFunctionResult (*)(const char *Data, size_t Size); 133349cc55cSDimitry Andric auto *WrapperFn = WrapperFnAddr.toPtr<WrapperFnTy>(); 134fe6060f1SDimitry Andric SendResult(WrapperFn(ArgBuffer.data(), ArgBuffer.size())); 135fe6060f1SDimitry Andric } 136fe6060f1SDimitry Andric 137349cc55cSDimitry Andric Error SelfExecutorProcessControl::disconnect() { 138349cc55cSDimitry Andric D->shutdown(); 139349cc55cSDimitry Andric return Error::success(); 140349cc55cSDimitry Andric } 141fe6060f1SDimitry Andric 142349cc55cSDimitry Andric void SelfExecutorProcessControl::writeUInt8sAsync( 143349cc55cSDimitry Andric ArrayRef<tpctypes::UInt8Write> Ws, WriteResultFn OnWriteComplete) { 144fe6060f1SDimitry Andric for (auto &W : Ws) 145349cc55cSDimitry Andric *W.Addr.toPtr<uint8_t *>() = W.Value; 146fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 147fe6060f1SDimitry Andric } 148fe6060f1SDimitry Andric 149349cc55cSDimitry Andric void SelfExecutorProcessControl::writeUInt16sAsync( 150fe6060f1SDimitry Andric ArrayRef<tpctypes::UInt16Write> Ws, WriteResultFn OnWriteComplete) { 151fe6060f1SDimitry Andric for (auto &W : Ws) 152349cc55cSDimitry Andric *W.Addr.toPtr<uint16_t *>() = W.Value; 153fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 154fe6060f1SDimitry Andric } 155fe6060f1SDimitry Andric 156349cc55cSDimitry Andric void SelfExecutorProcessControl::writeUInt32sAsync( 157fe6060f1SDimitry Andric ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) { 158fe6060f1SDimitry Andric for (auto &W : Ws) 159349cc55cSDimitry Andric *W.Addr.toPtr<uint32_t *>() = W.Value; 160fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 161fe6060f1SDimitry Andric } 162fe6060f1SDimitry Andric 163349cc55cSDimitry Andric void SelfExecutorProcessControl::writeUInt64sAsync( 164fe6060f1SDimitry Andric ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) { 165fe6060f1SDimitry Andric for (auto &W : Ws) 166349cc55cSDimitry Andric *W.Addr.toPtr<uint64_t *>() = W.Value; 167fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 168fe6060f1SDimitry Andric } 169fe6060f1SDimitry Andric 170349cc55cSDimitry Andric void SelfExecutorProcessControl::writeBuffersAsync( 171fe6060f1SDimitry Andric ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) { 172fe6060f1SDimitry Andric for (auto &W : Ws) 173349cc55cSDimitry Andric memcpy(W.Addr.toPtr<char *>(), W.Buffer.data(), W.Buffer.size()); 174fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 175fe6060f1SDimitry Andric } 176fe6060f1SDimitry Andric 177349cc55cSDimitry Andric shared::CWrapperFunctionResult 178fe6060f1SDimitry Andric SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager( 179fe6060f1SDimitry Andric void *Ctx, const void *FnTag, const char *Data, size_t Size) { 180fe6060f1SDimitry Andric 181fe6060f1SDimitry Andric LLVM_DEBUG({ 182fe6060f1SDimitry Andric dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size 183fe6060f1SDimitry Andric << " byte payload.\n"; 184fe6060f1SDimitry Andric }); 185fe6060f1SDimitry Andric 186fe6060f1SDimitry Andric std::promise<shared::WrapperFunctionResult> ResultP; 187fe6060f1SDimitry Andric auto ResultF = ResultP.get_future(); 188fe6060f1SDimitry Andric static_cast<SelfExecutorProcessControl *>(Ctx) 189fe6060f1SDimitry Andric ->getExecutionSession() 190fe6060f1SDimitry Andric .runJITDispatchHandler( 191fe6060f1SDimitry Andric [ResultP = std::move(ResultP)]( 192fe6060f1SDimitry Andric shared::WrapperFunctionResult Result) mutable { 193fe6060f1SDimitry Andric ResultP.set_value(std::move(Result)); 194fe6060f1SDimitry Andric }, 195fe6060f1SDimitry Andric pointerToJITTargetAddress(FnTag), {Data, Size}); 196fe6060f1SDimitry Andric 197fe6060f1SDimitry Andric return ResultF.get().release(); 198fe6060f1SDimitry Andric } 199fe6060f1SDimitry Andric 200fe6060f1SDimitry Andric } // end namespace orc 201fe6060f1SDimitry Andric } // end namespace llvm 202