LLVM  16.0.0git
ExecutorProcessControl.cpp
Go to the documentation of this file.
1 //===---- ExecutorProcessControl.cpp -- Executor process control APIs -----===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 
14 #include "llvm/Support/Host.h"
15 #include "llvm/Support/Process.h"
16 
17 #define DEBUG_TYPE "orc"
18 
19 namespace llvm {
20 namespace orc {
21 
23 
25 
27  std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,
28  Triple TargetTriple, unsigned PageSize,
29  std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)
30  : ExecutorProcessControl(std::move(SSP), std::move(D)) {
31 
32  OwnedMemMgr = std::move(MemMgr);
33  if (!OwnedMemMgr)
34  OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>(
36 
37  this->TargetTriple = std::move(TargetTriple);
38  this->PageSize = PageSize;
39  this->MemMgr = OwnedMemMgr.get();
40  this->MemAccess = this;
41  this->JDI = {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager),
42  ExecutorAddr::fromPtr(this)};
43  if (this->TargetTriple.isOSBinFormatMachO())
44  GlobalManglingPrefix = '_';
45 }
46 
49  std::shared_ptr<SymbolStringPool> SSP,
50  std::unique_ptr<TaskDispatcher> D,
51  std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
52 
53  if (!SSP)
54  SSP = std::make_shared<SymbolStringPool>();
55 
56  if (!D) {
57 #if LLVM_ENABLE_THREADS
58  D = std::make_unique<DynamicThreadPoolTaskDispatcher>();
59 #else
60  D = std::make_unique<InPlaceTaskDispatcher>();
61 #endif
62  }
63 
65  if (!PageSize)
66  return PageSize.takeError();
67 
69 
70  return std::make_unique<SelfExecutorProcessControl>(
72  std::move(MemMgr));
73 }
74 
76 SelfExecutorProcessControl::loadDylib(const char *DylibPath) {
77  std::string ErrMsg;
78  auto Dylib = sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg);
79  if (!Dylib.isValid())
80  return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
81  return ExecutorAddr::fromPtr(Dylib.getOSSpecificHandle());
82 }
83 
86  std::vector<tpctypes::LookupResult> R;
87 
88  for (auto &Elem : Request) {
89  sys::DynamicLibrary Dylib(Elem.Handle.toPtr<void *>());
90  R.push_back(std::vector<ExecutorAddr>());
91  for (auto &KV : Elem.Symbols) {
92  auto &Sym = KV.first;
93  std::string Tmp((*Sym).data() + !!GlobalManglingPrefix,
94  (*Sym).size() - !!GlobalManglingPrefix);
95  void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str());
96  if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) {
97  // FIXME: Collect all failing symbols before erroring out.
98  SymbolNameVector MissingSymbols;
99  MissingSymbols.push_back(Sym);
100  return make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols));
101  }
102  R.back().push_back(ExecutorAddr::fromPtr(Addr));
103  }
104  }
105 
106  return R;
107 }
108 
112  using MainTy = int (*)(int, char *[]);
113  return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args);
114 }
115 
118  using VoidTy = int (*)();
119  return orc::runAsVoidFunction(VoidFnAddr.toPtr<VoidTy>());
120 }
121 
124  using IntTy = int (*)(int);
125  return orc::runAsIntFunction(IntFnAddr.toPtr<IntTy>(), Arg);
126 }
127 
129  IncomingWFRHandler SendResult,
130  ArrayRef<char> ArgBuffer) {
131  using WrapperFnTy =
132  shared::CWrapperFunctionResult (*)(const char *Data, size_t Size);
133  auto *WrapperFn = WrapperFnAddr.toPtr<WrapperFnTy>();
134  SendResult(WrapperFn(ArgBuffer.data(), ArgBuffer.size()));
135 }
136 
138  D->shutdown();
139  return Error::success();
140 }
141 
142 void SelfExecutorProcessControl::writeUInt8sAsync(
143  ArrayRef<tpctypes::UInt8Write> Ws, WriteResultFn OnWriteComplete) {
144  for (auto &W : Ws)
145  *W.Addr.toPtr<uint8_t *>() = W.Value;
146  OnWriteComplete(Error::success());
147 }
148 
149 void SelfExecutorProcessControl::writeUInt16sAsync(
150  ArrayRef<tpctypes::UInt16Write> Ws, WriteResultFn OnWriteComplete) {
151  for (auto &W : Ws)
152  *W.Addr.toPtr<uint16_t *>() = W.Value;
153  OnWriteComplete(Error::success());
154 }
155 
156 void SelfExecutorProcessControl::writeUInt32sAsync(
157  ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) {
158  for (auto &W : Ws)
159  *W.Addr.toPtr<uint32_t *>() = W.Value;
160  OnWriteComplete(Error::success());
161 }
162 
163 void SelfExecutorProcessControl::writeUInt64sAsync(
164  ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) {
165  for (auto &W : Ws)
166  *W.Addr.toPtr<uint64_t *>() = W.Value;
167  OnWriteComplete(Error::success());
168 }
169 
170 void SelfExecutorProcessControl::writeBuffersAsync(
171  ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) {
172  for (auto &W : Ws)
173  memcpy(W.Addr.toPtr<char *>(), W.Buffer.data(), W.Buffer.size());
174  OnWriteComplete(Error::success());
175 }
176 
177 shared::CWrapperFunctionResult
178 SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager(
179  void *Ctx, const void *FnTag, const char *Data, size_t Size) {
180 
181  LLVM_DEBUG({
182  dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size
183  << " byte payload.\n";
184  });
185 
186  std::promise<shared::WrapperFunctionResult> ResultP;
187  auto ResultF = ResultP.get_future();
188  static_cast<SelfExecutorProcessControl *>(Ctx)
191  [ResultP = std::move(ResultP)](
192  shared::WrapperFunctionResult Result) mutable {
193  ResultP.set_value(std::move(Result));
194  },
195  pointerToJITTargetAddress(FnTag), {Data, Size});
196 
197  return ResultF.get().release();
198 }
199 
200 } // end namespace orc
201 } // end namespace llvm
llvm::Check::Size
@ Size
Definition: FileCheck.h:77
llvm::orc::ExecutorAddr
Represents an address in the executor process.
Definition: ExecutorAddress.h:31
llvm::orc::ExecutorProcessControl::MemMgr
jitlink::JITLinkMemoryManager * MemMgr
Definition: ExecutorProcessControl.h:374
llvm::orc::ExecutorAddr::fromPtr
static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap=UnwrapFn())
Create an ExecutorAddr from the given pointer.
Definition: ExecutorAddress.h:80
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::orc::shared::CWrapperFunctionResult
Definition: WrapperFunctionUtils.h:33
llvm::orc::ExecutorProcessControl::MemoryAccess::~MemoryAccess
virtual ~MemoryAccess()
llvm::sys::DynamicLibrary::getAddressOfSymbol
void * getAddressOfSymbol(const char *symbolName)
Searches through the library for the symbol symbolName.
Definition: DynamicLibrary.cpp:212
Host.h
llvm::RISCVFenceField::W
@ W
Definition: RISCVBaseInfo.h:266
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::orc::ExecutorProcessControl::TargetTriple
Triple TargetTriple
Definition: ExecutorProcessControl.h:370
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
llvm::orc::SelfExecutorProcessControl::disconnect
Error disconnect() override
Disconnect from the target process.
Definition: ExecutorProcessControl.cpp:137
llvm::orc::ExecutorProcessControl::getExecutionSession
ExecutionSession & getExecutionSession()
Return the ExecutionSession associated with this instance.
Definition: ExecutorProcessControl.h:187
llvm::orc::ExecutorProcessControl
ExecutorProcessControl supports interaction with a JIT target process.
Definition: ExecutorProcessControl.h:38
llvm::orc::ExecutorProcessControl::SSP
std::shared_ptr< SymbolStringPool > SSP
Definition: ExecutorProcessControl.h:367
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::orc::ExecutionSession::runJITDispatchHandler
void runJITDispatchHandler(SendResultFunction SendResult, JITTargetAddress HandlerFnTagAddr, ArrayRef< char > ArgBuffer)
Run a registered jit-side wrapper function.
Definition: Core.cpp:2216
llvm::ArrayRef::data
const T * data() const
Definition: ArrayRef.h:161
llvm::sys::DynamicLibrary
This class provides a portable interface to dynamic libraries which also might be known as shared lib...
Definition: DynamicLibrary.h:33
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
Arg
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Definition: AMDGPULibCalls.cpp:187
Process.h
PageSize
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)
llvm::orc::ExecutorAddr::toPtr
std::enable_if_t< std::is_pointer< T >::value, T > toPtr(WrapFn &&Wrap=WrapFn()) const
Cast this ExecutorAddr to a pointer of the given type.
Definition: ExecutorAddress.h:89
llvm::sys::DynamicLibrary::getPermanentLibrary
static DynamicLibrary getPermanentLibrary(const char *filename, std::string *errMsg=nullptr)
This function permanently loads the dynamic library at the given path using the library load operatio...
Definition: DynamicLibrary.cpp:165
int
Clang compiles this i1 i64 store i64 i64 store i64 i64 store i64 i64 store i64 align Which gets codegen d xmm0 movaps rbp movaps rbp movaps rbp movaps rbp rbp rbp rbp rbp It would be better to have movq s of instead of the movaps s LLVM produces ret int
Definition: README.txt:536
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::Triple::isOSBinFormatMachO
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
Definition: Triple.h:686
llvm::orc::runAsMain
int runAsMain(int(*Main)(int, char *[]), ArrayRef< std::string > Args, Optional< StringRef > ProgramName=None)
Run a main function, returning the result.
Definition: TargetExecutionUtils.cpp:16
FormatVariadic.h
llvm::orc::ExecutorProcessControl::MemAccess
MemoryAccess * MemAccess
Definition: ExecutorProcessControl.h:373
llvm::orc::ExecutorProcessControl::JDI
JITDispatchInfo JDI
Definition: ExecutorProcessControl.h:372
llvm::orc::ExecutorProcessControl::IncomingWFRHandler
A handler or incoming WrapperFunctionResults – either return values from callWrapper* calls,...
Definition: ExecutorProcessControl.h:48
llvm::orc::SelfExecutorProcessControl::loadDylib
Expected< tpctypes::DylibHandle > loadDylib(const char *DylibPath) override
Load the dynamic library at the given path and return a handle to it.
Definition: ExecutorProcessControl.cpp:76
llvm::orc::SelfExecutorProcessControl::runAsVoidFunction
Expected< int32_t > runAsVoidFunction(ExecutorAddr VoidFnAddr) override
Run function with a int (*)(void) signature.
Definition: ExecutorProcessControl.cpp:117
uint64_t
D
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:79
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::orc::SelfExecutorProcessControl::runAsIntFunction
Expected< int32_t > runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override
Run function with a int (*)(int) signature.
Definition: ExecutorProcessControl.cpp:123
llvm::sys::Process::getPageSize
static Expected< unsigned > getPageSize()
Get the process's page size.
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1836
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
llvm::orc::SelfExecutorProcessControl::callWrapperAsync
void callWrapperAsync(ExecutorAddr WrapperFnAddr, IncomingWFRHandler OnComplete, ArrayRef< char > ArgBuffer) override
Run a wrapper function in the executor.
Definition: ExecutorProcessControl.cpp:128
llvm::orc::runAsIntFunction
int runAsIntFunction(int(*Func)(int), int Arg)
Definition: TargetExecutionUtils.cpp:44
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
uint32_t
llvm::orc::SelfExecutorProcessControl::SelfExecutorProcessControl
SelfExecutorProcessControl(std::shared_ptr< SymbolStringPool > SSP, std::unique_ptr< TaskDispatcher > D, Triple TargetTriple, unsigned PageSize, std::unique_ptr< jitlink::JITLinkMemoryManager > MemMgr)
Definition: ExecutorProcessControl.cpp:26
llvm::orc::SelfExecutorProcessControl::lookupSymbols
Expected< std::vector< tpctypes::LookupResult > > lookupSymbols(ArrayRef< LookupRequest > Request) override
Search for symbols in the target process.
Definition: ExecutorProcessControl.cpp:85
llvm::pointerToJITTargetAddress
JITTargetAddress pointerToJITTargetAddress(T *Ptr)
Convert a pointer to a JITTargetAddress.
Definition: JITSymbol.h:69
llvm::orc::SelfExecutorProcessControl::Create
static Expected< std::unique_ptr< SelfExecutorProcessControl > > Create(std::shared_ptr< SymbolStringPool > SSP=nullptr, std::unique_ptr< TaskDispatcher > D=nullptr, std::unique_ptr< jitlink::JITLinkMemoryManager > MemMgr=nullptr)
Create a SelfExecutorProcessControl with the given symbol string pool and memory manager.
Definition: ExecutorProcessControl.cpp:48
std
Definition: BitVector.h:851
llvm::inconvertibleErrorCode
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:79
uint16_t
llvm::sys::getProcessTriple
std::string getProcessTriple()
getProcessTriple() - Return an appropriate target triple for generating code to be loaded into the cu...
Definition: Host.cpp:1961
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::orc::ExecutorProcessControl::D
std::unique_ptr< TaskDispatcher > D
Definition: ExecutorProcessControl.h:368
Core.h
llvm::orc::ExecutorProcessControl::~ExecutorProcessControl
virtual ~ExecutorProcessControl()
llvm::orc::ExecutorProcessControl::PageSize
unsigned PageSize
Definition: ExecutorProcessControl.h:371
llvm::orc::runAsVoidFunction
int runAsVoidFunction(int(*Func)(void))
Definition: TargetExecutionUtils.cpp:42
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:164
ExecutorProcessControl.h
TargetExecutionUtils.h
llvm::sys::Process::getPageSizeEstimate
static unsigned getPageSizeEstimate()
Get the process's estimated page size.
Definition: Process.h:61
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:394
llvm::orc::SymbolLookupFlags::RequiredSymbol
@ RequiredSymbol
llvm::orc::SymbolNameVector
std::vector< SymbolStringPtr > SymbolNameVector
A vector of symbol names.
Definition: Core.h:109
llvm::orc::SelfExecutorProcessControl::runAsMain
Expected< int32_t > runAsMain(ExecutorAddr MainFnAddr, ArrayRef< std::string > Args) override
Run function with a main-like signature.
Definition: ExecutorProcessControl.cpp:110