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 22fe6060f1SDimitry Andric ExecutorProcessControl::MemoryAccess::~MemoryAccess() {} 23fe6060f1SDimitry Andric 24fe6060f1SDimitry Andric ExecutorProcessControl::~ExecutorProcessControl() {} 25fe6060f1SDimitry Andric 26fe6060f1SDimitry Andric SelfExecutorProcessControl::SelfExecutorProcessControl( 27*349cc55cSDimitry Andric std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D, 28*349cc55cSDimitry Andric Triple TargetTriple, unsigned PageSize, 29*349cc55cSDimitry Andric std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) 30*349cc55cSDimitry Andric : ExecutorProcessControl(std::move(SSP), std::move(D)) { 31fe6060f1SDimitry Andric 32fe6060f1SDimitry Andric OwnedMemMgr = std::move(MemMgr); 33fe6060f1SDimitry Andric if (!OwnedMemMgr) 34*349cc55cSDimitry Andric OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>( 35*349cc55cSDimitry 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; 41*349cc55cSDimitry Andric this->JDI = {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager), 42*349cc55cSDimitry 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, 50*349cc55cSDimitry 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 56*349cc55cSDimitry Andric if (!D) { 57*349cc55cSDimitry Andric #if LLVM_ENABLE_THREADS 58*349cc55cSDimitry Andric D = std::make_unique<DynamicThreadPoolTaskDispatcher>(); 59*349cc55cSDimitry Andric #else 60*349cc55cSDimitry Andric D = std::make_unique<InPlaceTaskDispatcher>(); 61*349cc55cSDimitry Andric #endif 62*349cc55cSDimitry Andric } 63*349cc55cSDimitry 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>( 71*349cc55cSDimitry Andric std::move(SSP), std::move(D), std::move(TT), *PageSize, 72*349cc55cSDimitry 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; 78fe6060f1SDimitry Andric auto Dylib = std::make_unique<sys::DynamicLibrary>( 79fe6060f1SDimitry Andric sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg)); 80fe6060f1SDimitry Andric if (!Dylib->isValid()) 81fe6060f1SDimitry Andric return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 82fe6060f1SDimitry Andric DynamicLibraries.push_back(std::move(Dylib)); 83fe6060f1SDimitry Andric return pointerToJITTargetAddress(DynamicLibraries.back().get()); 84fe6060f1SDimitry Andric } 85fe6060f1SDimitry Andric 86fe6060f1SDimitry Andric Expected<std::vector<tpctypes::LookupResult>> 87fe6060f1SDimitry Andric SelfExecutorProcessControl::lookupSymbols(ArrayRef<LookupRequest> Request) { 88fe6060f1SDimitry Andric std::vector<tpctypes::LookupResult> R; 89fe6060f1SDimitry Andric 90fe6060f1SDimitry Andric for (auto &Elem : Request) { 91fe6060f1SDimitry Andric auto *Dylib = jitTargetAddressToPointer<sys::DynamicLibrary *>(Elem.Handle); 92fe6060f1SDimitry Andric assert(llvm::any_of(DynamicLibraries, 93fe6060f1SDimitry Andric [=](const std::unique_ptr<sys::DynamicLibrary> &DL) { 94fe6060f1SDimitry Andric return DL.get() == Dylib; 95fe6060f1SDimitry Andric }) && 96fe6060f1SDimitry Andric "Invalid handle"); 97fe6060f1SDimitry Andric 98fe6060f1SDimitry Andric R.push_back(std::vector<JITTargetAddress>()); 99fe6060f1SDimitry Andric for (auto &KV : Elem.Symbols) { 100fe6060f1SDimitry Andric auto &Sym = KV.first; 101fe6060f1SDimitry Andric std::string Tmp((*Sym).data() + !!GlobalManglingPrefix, 102fe6060f1SDimitry Andric (*Sym).size() - !!GlobalManglingPrefix); 103fe6060f1SDimitry Andric void *Addr = Dylib->getAddressOfSymbol(Tmp.c_str()); 104fe6060f1SDimitry Andric if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) { 105fe6060f1SDimitry Andric // FIXME: Collect all failing symbols before erroring out. 106fe6060f1SDimitry Andric SymbolNameVector MissingSymbols; 107fe6060f1SDimitry Andric MissingSymbols.push_back(Sym); 108*349cc55cSDimitry Andric return make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols)); 109fe6060f1SDimitry Andric } 110fe6060f1SDimitry Andric R.back().push_back(pointerToJITTargetAddress(Addr)); 111fe6060f1SDimitry Andric } 112fe6060f1SDimitry Andric } 113fe6060f1SDimitry Andric 114fe6060f1SDimitry Andric return R; 115fe6060f1SDimitry Andric } 116fe6060f1SDimitry Andric 117fe6060f1SDimitry Andric Expected<int32_t> 118*349cc55cSDimitry Andric SelfExecutorProcessControl::runAsMain(ExecutorAddr MainFnAddr, 119fe6060f1SDimitry Andric ArrayRef<std::string> Args) { 120fe6060f1SDimitry Andric using MainTy = int (*)(int, char *[]); 121*349cc55cSDimitry Andric return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args); 122fe6060f1SDimitry Andric } 123fe6060f1SDimitry Andric 124*349cc55cSDimitry Andric void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr, 125*349cc55cSDimitry Andric IncomingWFRHandler SendResult, 126fe6060f1SDimitry Andric ArrayRef<char> ArgBuffer) { 127fe6060f1SDimitry Andric using WrapperFnTy = 128*349cc55cSDimitry Andric shared::CWrapperFunctionResult (*)(const char *Data, size_t Size); 129*349cc55cSDimitry Andric auto *WrapperFn = WrapperFnAddr.toPtr<WrapperFnTy>(); 130fe6060f1SDimitry Andric SendResult(WrapperFn(ArgBuffer.data(), ArgBuffer.size())); 131fe6060f1SDimitry Andric } 132fe6060f1SDimitry Andric 133*349cc55cSDimitry Andric Error SelfExecutorProcessControl::disconnect() { 134*349cc55cSDimitry Andric D->shutdown(); 135*349cc55cSDimitry Andric return Error::success(); 136*349cc55cSDimitry Andric } 137fe6060f1SDimitry Andric 138*349cc55cSDimitry Andric void SelfExecutorProcessControl::writeUInt8sAsync( 139*349cc55cSDimitry Andric ArrayRef<tpctypes::UInt8Write> Ws, WriteResultFn OnWriteComplete) { 140fe6060f1SDimitry Andric for (auto &W : Ws) 141*349cc55cSDimitry Andric *W.Addr.toPtr<uint8_t *>() = W.Value; 142fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 143fe6060f1SDimitry Andric } 144fe6060f1SDimitry Andric 145*349cc55cSDimitry Andric void SelfExecutorProcessControl::writeUInt16sAsync( 146fe6060f1SDimitry Andric ArrayRef<tpctypes::UInt16Write> Ws, WriteResultFn OnWriteComplete) { 147fe6060f1SDimitry Andric for (auto &W : Ws) 148*349cc55cSDimitry Andric *W.Addr.toPtr<uint16_t *>() = W.Value; 149fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 150fe6060f1SDimitry Andric } 151fe6060f1SDimitry Andric 152*349cc55cSDimitry Andric void SelfExecutorProcessControl::writeUInt32sAsync( 153fe6060f1SDimitry Andric ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) { 154fe6060f1SDimitry Andric for (auto &W : Ws) 155*349cc55cSDimitry Andric *W.Addr.toPtr<uint32_t *>() = W.Value; 156fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 157fe6060f1SDimitry Andric } 158fe6060f1SDimitry Andric 159*349cc55cSDimitry Andric void SelfExecutorProcessControl::writeUInt64sAsync( 160fe6060f1SDimitry Andric ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) { 161fe6060f1SDimitry Andric for (auto &W : Ws) 162*349cc55cSDimitry Andric *W.Addr.toPtr<uint64_t *>() = W.Value; 163fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 164fe6060f1SDimitry Andric } 165fe6060f1SDimitry Andric 166*349cc55cSDimitry Andric void SelfExecutorProcessControl::writeBuffersAsync( 167fe6060f1SDimitry Andric ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) { 168fe6060f1SDimitry Andric for (auto &W : Ws) 169*349cc55cSDimitry Andric memcpy(W.Addr.toPtr<char *>(), W.Buffer.data(), W.Buffer.size()); 170fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 171fe6060f1SDimitry Andric } 172fe6060f1SDimitry Andric 173*349cc55cSDimitry Andric shared::CWrapperFunctionResult 174fe6060f1SDimitry Andric SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager( 175fe6060f1SDimitry Andric void *Ctx, const void *FnTag, const char *Data, size_t Size) { 176fe6060f1SDimitry Andric 177fe6060f1SDimitry Andric LLVM_DEBUG({ 178fe6060f1SDimitry Andric dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size 179fe6060f1SDimitry Andric << " byte payload.\n"; 180fe6060f1SDimitry Andric }); 181fe6060f1SDimitry Andric 182fe6060f1SDimitry Andric std::promise<shared::WrapperFunctionResult> ResultP; 183fe6060f1SDimitry Andric auto ResultF = ResultP.get_future(); 184fe6060f1SDimitry Andric static_cast<SelfExecutorProcessControl *>(Ctx) 185fe6060f1SDimitry Andric ->getExecutionSession() 186fe6060f1SDimitry Andric .runJITDispatchHandler( 187fe6060f1SDimitry Andric [ResultP = std::move(ResultP)]( 188fe6060f1SDimitry Andric shared::WrapperFunctionResult Result) mutable { 189fe6060f1SDimitry Andric ResultP.set_value(std::move(Result)); 190fe6060f1SDimitry Andric }, 191fe6060f1SDimitry Andric pointerToJITTargetAddress(FnTag), {Data, Size}); 192fe6060f1SDimitry Andric 193fe6060f1SDimitry Andric return ResultF.get().release(); 194fe6060f1SDimitry Andric } 195fe6060f1SDimitry Andric 196fe6060f1SDimitry Andric } // end namespace orc 197fe6060f1SDimitry Andric } // end namespace llvm 198