xref: /src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1344a3780SDimitry Andric //===---- ExecutorProcessControl.cpp -- Executor process control APIs -----===//
2344a3780SDimitry Andric //
3344a3780SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4344a3780SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5344a3780SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6344a3780SDimitry Andric //
7344a3780SDimitry Andric //===----------------------------------------------------------------------===//
8344a3780SDimitry Andric 
9344a3780SDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
10344a3780SDimitry Andric 
11344a3780SDimitry Andric #include "llvm/ExecutionEngine/Orc/Core.h"
12b1c73532SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
13b1c73532SDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
14344a3780SDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
15344a3780SDimitry Andric #include "llvm/Support/FormatVariadic.h"
16344a3780SDimitry Andric #include "llvm/Support/Process.h"
177fa27ce4SDimitry Andric #include "llvm/TargetParser/Host.h"
18344a3780SDimitry Andric 
19344a3780SDimitry Andric #define DEBUG_TYPE "orc"
20344a3780SDimitry Andric 
21344a3780SDimitry Andric namespace llvm {
22344a3780SDimitry Andric namespace orc {
23344a3780SDimitry Andric 
24145449b1SDimitry Andric ExecutorProcessControl::MemoryAccess::~MemoryAccess() = default;
25344a3780SDimitry Andric 
26145449b1SDimitry Andric ExecutorProcessControl::~ExecutorProcessControl() = default;
27344a3780SDimitry Andric 
SelfExecutorProcessControl(std::shared_ptr<SymbolStringPool> SSP,std::unique_ptr<TaskDispatcher> D,Triple TargetTriple,unsigned PageSize,std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)28344a3780SDimitry Andric SelfExecutorProcessControl::SelfExecutorProcessControl(
29c0981da4SDimitry Andric     std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,
30c0981da4SDimitry Andric     Triple TargetTriple, unsigned PageSize,
31c0981da4SDimitry Andric     std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)
32b1c73532SDimitry Andric     : ExecutorProcessControl(std::move(SSP), std::move(D)),
33b1c73532SDimitry Andric       InProcessMemoryAccess(TargetTriple.isArch64Bit()) {
34344a3780SDimitry Andric 
35344a3780SDimitry Andric   OwnedMemMgr = std::move(MemMgr);
36344a3780SDimitry Andric   if (!OwnedMemMgr)
37c0981da4SDimitry Andric     OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>(
38c0981da4SDimitry Andric         sys::Process::getPageSizeEstimate());
39344a3780SDimitry Andric 
40344a3780SDimitry Andric   this->TargetTriple = std::move(TargetTriple);
41344a3780SDimitry Andric   this->PageSize = PageSize;
42344a3780SDimitry Andric   this->MemMgr = OwnedMemMgr.get();
43344a3780SDimitry Andric   this->MemAccess = this;
44c0981da4SDimitry Andric   this->JDI = {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager),
45c0981da4SDimitry Andric                ExecutorAddr::fromPtr(this)};
46344a3780SDimitry Andric   if (this->TargetTriple.isOSBinFormatMachO())
47344a3780SDimitry Andric     GlobalManglingPrefix = '_';
48b1c73532SDimitry Andric 
49b1c73532SDimitry Andric   this->BootstrapSymbols[rt::RegisterEHFrameSectionWrapperName] =
50b1c73532SDimitry Andric       ExecutorAddr::fromPtr(&llvm_orc_registerEHFrameSectionWrapper);
51b1c73532SDimitry Andric   this->BootstrapSymbols[rt::DeregisterEHFrameSectionWrapperName] =
52b1c73532SDimitry Andric       ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionWrapper);
53344a3780SDimitry Andric }
54344a3780SDimitry Andric 
55344a3780SDimitry Andric Expected<std::unique_ptr<SelfExecutorProcessControl>>
Create(std::shared_ptr<SymbolStringPool> SSP,std::unique_ptr<TaskDispatcher> D,std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)56344a3780SDimitry Andric SelfExecutorProcessControl::Create(
57344a3780SDimitry Andric     std::shared_ptr<SymbolStringPool> SSP,
58c0981da4SDimitry Andric     std::unique_ptr<TaskDispatcher> D,
59344a3780SDimitry Andric     std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
60344a3780SDimitry Andric 
61344a3780SDimitry Andric   if (!SSP)
62344a3780SDimitry Andric     SSP = std::make_shared<SymbolStringPool>();
63344a3780SDimitry Andric 
64ac9a064cSDimitry Andric   if (!D)
65c0981da4SDimitry Andric     D = std::make_unique<InPlaceTaskDispatcher>();
66c0981da4SDimitry Andric 
67344a3780SDimitry Andric   auto PageSize = sys::Process::getPageSize();
68344a3780SDimitry Andric   if (!PageSize)
69344a3780SDimitry Andric     return PageSize.takeError();
70344a3780SDimitry Andric 
71344a3780SDimitry Andric   Triple TT(sys::getProcessTriple());
72344a3780SDimitry Andric 
73344a3780SDimitry Andric   return std::make_unique<SelfExecutorProcessControl>(
74c0981da4SDimitry Andric       std::move(SSP), std::move(D), std::move(TT), *PageSize,
75c0981da4SDimitry Andric       std::move(MemMgr));
76344a3780SDimitry Andric }
77344a3780SDimitry Andric 
78344a3780SDimitry Andric Expected<tpctypes::DylibHandle>
loadDylib(const char * DylibPath)79344a3780SDimitry Andric SelfExecutorProcessControl::loadDylib(const char *DylibPath) {
80344a3780SDimitry Andric   std::string ErrMsg;
81e3b55780SDimitry Andric   auto Dylib = sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg);
82e3b55780SDimitry Andric   if (!Dylib.isValid())
83344a3780SDimitry Andric     return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
84e3b55780SDimitry Andric   return ExecutorAddr::fromPtr(Dylib.getOSSpecificHandle());
85344a3780SDimitry Andric }
86344a3780SDimitry Andric 
lookupSymbolsAsync(ArrayRef<LookupRequest> Request,ExecutorProcessControl::SymbolLookupCompleteFn Complete)87ac9a064cSDimitry Andric void SelfExecutorProcessControl::lookupSymbolsAsync(
88ac9a064cSDimitry Andric     ArrayRef<LookupRequest> Request,
89ac9a064cSDimitry Andric     ExecutorProcessControl::SymbolLookupCompleteFn Complete) {
90344a3780SDimitry Andric   std::vector<tpctypes::LookupResult> R;
91344a3780SDimitry Andric 
92344a3780SDimitry Andric   for (auto &Elem : Request) {
93e3b55780SDimitry Andric     sys::DynamicLibrary Dylib(Elem.Handle.toPtr<void *>());
94aca2e42cSDimitry Andric     R.push_back(std::vector<ExecutorSymbolDef>());
95344a3780SDimitry Andric     for (auto &KV : Elem.Symbols) {
96344a3780SDimitry Andric       auto &Sym = KV.first;
97344a3780SDimitry Andric       std::string Tmp((*Sym).data() + !!GlobalManglingPrefix,
98344a3780SDimitry Andric                       (*Sym).size() - !!GlobalManglingPrefix);
99e3b55780SDimitry Andric       void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str());
100344a3780SDimitry Andric       if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) {
101344a3780SDimitry Andric         // FIXME: Collect all failing symbols before erroring out.
102344a3780SDimitry Andric         SymbolNameVector MissingSymbols;
103344a3780SDimitry Andric         MissingSymbols.push_back(Sym);
104ac9a064cSDimitry Andric         return Complete(
105ac9a064cSDimitry Andric             make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols)));
106344a3780SDimitry Andric       }
107aca2e42cSDimitry Andric       // FIXME: determine accurate JITSymbolFlags.
108aca2e42cSDimitry Andric       R.back().push_back(
109aca2e42cSDimitry Andric           {ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported});
110344a3780SDimitry Andric     }
111344a3780SDimitry Andric   }
112344a3780SDimitry Andric 
113ac9a064cSDimitry Andric   Complete(std::move(R));
114344a3780SDimitry Andric }
115344a3780SDimitry Andric 
116344a3780SDimitry Andric Expected<int32_t>
runAsMain(ExecutorAddr MainFnAddr,ArrayRef<std::string> Args)117c0981da4SDimitry Andric SelfExecutorProcessControl::runAsMain(ExecutorAddr MainFnAddr,
118344a3780SDimitry Andric                                       ArrayRef<std::string> Args) {
119344a3780SDimitry Andric   using MainTy = int (*)(int, char *[]);
120c0981da4SDimitry Andric   return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args);
121344a3780SDimitry Andric }
122344a3780SDimitry Andric 
123e3b55780SDimitry Andric Expected<int32_t>
runAsVoidFunction(ExecutorAddr VoidFnAddr)124e3b55780SDimitry Andric SelfExecutorProcessControl::runAsVoidFunction(ExecutorAddr VoidFnAddr) {
125e3b55780SDimitry Andric   using VoidTy = int (*)();
126e3b55780SDimitry Andric   return orc::runAsVoidFunction(VoidFnAddr.toPtr<VoidTy>());
127e3b55780SDimitry Andric }
128e3b55780SDimitry Andric 
129e3b55780SDimitry Andric Expected<int32_t>
runAsIntFunction(ExecutorAddr IntFnAddr,int Arg)130e3b55780SDimitry Andric SelfExecutorProcessControl::runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) {
131e3b55780SDimitry Andric   using IntTy = int (*)(int);
132e3b55780SDimitry Andric   return orc::runAsIntFunction(IntFnAddr.toPtr<IntTy>(), Arg);
133e3b55780SDimitry Andric }
134e3b55780SDimitry Andric 
callWrapperAsync(ExecutorAddr WrapperFnAddr,IncomingWFRHandler SendResult,ArrayRef<char> ArgBuffer)135c0981da4SDimitry Andric void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr,
136c0981da4SDimitry Andric                                                   IncomingWFRHandler SendResult,
137344a3780SDimitry Andric                                                   ArrayRef<char> ArgBuffer) {
138344a3780SDimitry Andric   using WrapperFnTy =
139c0981da4SDimitry Andric       shared::CWrapperFunctionResult (*)(const char *Data, size_t Size);
140c0981da4SDimitry Andric   auto *WrapperFn = WrapperFnAddr.toPtr<WrapperFnTy>();
141344a3780SDimitry Andric   SendResult(WrapperFn(ArgBuffer.data(), ArgBuffer.size()));
142344a3780SDimitry Andric }
143344a3780SDimitry Andric 
disconnect()144c0981da4SDimitry Andric Error SelfExecutorProcessControl::disconnect() {
145c0981da4SDimitry Andric   D->shutdown();
146c0981da4SDimitry Andric   return Error::success();
147c0981da4SDimitry Andric }
148344a3780SDimitry Andric 
writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,WriteResultFn OnWriteComplete)149b1c73532SDimitry Andric void InProcessMemoryAccess::writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
150b1c73532SDimitry Andric                                              WriteResultFn OnWriteComplete) {
151344a3780SDimitry Andric   for (auto &W : Ws)
152c0981da4SDimitry Andric     *W.Addr.toPtr<uint8_t *>() = W.Value;
153344a3780SDimitry Andric   OnWriteComplete(Error::success());
154344a3780SDimitry Andric }
155344a3780SDimitry Andric 
writeUInt16sAsync(ArrayRef<tpctypes::UInt16Write> Ws,WriteResultFn OnWriteComplete)156b1c73532SDimitry Andric void InProcessMemoryAccess::writeUInt16sAsync(
157344a3780SDimitry Andric     ArrayRef<tpctypes::UInt16Write> Ws, WriteResultFn OnWriteComplete) {
158344a3780SDimitry Andric   for (auto &W : Ws)
159c0981da4SDimitry Andric     *W.Addr.toPtr<uint16_t *>() = W.Value;
160344a3780SDimitry Andric   OnWriteComplete(Error::success());
161344a3780SDimitry Andric }
162344a3780SDimitry Andric 
writeUInt32sAsync(ArrayRef<tpctypes::UInt32Write> Ws,WriteResultFn OnWriteComplete)163b1c73532SDimitry Andric void InProcessMemoryAccess::writeUInt32sAsync(
164344a3780SDimitry Andric     ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) {
165344a3780SDimitry Andric   for (auto &W : Ws)
166c0981da4SDimitry Andric     *W.Addr.toPtr<uint32_t *>() = W.Value;
167344a3780SDimitry Andric   OnWriteComplete(Error::success());
168344a3780SDimitry Andric }
169344a3780SDimitry Andric 
writeUInt64sAsync(ArrayRef<tpctypes::UInt64Write> Ws,WriteResultFn OnWriteComplete)170b1c73532SDimitry Andric void InProcessMemoryAccess::writeUInt64sAsync(
171344a3780SDimitry Andric     ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) {
172344a3780SDimitry Andric   for (auto &W : Ws)
173c0981da4SDimitry Andric     *W.Addr.toPtr<uint64_t *>() = W.Value;
174344a3780SDimitry Andric   OnWriteComplete(Error::success());
175344a3780SDimitry Andric }
176344a3780SDimitry Andric 
writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws,WriteResultFn OnWriteComplete)177b1c73532SDimitry Andric void InProcessMemoryAccess::writeBuffersAsync(
178344a3780SDimitry Andric     ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) {
179344a3780SDimitry Andric   for (auto &W : Ws)
180c0981da4SDimitry Andric     memcpy(W.Addr.toPtr<char *>(), W.Buffer.data(), W.Buffer.size());
181344a3780SDimitry Andric   OnWriteComplete(Error::success());
182344a3780SDimitry Andric }
183344a3780SDimitry Andric 
writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws,WriteResultFn OnWriteComplete)184b1c73532SDimitry Andric void InProcessMemoryAccess::writePointersAsync(
185b1c73532SDimitry Andric     ArrayRef<tpctypes::PointerWrite> Ws, WriteResultFn OnWriteComplete) {
186b1c73532SDimitry Andric   if (IsArch64Bit) {
187b1c73532SDimitry Andric     for (auto &W : Ws)
188b1c73532SDimitry Andric       *W.Addr.toPtr<uint64_t *>() = W.Value.getValue();
189b1c73532SDimitry Andric   } else {
190b1c73532SDimitry Andric     for (auto &W : Ws)
191b1c73532SDimitry Andric       *W.Addr.toPtr<uint32_t *>() = static_cast<uint32_t>(W.Value.getValue());
192b1c73532SDimitry Andric   }
193b1c73532SDimitry Andric 
194b1c73532SDimitry Andric   OnWriteComplete(Error::success());
195b1c73532SDimitry Andric }
196b1c73532SDimitry Andric 
197c0981da4SDimitry Andric shared::CWrapperFunctionResult
jitDispatchViaWrapperFunctionManager(void * Ctx,const void * FnTag,const char * Data,size_t Size)198344a3780SDimitry Andric SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager(
199344a3780SDimitry Andric     void *Ctx, const void *FnTag, const char *Data, size_t Size) {
200344a3780SDimitry Andric 
201344a3780SDimitry Andric   LLVM_DEBUG({
202344a3780SDimitry Andric     dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size
203344a3780SDimitry Andric            << " byte payload.\n";
204344a3780SDimitry Andric   });
205344a3780SDimitry Andric 
206344a3780SDimitry Andric   std::promise<shared::WrapperFunctionResult> ResultP;
207344a3780SDimitry Andric   auto ResultF = ResultP.get_future();
208344a3780SDimitry Andric   static_cast<SelfExecutorProcessControl *>(Ctx)
209344a3780SDimitry Andric       ->getExecutionSession()
210344a3780SDimitry Andric       .runJITDispatchHandler(
211344a3780SDimitry Andric           [ResultP = std::move(ResultP)](
212344a3780SDimitry Andric               shared::WrapperFunctionResult Result) mutable {
213344a3780SDimitry Andric             ResultP.set_value(std::move(Result));
214344a3780SDimitry Andric           },
2157fa27ce4SDimitry Andric           ExecutorAddr::fromPtr(FnTag), {Data, Size});
216344a3780SDimitry Andric 
217344a3780SDimitry Andric   return ResultF.get().release();
218344a3780SDimitry Andric }
219344a3780SDimitry Andric 
220344a3780SDimitry Andric } // end namespace orc
221344a3780SDimitry Andric } // end namespace llvm
222