1 //===---- ExecutorProcessControl.cpp -- Executor process control APIs -----===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
11 #include "llvm/ExecutionEngine/Orc/Core.h"
12 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
13 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
14 #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
15 #include "llvm/Support/FormatVariadic.h"
16 #include "llvm/Support/Process.h"
17 #include "llvm/TargetParser/Host.h"
19 #define DEBUG_TYPE "orc"
24 ExecutorProcessControl::MemoryAccess::~MemoryAccess() = default;
26 ExecutorProcessControl::~ExecutorProcessControl() = default;
28 SelfExecutorProcessControl::SelfExecutorProcessControl(
29 std::shared_ptr
<SymbolStringPool
> SSP
, std::unique_ptr
<TaskDispatcher
> D
,
30 Triple TargetTriple
, unsigned PageSize
,
31 std::unique_ptr
<jitlink::JITLinkMemoryManager
> MemMgr
)
32 : ExecutorProcessControl(std::move(SSP
), std::move(D
)),
33 InProcessMemoryAccess(TargetTriple
.isArch64Bit()) {
35 OwnedMemMgr
= std::move(MemMgr
);
37 OwnedMemMgr
= std::make_unique
<jitlink::InProcessMemoryManager
>(
38 sys::Process::getPageSizeEstimate());
40 this->TargetTriple
= std::move(TargetTriple
);
41 this->PageSize
= PageSize
;
42 this->MemMgr
= OwnedMemMgr
.get();
43 this->MemAccess
= this;
44 this->JDI
= {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager
),
45 ExecutorAddr::fromPtr(this)};
46 if (this->TargetTriple
.isOSBinFormatMachO())
47 GlobalManglingPrefix
= '_';
49 this->BootstrapSymbols
[rt::RegisterEHFrameSectionWrapperName
] =
50 ExecutorAddr::fromPtr(&llvm_orc_registerEHFrameSectionWrapper
);
51 this->BootstrapSymbols
[rt::DeregisterEHFrameSectionWrapperName
] =
52 ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionWrapper
);
55 Expected
<std::unique_ptr
<SelfExecutorProcessControl
>>
56 SelfExecutorProcessControl::Create(
57 std::shared_ptr
<SymbolStringPool
> SSP
,
58 std::unique_ptr
<TaskDispatcher
> D
,
59 std::unique_ptr
<jitlink::JITLinkMemoryManager
> MemMgr
) {
62 SSP
= std::make_shared
<SymbolStringPool
>();
65 #if LLVM_ENABLE_THREADS
66 D
= std::make_unique
<DynamicThreadPoolTaskDispatcher
>();
68 D
= std::make_unique
<InPlaceTaskDispatcher
>();
72 auto PageSize
= sys::Process::getPageSize();
74 return PageSize
.takeError();
76 Triple
TT(sys::getProcessTriple());
78 return std::make_unique
<SelfExecutorProcessControl
>(
79 std::move(SSP
), std::move(D
), std::move(TT
), *PageSize
,
83 Expected
<tpctypes::DylibHandle
>
84 SelfExecutorProcessControl::loadDylib(const char *DylibPath
) {
86 auto Dylib
= sys::DynamicLibrary::getPermanentLibrary(DylibPath
, &ErrMsg
);
88 return make_error
<StringError
>(std::move(ErrMsg
), inconvertibleErrorCode());
89 return ExecutorAddr::fromPtr(Dylib
.getOSSpecificHandle());
92 Expected
<std::vector
<tpctypes::LookupResult
>>
93 SelfExecutorProcessControl::lookupSymbols(ArrayRef
<LookupRequest
> Request
) {
94 std::vector
<tpctypes::LookupResult
> R
;
96 for (auto &Elem
: Request
) {
97 sys::DynamicLibrary
Dylib(Elem
.Handle
.toPtr
<void *>());
98 R
.push_back(std::vector
<ExecutorSymbolDef
>());
99 for (auto &KV
: Elem
.Symbols
) {
100 auto &Sym
= KV
.first
;
101 std::string
Tmp((*Sym
).data() + !!GlobalManglingPrefix
,
102 (*Sym
).size() - !!GlobalManglingPrefix
);
103 void *Addr
= Dylib
.getAddressOfSymbol(Tmp
.c_str());
104 if (!Addr
&& KV
.second
== SymbolLookupFlags::RequiredSymbol
) {
105 // FIXME: Collect all failing symbols before erroring out.
106 SymbolNameVector MissingSymbols
;
107 MissingSymbols
.push_back(Sym
);
108 return make_error
<SymbolsNotFound
>(SSP
, std::move(MissingSymbols
));
110 // FIXME: determine accurate JITSymbolFlags.
112 {ExecutorAddr::fromPtr(Addr
), JITSymbolFlags::Exported
});
120 SelfExecutorProcessControl::runAsMain(ExecutorAddr MainFnAddr
,
121 ArrayRef
<std::string
> Args
) {
122 using MainTy
= int (*)(int, char *[]);
123 return orc::runAsMain(MainFnAddr
.toPtr
<MainTy
>(), Args
);
127 SelfExecutorProcessControl::runAsVoidFunction(ExecutorAddr VoidFnAddr
) {
128 using VoidTy
= int (*)();
129 return orc::runAsVoidFunction(VoidFnAddr
.toPtr
<VoidTy
>());
133 SelfExecutorProcessControl::runAsIntFunction(ExecutorAddr IntFnAddr
, int Arg
) {
134 using IntTy
= int (*)(int);
135 return orc::runAsIntFunction(IntFnAddr
.toPtr
<IntTy
>(), Arg
);
138 void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr
,
139 IncomingWFRHandler SendResult
,
140 ArrayRef
<char> ArgBuffer
) {
142 shared::CWrapperFunctionResult (*)(const char *Data
, size_t Size
);
143 auto *WrapperFn
= WrapperFnAddr
.toPtr
<WrapperFnTy
>();
144 SendResult(WrapperFn(ArgBuffer
.data(), ArgBuffer
.size()));
147 Error
SelfExecutorProcessControl::disconnect() {
149 return Error::success();
152 void InProcessMemoryAccess::writeUInt8sAsync(ArrayRef
<tpctypes::UInt8Write
> Ws
,
153 WriteResultFn OnWriteComplete
) {
155 *W
.Addr
.toPtr
<uint8_t *>() = W
.Value
;
156 OnWriteComplete(Error::success());
159 void InProcessMemoryAccess::writeUInt16sAsync(
160 ArrayRef
<tpctypes::UInt16Write
> Ws
, WriteResultFn OnWriteComplete
) {
162 *W
.Addr
.toPtr
<uint16_t *>() = W
.Value
;
163 OnWriteComplete(Error::success());
166 void InProcessMemoryAccess::writeUInt32sAsync(
167 ArrayRef
<tpctypes::UInt32Write
> Ws
, WriteResultFn OnWriteComplete
) {
169 *W
.Addr
.toPtr
<uint32_t *>() = W
.Value
;
170 OnWriteComplete(Error::success());
173 void InProcessMemoryAccess::writeUInt64sAsync(
174 ArrayRef
<tpctypes::UInt64Write
> Ws
, WriteResultFn OnWriteComplete
) {
176 *W
.Addr
.toPtr
<uint64_t *>() = W
.Value
;
177 OnWriteComplete(Error::success());
180 void InProcessMemoryAccess::writeBuffersAsync(
181 ArrayRef
<tpctypes::BufferWrite
> Ws
, WriteResultFn OnWriteComplete
) {
183 memcpy(W
.Addr
.toPtr
<char *>(), W
.Buffer
.data(), W
.Buffer
.size());
184 OnWriteComplete(Error::success());
187 void InProcessMemoryAccess::writePointersAsync(
188 ArrayRef
<tpctypes::PointerWrite
> Ws
, WriteResultFn OnWriteComplete
) {
191 *W
.Addr
.toPtr
<uint64_t *>() = W
.Value
.getValue();
194 *W
.Addr
.toPtr
<uint32_t *>() = static_cast<uint32_t>(W
.Value
.getValue());
197 OnWriteComplete(Error::success());
200 shared::CWrapperFunctionResult
201 SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager(
202 void *Ctx
, const void *FnTag
, const char *Data
, size_t Size
) {
205 dbgs() << "jit-dispatch call with tag " << FnTag
<< " and " << Size
206 << " byte payload.\n";
209 std::promise
<shared::WrapperFunctionResult
> ResultP
;
210 auto ResultF
= ResultP
.get_future();
211 static_cast<SelfExecutorProcessControl
*>(Ctx
)
212 ->getExecutionSession()
213 .runJITDispatchHandler(
214 [ResultP
= std::move(ResultP
)](
215 shared::WrapperFunctionResult Result
) mutable {
216 ResultP
.set_value(std::move(Result
));
218 ExecutorAddr::fromPtr(FnTag
), {Data
, Size
});
220 return ResultF
.get().release();
223 } // end namespace orc
224 } // end namespace llvm