| //===------ SelfExecutorProcessControl.cpp -- EPC for in-process JITs -----===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h" | |
| #include "llvm/ExecutionEngine/Orc/Shared/Mangler.h" | |
| #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" | |
| #include "llvm/ExecutionEngine/Orc/Core.h" | |
| #include "llvm/ExecutionEngine/Orc/DylibManager.h" | |
| #include "llvm/ExecutionEngine/Orc/InProcessMemoryAccess.h" | |
| #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" | |
| #include "llvm/ExecutionEngine/Orc/TargetProcess/DefaultHostBootstrapValues.h" | |
| #include "llvm/ExecutionEngine/Orc/TargetProcess/OrcRTBootstrap.h" | |
| #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h" | |
| #include "llvm/Support/DynamicLibrary.h" | |
| #include "llvm/Support/Process.h" | |
| #include "llvm/TargetParser/Host.h" | |
| #define DEBUG_TYPE "orc" | |
| namespace llvm::orc { | |
| class SelfExecutorProcessControl::InProcessDylibManager : public DylibManager { | |
| public: | |
| InProcessDylibManager(char GlobalManglingPrefix); | |
| Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override; | |
| void | |
| lookupSymbolsAsync(tpctypes::DylibHandle H, const SymbolLookupSet &Symbols, | |
| DylibManager::SymbolLookupCompleteFn Complete) override; | |
| private: | |
| char GlobalManglingPrefix; | |
| }; | |
| SelfExecutorProcessControl::SelfExecutorProcessControl( | |
| std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D, | |
| Triple TargetTriple, unsigned PageSize) | |
| : ExecutorProcessControl(std::move(SSP), std::move(D)) { | |
| this->TargetTriple = std::move(TargetTriple); | |
| this->PageSize = PageSize; | |
| addDefaultBootstrapValuesForHostProcess(BootstrapMap, BootstrapSymbols); | |
| rt_bootstrap::addRunAsFunctionWrappersTo(BootstrapSymbols); | |
| Mangler Mangle(getTargetTriple()); | |
| BootstrapSymbols[Mangle.mangledCopy(rt::DispatchName)] = | |
| ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager); | |
| BootstrapSymbols[Mangle.mangledCopy(rt::DispatchCtxName)] = | |
| ExecutorAddr::fromPtr(this); | |
| #ifdef __APPLE__ | |
| // FIXME: Don't add an UnwindInfoManager by default -- it's redundant when | |
| // the ORC runtime is loaded. We'll need a way to document this and | |
| // allow clients to choose. | |
| if (UnwindInfoManager::TryEnable()) | |
| UnwindInfoManager::addBootstrapSymbols(this->BootstrapSymbols); | |
| #endif // __APPLE__ | |
| } | |
| Expected<std::unique_ptr<SelfExecutorProcessControl>> | |
| SelfExecutorProcessControl::Create(std::shared_ptr<SymbolStringPool> SSP, | |
| std::unique_ptr<TaskDispatcher> D) { | |
| if (!SSP) | |
| SSP = std::make_shared<SymbolStringPool>(); | |
| if (!D) | |
| D = std::make_unique<InPlaceTaskDispatcher>(); | |
| auto PageSize = sys::Process::getPageSize(); | |
| if (!PageSize) | |
| return PageSize.takeError(); | |
| Triple TT(sys::getProcessTriple()); | |
| return std::make_unique<SelfExecutorProcessControl>( | |
| std::move(SSP), std::move(D), std::move(TT), *PageSize); | |
| } | |
| Expected<int32_t> | |
| SelfExecutorProcessControl::runAsMain(ExecutorAddr MainFnAddr, | |
| ArrayRef<std::string> Args) { | |
| using MainTy = int (*)(int, char *[]); | |
| return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args); | |
| } | |
| void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr, | |
| IncomingWFRHandler SendResult, | |
| ArrayRef<char> ArgBuffer) { | |
| using WrapperFnTy = | |
| shared::CWrapperFunctionBuffer (*)(const char *Data, size_t Size); | |
| auto *WrapperFn = WrapperFnAddr.toPtr<WrapperFnTy>(); | |
| SendResult(shared::WrapperFunctionBuffer( | |
| WrapperFn(ArgBuffer.data(), ArgBuffer.size()))); | |
| } | |
| Error SelfExecutorProcessControl::disconnect() { | |
| D->shutdown(); | |
| return Error::success(); | |
| } | |
| Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>> | |
| SelfExecutorProcessControl::createDefaultMemoryManager() { | |
| return std::make_unique<jitlink::InProcessMemoryManager>( | |
| sys::Process::getPageSizeEstimate()); | |
| } | |
| Expected<std::unique_ptr<DylibManager>> | |
| SelfExecutorProcessControl::createDefaultDylibMgr() { | |
| char Prefix = TargetTriple.isOSBinFormatMachO() ? '_' : '\0'; | |
| return std::make_unique<InProcessDylibManager>(Prefix); | |
| } | |
| Expected<std::unique_ptr<MemoryAccess>> | |
| SelfExecutorProcessControl::createDefaultMemoryAccess() { | |
| return std::make_unique<InProcessMemoryAccess>(TargetTriple.isArch64Bit()); | |
| } | |
| shared::CWrapperFunctionBuffer | |
| SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager( | |
| void *Ctx, const void *FnTag, const char *Data, size_t Size) { | |
| LLVM_DEBUG({ | |
| dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size | |
| << " byte payload.\n"; | |
| }); | |
| std::promise<shared::WrapperFunctionBuffer> ResultP; | |
| auto ResultF = ResultP.get_future(); | |
| static_cast<SelfExecutorProcessControl *>(Ctx) | |
| ->getExecutionSession() | |
| .runJITDispatchHandler( | |
| [ResultP = std::move(ResultP)]( | |
| shared::WrapperFunctionBuffer Result) mutable { | |
| ResultP.set_value(std::move(Result)); | |
| }, | |
| ExecutorAddr::fromPtr(FnTag), | |
| shared::WrapperFunctionBuffer::copyFrom(Data, Size)); | |
| return ResultF.get().release(); | |
| } | |
| SelfExecutorProcessControl::InProcessDylibManager::InProcessDylibManager( | |
| char GlobalManglingPrefix) | |
| : GlobalManglingPrefix(GlobalManglingPrefix) {} | |
| Expected<tpctypes::DylibHandle> | |
| SelfExecutorProcessControl::InProcessDylibManager::loadDylib( | |
| const char *DylibPath) { | |
| std::string ErrMsg; | |
| auto Dylib = sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg); | |
| if (!Dylib.isValid()) | |
| return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); | |
| return ExecutorAddr::fromPtr(Dylib.getOSSpecificHandle()); | |
| } | |
| void SelfExecutorProcessControl::InProcessDylibManager::lookupSymbolsAsync( | |
| tpctypes::DylibHandle H, const SymbolLookupSet &Symbols, | |
| DylibManager::SymbolLookupCompleteFn Complete) { | |
| tpctypes::LookupResult R; | |
| sys::DynamicLibrary Dylib(H.toPtr<void *>()); | |
| for (auto &KV : Symbols) { | |
| auto &Sym = KV.first; | |
| std::string Tmp((*Sym).data() + !!GlobalManglingPrefix, | |
| (*Sym).size() - !!GlobalManglingPrefix); | |
| void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str()); | |
| if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) | |
| R.emplace_back(); | |
| else | |
| R.emplace_back(ExecutorAddr::fromPtr(Addr)); | |
| } | |
| Complete(std::move(R)); | |
| } | |
| } // namespace llvm::orc |