169 lines · cpp
1//===------ SelfExecutorProcessControl.cpp -- EPC for in-process JITs -----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h"10 11#include "llvm/ExecutionEngine/Orc/Core.h"12#include "llvm/ExecutionEngine/Orc/TargetProcess/DefaultHostBootstrapValues.h"13#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"14#include "llvm/Support/DynamicLibrary.h"15#include "llvm/Support/Process.h"16#include "llvm/TargetParser/Host.h"17 18#define DEBUG_TYPE "orc"19 20namespace llvm::orc {21 22SelfExecutorProcessControl::SelfExecutorProcessControl(23 std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,24 Triple TargetTriple, unsigned PageSize,25 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)26 : ExecutorProcessControl(std::move(SSP), std::move(D)),27 IPMA(TargetTriple.isArch64Bit()) {28 29 OwnedMemMgr = std::move(MemMgr);30 if (!OwnedMemMgr)31 OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>(32 sys::Process::getPageSizeEstimate());33 34 this->TargetTriple = std::move(TargetTriple);35 this->PageSize = PageSize;36 this->MemMgr = OwnedMemMgr.get();37 this->MemAccess = &IPMA;38 this->DylibMgr = this;39 this->JDI = {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager),40 ExecutorAddr::fromPtr(this)};41 42 if (this->TargetTriple.isOSBinFormatMachO())43 GlobalManglingPrefix = '_';44 45 addDefaultBootstrapValuesForHostProcess(BootstrapMap, BootstrapSymbols);46 47#ifdef __APPLE__48 // FIXME: Don't add an UnwindInfoManager by default -- it's redundant when49 // the ORC runtime is loaded. We'll need a way to document this and50 // allow clients to choose.51 if (UnwindInfoManager::TryEnable())52 UnwindInfoManager::addBootstrapSymbols(this->BootstrapSymbols);53#endif // __APPLE__54}55 56Expected<std::unique_ptr<SelfExecutorProcessControl>>57SelfExecutorProcessControl::Create(58 std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,59 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {60 61 if (!SSP)62 SSP = std::make_shared<SymbolStringPool>();63 64 if (!D)65 D = std::make_unique<InPlaceTaskDispatcher>();66 67 auto PageSize = sys::Process::getPageSize();68 if (!PageSize)69 return PageSize.takeError();70 71 Triple TT(sys::getProcessTriple());72 73 return std::make_unique<SelfExecutorProcessControl>(74 std::move(SSP), std::move(D), std::move(TT), *PageSize,75 std::move(MemMgr));76}77 78Expected<tpctypes::DylibHandle>79SelfExecutorProcessControl::loadDylib(const char *DylibPath) {80 std::string ErrMsg;81 auto Dylib = sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg);82 if (!Dylib.isValid())83 return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());84 return ExecutorAddr::fromPtr(Dylib.getOSSpecificHandle());85}86 87void SelfExecutorProcessControl::lookupSymbolsAsync(88 ArrayRef<LookupRequest> Request,89 DylibManager::SymbolLookupCompleteFn Complete) {90 std::vector<tpctypes::LookupResult> R;91 92 for (auto &Elem : Request) {93 sys::DynamicLibrary Dylib(Elem.Handle.toPtr<void *>());94 R.push_back(tpctypes::LookupResult());95 for (auto &KV : Elem.Symbols) {96 auto &Sym = KV.first;97 std::string Tmp((*Sym).data() + !!GlobalManglingPrefix,98 (*Sym).size() - !!GlobalManglingPrefix);99 void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str());100 if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol)101 R.back().emplace_back();102 else103 // FIXME: determine accurate JITSymbolFlags.104 R.back().emplace_back(ExecutorSymbolDef(ExecutorAddr::fromPtr(Addr),105 JITSymbolFlags::Exported));106 }107 }108 109 Complete(std::move(R));110}111 112Expected<int32_t>113SelfExecutorProcessControl::runAsMain(ExecutorAddr MainFnAddr,114 ArrayRef<std::string> Args) {115 using MainTy = int (*)(int, char *[]);116 return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args);117}118 119Expected<int32_t>120SelfExecutorProcessControl::runAsVoidFunction(ExecutorAddr VoidFnAddr) {121 using VoidTy = int (*)();122 return orc::runAsVoidFunction(VoidFnAddr.toPtr<VoidTy>());123}124 125Expected<int32_t>126SelfExecutorProcessControl::runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) {127 using IntTy = int (*)(int);128 return orc::runAsIntFunction(IntFnAddr.toPtr<IntTy>(), Arg);129}130 131void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr,132 IncomingWFRHandler SendResult,133 ArrayRef<char> ArgBuffer) {134 using WrapperFnTy =135 shared::CWrapperFunctionResult (*)(const char *Data, size_t Size);136 auto *WrapperFn = WrapperFnAddr.toPtr<WrapperFnTy>();137 SendResult(WrapperFn(ArgBuffer.data(), ArgBuffer.size()));138}139 140Error SelfExecutorProcessControl::disconnect() {141 D->shutdown();142 return Error::success();143}144 145shared::CWrapperFunctionResult146SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager(147 void *Ctx, const void *FnTag, const char *Data, size_t Size) {148 149 LLVM_DEBUG({150 dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size151 << " byte payload.\n";152 });153 154 std::promise<shared::WrapperFunctionResult> ResultP;155 auto ResultF = ResultP.get_future();156 static_cast<SelfExecutorProcessControl *>(Ctx)157 ->getExecutionSession()158 .runJITDispatchHandler(159 [ResultP = std::move(ResultP)](160 shared::WrapperFunctionResult Result) mutable {161 ResultP.set_value(std::move(Result));162 },163 ExecutorAddr::fromPtr(FnTag), {Data, Size});164 165 return ResultF.get().release();166}167 168} // namespace llvm::orc169