1*5f7ddb14SDimitry Andric //===---- ExecutorProcessControl.cpp -- Executor process control APIs -----===//
2*5f7ddb14SDimitry Andric //
3*5f7ddb14SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5f7ddb14SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*5f7ddb14SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5f7ddb14SDimitry Andric //
7*5f7ddb14SDimitry Andric //===----------------------------------------------------------------------===//
8*5f7ddb14SDimitry Andric
9*5f7ddb14SDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
10*5f7ddb14SDimitry Andric
11*5f7ddb14SDimitry Andric #include "llvm/ExecutionEngine/Orc/Core.h"
12*5f7ddb14SDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
13*5f7ddb14SDimitry Andric #include "llvm/Support/FormatVariadic.h"
14*5f7ddb14SDimitry Andric #include "llvm/Support/Host.h"
15*5f7ddb14SDimitry Andric #include "llvm/Support/Process.h"
16*5f7ddb14SDimitry Andric
17*5f7ddb14SDimitry Andric #define DEBUG_TYPE "orc"
18*5f7ddb14SDimitry Andric
19*5f7ddb14SDimitry Andric namespace llvm {
20*5f7ddb14SDimitry Andric namespace orc {
21*5f7ddb14SDimitry Andric
~MemoryAccess()22*5f7ddb14SDimitry Andric ExecutorProcessControl::MemoryAccess::~MemoryAccess() {}
23*5f7ddb14SDimitry Andric
~ExecutorProcessControl()24*5f7ddb14SDimitry Andric ExecutorProcessControl::~ExecutorProcessControl() {}
25*5f7ddb14SDimitry Andric
SelfExecutorProcessControl(std::shared_ptr<SymbolStringPool> SSP,Triple TargetTriple,unsigned PageSize,std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)26*5f7ddb14SDimitry Andric SelfExecutorProcessControl::SelfExecutorProcessControl(
27*5f7ddb14SDimitry Andric std::shared_ptr<SymbolStringPool> SSP, Triple TargetTriple,
28*5f7ddb14SDimitry Andric unsigned PageSize, std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)
29*5f7ddb14SDimitry Andric : ExecutorProcessControl(std::move(SSP)) {
30*5f7ddb14SDimitry Andric
31*5f7ddb14SDimitry Andric OwnedMemMgr = std::move(MemMgr);
32*5f7ddb14SDimitry Andric if (!OwnedMemMgr)
33*5f7ddb14SDimitry Andric OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>();
34*5f7ddb14SDimitry Andric
35*5f7ddb14SDimitry Andric this->TargetTriple = std::move(TargetTriple);
36*5f7ddb14SDimitry Andric this->PageSize = PageSize;
37*5f7ddb14SDimitry Andric this->MemMgr = OwnedMemMgr.get();
38*5f7ddb14SDimitry Andric this->MemAccess = this;
39*5f7ddb14SDimitry Andric this->JDI = {ExecutorAddress::fromPtr(jitDispatchViaWrapperFunctionManager),
40*5f7ddb14SDimitry Andric ExecutorAddress::fromPtr(this)};
41*5f7ddb14SDimitry Andric if (this->TargetTriple.isOSBinFormatMachO())
42*5f7ddb14SDimitry Andric GlobalManglingPrefix = '_';
43*5f7ddb14SDimitry Andric }
44*5f7ddb14SDimitry Andric
45*5f7ddb14SDimitry Andric Expected<std::unique_ptr<SelfExecutorProcessControl>>
Create(std::shared_ptr<SymbolStringPool> SSP,std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)46*5f7ddb14SDimitry Andric SelfExecutorProcessControl::Create(
47*5f7ddb14SDimitry Andric std::shared_ptr<SymbolStringPool> SSP,
48*5f7ddb14SDimitry Andric std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
49*5f7ddb14SDimitry Andric
50*5f7ddb14SDimitry Andric if (!SSP)
51*5f7ddb14SDimitry Andric SSP = std::make_shared<SymbolStringPool>();
52*5f7ddb14SDimitry Andric
53*5f7ddb14SDimitry Andric auto PageSize = sys::Process::getPageSize();
54*5f7ddb14SDimitry Andric if (!PageSize)
55*5f7ddb14SDimitry Andric return PageSize.takeError();
56*5f7ddb14SDimitry Andric
57*5f7ddb14SDimitry Andric Triple TT(sys::getProcessTriple());
58*5f7ddb14SDimitry Andric
59*5f7ddb14SDimitry Andric return std::make_unique<SelfExecutorProcessControl>(
60*5f7ddb14SDimitry Andric std::move(SSP), std::move(TT), *PageSize, std::move(MemMgr));
61*5f7ddb14SDimitry Andric }
62*5f7ddb14SDimitry Andric
63*5f7ddb14SDimitry Andric Expected<tpctypes::DylibHandle>
loadDylib(const char * DylibPath)64*5f7ddb14SDimitry Andric SelfExecutorProcessControl::loadDylib(const char *DylibPath) {
65*5f7ddb14SDimitry Andric std::string ErrMsg;
66*5f7ddb14SDimitry Andric auto Dylib = std::make_unique<sys::DynamicLibrary>(
67*5f7ddb14SDimitry Andric sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg));
68*5f7ddb14SDimitry Andric if (!Dylib->isValid())
69*5f7ddb14SDimitry Andric return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
70*5f7ddb14SDimitry Andric DynamicLibraries.push_back(std::move(Dylib));
71*5f7ddb14SDimitry Andric return pointerToJITTargetAddress(DynamicLibraries.back().get());
72*5f7ddb14SDimitry Andric }
73*5f7ddb14SDimitry Andric
74*5f7ddb14SDimitry Andric Expected<std::vector<tpctypes::LookupResult>>
lookupSymbols(ArrayRef<LookupRequest> Request)75*5f7ddb14SDimitry Andric SelfExecutorProcessControl::lookupSymbols(ArrayRef<LookupRequest> Request) {
76*5f7ddb14SDimitry Andric std::vector<tpctypes::LookupResult> R;
77*5f7ddb14SDimitry Andric
78*5f7ddb14SDimitry Andric for (auto &Elem : Request) {
79*5f7ddb14SDimitry Andric auto *Dylib = jitTargetAddressToPointer<sys::DynamicLibrary *>(Elem.Handle);
80*5f7ddb14SDimitry Andric assert(llvm::any_of(DynamicLibraries,
81*5f7ddb14SDimitry Andric [=](const std::unique_ptr<sys::DynamicLibrary> &DL) {
82*5f7ddb14SDimitry Andric return DL.get() == Dylib;
83*5f7ddb14SDimitry Andric }) &&
84*5f7ddb14SDimitry Andric "Invalid handle");
85*5f7ddb14SDimitry Andric
86*5f7ddb14SDimitry Andric R.push_back(std::vector<JITTargetAddress>());
87*5f7ddb14SDimitry Andric for (auto &KV : Elem.Symbols) {
88*5f7ddb14SDimitry Andric auto &Sym = KV.first;
89*5f7ddb14SDimitry Andric std::string Tmp((*Sym).data() + !!GlobalManglingPrefix,
90*5f7ddb14SDimitry Andric (*Sym).size() - !!GlobalManglingPrefix);
91*5f7ddb14SDimitry Andric void *Addr = Dylib->getAddressOfSymbol(Tmp.c_str());
92*5f7ddb14SDimitry Andric if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) {
93*5f7ddb14SDimitry Andric // FIXME: Collect all failing symbols before erroring out.
94*5f7ddb14SDimitry Andric SymbolNameVector MissingSymbols;
95*5f7ddb14SDimitry Andric MissingSymbols.push_back(Sym);
96*5f7ddb14SDimitry Andric return make_error<SymbolsNotFound>(std::move(MissingSymbols));
97*5f7ddb14SDimitry Andric }
98*5f7ddb14SDimitry Andric R.back().push_back(pointerToJITTargetAddress(Addr));
99*5f7ddb14SDimitry Andric }
100*5f7ddb14SDimitry Andric }
101*5f7ddb14SDimitry Andric
102*5f7ddb14SDimitry Andric return R;
103*5f7ddb14SDimitry Andric }
104*5f7ddb14SDimitry Andric
105*5f7ddb14SDimitry Andric Expected<int32_t>
runAsMain(JITTargetAddress MainFnAddr,ArrayRef<std::string> Args)106*5f7ddb14SDimitry Andric SelfExecutorProcessControl::runAsMain(JITTargetAddress MainFnAddr,
107*5f7ddb14SDimitry Andric ArrayRef<std::string> Args) {
108*5f7ddb14SDimitry Andric using MainTy = int (*)(int, char *[]);
109*5f7ddb14SDimitry Andric return orc::runAsMain(jitTargetAddressToFunction<MainTy>(MainFnAddr), Args);
110*5f7ddb14SDimitry Andric }
111*5f7ddb14SDimitry Andric
callWrapperAsync(SendResultFunction SendResult,JITTargetAddress WrapperFnAddr,ArrayRef<char> ArgBuffer)112*5f7ddb14SDimitry Andric void SelfExecutorProcessControl::callWrapperAsync(
113*5f7ddb14SDimitry Andric SendResultFunction SendResult, JITTargetAddress WrapperFnAddr,
114*5f7ddb14SDimitry Andric ArrayRef<char> ArgBuffer) {
115*5f7ddb14SDimitry Andric using WrapperFnTy =
116*5f7ddb14SDimitry Andric shared::detail::CWrapperFunctionResult (*)(const char *Data, size_t Size);
117*5f7ddb14SDimitry Andric auto *WrapperFn = jitTargetAddressToFunction<WrapperFnTy>(WrapperFnAddr);
118*5f7ddb14SDimitry Andric SendResult(WrapperFn(ArgBuffer.data(), ArgBuffer.size()));
119*5f7ddb14SDimitry Andric }
120*5f7ddb14SDimitry Andric
disconnect()121*5f7ddb14SDimitry Andric Error SelfExecutorProcessControl::disconnect() { return Error::success(); }
122*5f7ddb14SDimitry Andric
writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws,WriteResultFn OnWriteComplete)123*5f7ddb14SDimitry Andric void SelfExecutorProcessControl::writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws,
124*5f7ddb14SDimitry Andric WriteResultFn OnWriteComplete) {
125*5f7ddb14SDimitry Andric for (auto &W : Ws)
126*5f7ddb14SDimitry Andric *jitTargetAddressToPointer<uint8_t *>(W.Address) = W.Value;
127*5f7ddb14SDimitry Andric OnWriteComplete(Error::success());
128*5f7ddb14SDimitry Andric }
129*5f7ddb14SDimitry Andric
writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws,WriteResultFn OnWriteComplete)130*5f7ddb14SDimitry Andric void SelfExecutorProcessControl::writeUInt16s(
131*5f7ddb14SDimitry Andric ArrayRef<tpctypes::UInt16Write> Ws, WriteResultFn OnWriteComplete) {
132*5f7ddb14SDimitry Andric for (auto &W : Ws)
133*5f7ddb14SDimitry Andric *jitTargetAddressToPointer<uint16_t *>(W.Address) = W.Value;
134*5f7ddb14SDimitry Andric OnWriteComplete(Error::success());
135*5f7ddb14SDimitry Andric }
136*5f7ddb14SDimitry Andric
writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws,WriteResultFn OnWriteComplete)137*5f7ddb14SDimitry Andric void SelfExecutorProcessControl::writeUInt32s(
138*5f7ddb14SDimitry Andric ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) {
139*5f7ddb14SDimitry Andric for (auto &W : Ws)
140*5f7ddb14SDimitry Andric *jitTargetAddressToPointer<uint32_t *>(W.Address) = W.Value;
141*5f7ddb14SDimitry Andric OnWriteComplete(Error::success());
142*5f7ddb14SDimitry Andric }
143*5f7ddb14SDimitry Andric
writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws,WriteResultFn OnWriteComplete)144*5f7ddb14SDimitry Andric void SelfExecutorProcessControl::writeUInt64s(
145*5f7ddb14SDimitry Andric ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) {
146*5f7ddb14SDimitry Andric for (auto &W : Ws)
147*5f7ddb14SDimitry Andric *jitTargetAddressToPointer<uint64_t *>(W.Address) = W.Value;
148*5f7ddb14SDimitry Andric OnWriteComplete(Error::success());
149*5f7ddb14SDimitry Andric }
150*5f7ddb14SDimitry Andric
writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws,WriteResultFn OnWriteComplete)151*5f7ddb14SDimitry Andric void SelfExecutorProcessControl::writeBuffers(
152*5f7ddb14SDimitry Andric ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) {
153*5f7ddb14SDimitry Andric for (auto &W : Ws)
154*5f7ddb14SDimitry Andric memcpy(jitTargetAddressToPointer<char *>(W.Address), W.Buffer.data(),
155*5f7ddb14SDimitry Andric W.Buffer.size());
156*5f7ddb14SDimitry Andric OnWriteComplete(Error::success());
157*5f7ddb14SDimitry Andric }
158*5f7ddb14SDimitry Andric
159*5f7ddb14SDimitry Andric shared::detail::CWrapperFunctionResult
jitDispatchViaWrapperFunctionManager(void * Ctx,const void * FnTag,const char * Data,size_t Size)160*5f7ddb14SDimitry Andric SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager(
161*5f7ddb14SDimitry Andric void *Ctx, const void *FnTag, const char *Data, size_t Size) {
162*5f7ddb14SDimitry Andric
163*5f7ddb14SDimitry Andric LLVM_DEBUG({
164*5f7ddb14SDimitry Andric dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size
165*5f7ddb14SDimitry Andric << " byte payload.\n";
166*5f7ddb14SDimitry Andric });
167*5f7ddb14SDimitry Andric
168*5f7ddb14SDimitry Andric std::promise<shared::WrapperFunctionResult> ResultP;
169*5f7ddb14SDimitry Andric auto ResultF = ResultP.get_future();
170*5f7ddb14SDimitry Andric static_cast<SelfExecutorProcessControl *>(Ctx)
171*5f7ddb14SDimitry Andric ->getExecutionSession()
172*5f7ddb14SDimitry Andric .runJITDispatchHandler(
173*5f7ddb14SDimitry Andric [ResultP = std::move(ResultP)](
174*5f7ddb14SDimitry Andric shared::WrapperFunctionResult Result) mutable {
175*5f7ddb14SDimitry Andric ResultP.set_value(std::move(Result));
176*5f7ddb14SDimitry Andric },
177*5f7ddb14SDimitry Andric pointerToJITTargetAddress(FnTag), {Data, Size});
178*5f7ddb14SDimitry Andric
179*5f7ddb14SDimitry Andric return ResultF.get().release();
180*5f7ddb14SDimitry Andric }
181*5f7ddb14SDimitry Andric
182*5f7ddb14SDimitry Andric } // end namespace orc
183*5f7ddb14SDimitry Andric } // end namespace llvm
184