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" 125f757f3fSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" 135f757f3fSDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h" 14fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h" 15fe6060f1SDimitry Andric #include "llvm/Support/FormatVariadic.h" 16fe6060f1SDimitry Andric #include "llvm/Support/Process.h" 1706c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 18fe6060f1SDimitry Andric 19fe6060f1SDimitry Andric #define DEBUG_TYPE "orc" 20fe6060f1SDimitry Andric 21fe6060f1SDimitry Andric namespace llvm { 22fe6060f1SDimitry Andric namespace orc { 23fe6060f1SDimitry Andric 2481ad6265SDimitry Andric ExecutorProcessControl::MemoryAccess::~MemoryAccess() = default; 25fe6060f1SDimitry Andric 2681ad6265SDimitry Andric ExecutorProcessControl::~ExecutorProcessControl() = default; 27fe6060f1SDimitry Andric 28fe6060f1SDimitry Andric SelfExecutorProcessControl::SelfExecutorProcessControl( 29349cc55cSDimitry Andric std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D, 30349cc55cSDimitry Andric Triple TargetTriple, unsigned PageSize, 31349cc55cSDimitry Andric std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) 325f757f3fSDimitry Andric : ExecutorProcessControl(std::move(SSP), std::move(D)), 335f757f3fSDimitry Andric InProcessMemoryAccess(TargetTriple.isArch64Bit()) { 34fe6060f1SDimitry Andric 35fe6060f1SDimitry Andric OwnedMemMgr = std::move(MemMgr); 36fe6060f1SDimitry Andric if (!OwnedMemMgr) 37349cc55cSDimitry Andric OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>( 38349cc55cSDimitry Andric sys::Process::getPageSizeEstimate()); 39fe6060f1SDimitry Andric 40fe6060f1SDimitry Andric this->TargetTriple = std::move(TargetTriple); 41fe6060f1SDimitry Andric this->PageSize = PageSize; 42fe6060f1SDimitry Andric this->MemMgr = OwnedMemMgr.get(); 43fe6060f1SDimitry Andric this->MemAccess = this; 44349cc55cSDimitry Andric this->JDI = {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager), 45349cc55cSDimitry Andric ExecutorAddr::fromPtr(this)}; 46fe6060f1SDimitry Andric if (this->TargetTriple.isOSBinFormatMachO()) 47fe6060f1SDimitry Andric GlobalManglingPrefix = '_'; 485f757f3fSDimitry Andric 495f757f3fSDimitry Andric this->BootstrapSymbols[rt::RegisterEHFrameSectionWrapperName] = 505f757f3fSDimitry Andric ExecutorAddr::fromPtr(&llvm_orc_registerEHFrameSectionWrapper); 515f757f3fSDimitry Andric this->BootstrapSymbols[rt::DeregisterEHFrameSectionWrapperName] = 525f757f3fSDimitry Andric ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionWrapper); 53fe6060f1SDimitry Andric } 54fe6060f1SDimitry Andric 55fe6060f1SDimitry Andric Expected<std::unique_ptr<SelfExecutorProcessControl>> 56fe6060f1SDimitry Andric SelfExecutorProcessControl::Create( 57fe6060f1SDimitry Andric std::shared_ptr<SymbolStringPool> SSP, 58349cc55cSDimitry Andric std::unique_ptr<TaskDispatcher> D, 59fe6060f1SDimitry Andric std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) { 60fe6060f1SDimitry Andric 61fe6060f1SDimitry Andric if (!SSP) 62fe6060f1SDimitry Andric SSP = std::make_shared<SymbolStringPool>(); 63fe6060f1SDimitry Andric 64*0fca6ea1SDimitry Andric if (!D) 65349cc55cSDimitry Andric D = std::make_unique<InPlaceTaskDispatcher>(); 66349cc55cSDimitry Andric 67fe6060f1SDimitry Andric auto PageSize = sys::Process::getPageSize(); 68fe6060f1SDimitry Andric if (!PageSize) 69fe6060f1SDimitry Andric return PageSize.takeError(); 70fe6060f1SDimitry Andric 71fe6060f1SDimitry Andric Triple TT(sys::getProcessTriple()); 72fe6060f1SDimitry Andric 73fe6060f1SDimitry Andric return std::make_unique<SelfExecutorProcessControl>( 74349cc55cSDimitry Andric std::move(SSP), std::move(D), std::move(TT), *PageSize, 75349cc55cSDimitry Andric std::move(MemMgr)); 76fe6060f1SDimitry Andric } 77fe6060f1SDimitry Andric 78fe6060f1SDimitry Andric Expected<tpctypes::DylibHandle> 79fe6060f1SDimitry Andric SelfExecutorProcessControl::loadDylib(const char *DylibPath) { 80fe6060f1SDimitry Andric std::string ErrMsg; 81bdd1243dSDimitry Andric auto Dylib = sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg); 82bdd1243dSDimitry Andric if (!Dylib.isValid()) 83fe6060f1SDimitry Andric return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 84bdd1243dSDimitry Andric return ExecutorAddr::fromPtr(Dylib.getOSSpecificHandle()); 85fe6060f1SDimitry Andric } 86fe6060f1SDimitry Andric 87*0fca6ea1SDimitry Andric void SelfExecutorProcessControl::lookupSymbolsAsync( 88*0fca6ea1SDimitry Andric ArrayRef<LookupRequest> Request, 89*0fca6ea1SDimitry Andric ExecutorProcessControl::SymbolLookupCompleteFn Complete) { 90fe6060f1SDimitry Andric std::vector<tpctypes::LookupResult> R; 91fe6060f1SDimitry Andric 92fe6060f1SDimitry Andric for (auto &Elem : Request) { 93bdd1243dSDimitry Andric sys::DynamicLibrary Dylib(Elem.Handle.toPtr<void *>()); 941db9f3b2SDimitry Andric R.push_back(std::vector<ExecutorSymbolDef>()); 95fe6060f1SDimitry Andric for (auto &KV : Elem.Symbols) { 96fe6060f1SDimitry Andric auto &Sym = KV.first; 97fe6060f1SDimitry Andric std::string Tmp((*Sym).data() + !!GlobalManglingPrefix, 98fe6060f1SDimitry Andric (*Sym).size() - !!GlobalManglingPrefix); 99bdd1243dSDimitry Andric void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str()); 100fe6060f1SDimitry Andric if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) { 101fe6060f1SDimitry Andric // FIXME: Collect all failing symbols before erroring out. 102fe6060f1SDimitry Andric SymbolNameVector MissingSymbols; 103fe6060f1SDimitry Andric MissingSymbols.push_back(Sym); 104*0fca6ea1SDimitry Andric return Complete( 105*0fca6ea1SDimitry Andric make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols))); 106fe6060f1SDimitry Andric } 1071db9f3b2SDimitry Andric // FIXME: determine accurate JITSymbolFlags. 1081db9f3b2SDimitry Andric R.back().push_back( 1091db9f3b2SDimitry Andric {ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported}); 110fe6060f1SDimitry Andric } 111fe6060f1SDimitry Andric } 112fe6060f1SDimitry Andric 113*0fca6ea1SDimitry Andric Complete(std::move(R)); 114fe6060f1SDimitry Andric } 115fe6060f1SDimitry Andric 116fe6060f1SDimitry Andric Expected<int32_t> 117349cc55cSDimitry Andric SelfExecutorProcessControl::runAsMain(ExecutorAddr MainFnAddr, 118fe6060f1SDimitry Andric ArrayRef<std::string> Args) { 119fe6060f1SDimitry Andric using MainTy = int (*)(int, char *[]); 120349cc55cSDimitry Andric return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args); 121fe6060f1SDimitry Andric } 122fe6060f1SDimitry Andric 123bdd1243dSDimitry Andric Expected<int32_t> 124bdd1243dSDimitry Andric SelfExecutorProcessControl::runAsVoidFunction(ExecutorAddr VoidFnAddr) { 125bdd1243dSDimitry Andric using VoidTy = int (*)(); 126bdd1243dSDimitry Andric return orc::runAsVoidFunction(VoidFnAddr.toPtr<VoidTy>()); 127bdd1243dSDimitry Andric } 128bdd1243dSDimitry Andric 129bdd1243dSDimitry Andric Expected<int32_t> 130bdd1243dSDimitry Andric SelfExecutorProcessControl::runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) { 131bdd1243dSDimitry Andric using IntTy = int (*)(int); 132bdd1243dSDimitry Andric return orc::runAsIntFunction(IntFnAddr.toPtr<IntTy>(), Arg); 133bdd1243dSDimitry Andric } 134bdd1243dSDimitry Andric 135349cc55cSDimitry Andric void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr, 136349cc55cSDimitry Andric IncomingWFRHandler SendResult, 137fe6060f1SDimitry Andric ArrayRef<char> ArgBuffer) { 138fe6060f1SDimitry Andric using WrapperFnTy = 139349cc55cSDimitry Andric shared::CWrapperFunctionResult (*)(const char *Data, size_t Size); 140349cc55cSDimitry Andric auto *WrapperFn = WrapperFnAddr.toPtr<WrapperFnTy>(); 141fe6060f1SDimitry Andric SendResult(WrapperFn(ArgBuffer.data(), ArgBuffer.size())); 142fe6060f1SDimitry Andric } 143fe6060f1SDimitry Andric 144349cc55cSDimitry Andric Error SelfExecutorProcessControl::disconnect() { 145349cc55cSDimitry Andric D->shutdown(); 146349cc55cSDimitry Andric return Error::success(); 147349cc55cSDimitry Andric } 148fe6060f1SDimitry Andric 1495f757f3fSDimitry Andric void InProcessMemoryAccess::writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws, 1505f757f3fSDimitry Andric WriteResultFn OnWriteComplete) { 151fe6060f1SDimitry Andric for (auto &W : Ws) 152349cc55cSDimitry Andric *W.Addr.toPtr<uint8_t *>() = W.Value; 153fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 154fe6060f1SDimitry Andric } 155fe6060f1SDimitry Andric 1565f757f3fSDimitry Andric void InProcessMemoryAccess::writeUInt16sAsync( 157fe6060f1SDimitry Andric ArrayRef<tpctypes::UInt16Write> Ws, WriteResultFn OnWriteComplete) { 158fe6060f1SDimitry Andric for (auto &W : Ws) 159349cc55cSDimitry Andric *W.Addr.toPtr<uint16_t *>() = W.Value; 160fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 161fe6060f1SDimitry Andric } 162fe6060f1SDimitry Andric 1635f757f3fSDimitry Andric void InProcessMemoryAccess::writeUInt32sAsync( 164fe6060f1SDimitry Andric ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) { 165fe6060f1SDimitry Andric for (auto &W : Ws) 166349cc55cSDimitry Andric *W.Addr.toPtr<uint32_t *>() = W.Value; 167fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 168fe6060f1SDimitry Andric } 169fe6060f1SDimitry Andric 1705f757f3fSDimitry Andric void InProcessMemoryAccess::writeUInt64sAsync( 171fe6060f1SDimitry Andric ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) { 172fe6060f1SDimitry Andric for (auto &W : Ws) 173349cc55cSDimitry Andric *W.Addr.toPtr<uint64_t *>() = W.Value; 174fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 175fe6060f1SDimitry Andric } 176fe6060f1SDimitry Andric 1775f757f3fSDimitry Andric void InProcessMemoryAccess::writeBuffersAsync( 178fe6060f1SDimitry Andric ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) { 179fe6060f1SDimitry Andric for (auto &W : Ws) 180349cc55cSDimitry Andric memcpy(W.Addr.toPtr<char *>(), W.Buffer.data(), W.Buffer.size()); 181fe6060f1SDimitry Andric OnWriteComplete(Error::success()); 182fe6060f1SDimitry Andric } 183fe6060f1SDimitry Andric 1845f757f3fSDimitry Andric void InProcessMemoryAccess::writePointersAsync( 1855f757f3fSDimitry Andric ArrayRef<tpctypes::PointerWrite> Ws, WriteResultFn OnWriteComplete) { 1865f757f3fSDimitry Andric if (IsArch64Bit) { 1875f757f3fSDimitry Andric for (auto &W : Ws) 1885f757f3fSDimitry Andric *W.Addr.toPtr<uint64_t *>() = W.Value.getValue(); 1895f757f3fSDimitry Andric } else { 1905f757f3fSDimitry Andric for (auto &W : Ws) 1915f757f3fSDimitry Andric *W.Addr.toPtr<uint32_t *>() = static_cast<uint32_t>(W.Value.getValue()); 1925f757f3fSDimitry Andric } 1935f757f3fSDimitry Andric 1945f757f3fSDimitry Andric OnWriteComplete(Error::success()); 1955f757f3fSDimitry Andric } 1965f757f3fSDimitry Andric 197349cc55cSDimitry Andric shared::CWrapperFunctionResult 198fe6060f1SDimitry Andric SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager( 199fe6060f1SDimitry Andric void *Ctx, const void *FnTag, const char *Data, size_t Size) { 200fe6060f1SDimitry Andric 201fe6060f1SDimitry Andric LLVM_DEBUG({ 202fe6060f1SDimitry Andric dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size 203fe6060f1SDimitry Andric << " byte payload.\n"; 204fe6060f1SDimitry Andric }); 205fe6060f1SDimitry Andric 206fe6060f1SDimitry Andric std::promise<shared::WrapperFunctionResult> ResultP; 207fe6060f1SDimitry Andric auto ResultF = ResultP.get_future(); 208fe6060f1SDimitry Andric static_cast<SelfExecutorProcessControl *>(Ctx) 209fe6060f1SDimitry Andric ->getExecutionSession() 210fe6060f1SDimitry Andric .runJITDispatchHandler( 211fe6060f1SDimitry Andric [ResultP = std::move(ResultP)]( 212fe6060f1SDimitry Andric shared::WrapperFunctionResult Result) mutable { 213fe6060f1SDimitry Andric ResultP.set_value(std::move(Result)); 214fe6060f1SDimitry Andric }, 21506c3fb27SDimitry Andric ExecutorAddr::fromPtr(FnTag), {Data, Size}); 216fe6060f1SDimitry Andric 217fe6060f1SDimitry Andric return ResultF.get().release(); 218fe6060f1SDimitry Andric } 219fe6060f1SDimitry Andric 220fe6060f1SDimitry Andric } // end namespace orc 221fe6060f1SDimitry Andric } // end namespace llvm 222