File indexing completed on 2026-05-10 08:43:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTORPROCESSCONTROL_H
0014 #define LLVM_EXECUTIONENGINE_ORC_EXECUTORPROCESSCONTROL_H
0015
0016 #include "llvm/ADT/StringRef.h"
0017 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
0018 #include "llvm/ExecutionEngine/Orc/DylibManager.h"
0019 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
0020 #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
0021 #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
0022 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
0023 #include "llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h"
0024 #include "llvm/ExecutionEngine/Orc/TaskDispatch.h"
0025 #include "llvm/Support/DynamicLibrary.h"
0026 #include "llvm/Support/MSVCErrorWorkarounds.h"
0027 #include "llvm/TargetParser/Triple.h"
0028
0029 #include <future>
0030 #include <mutex>
0031 #include <vector>
0032
0033 namespace llvm {
0034 namespace orc {
0035
0036 class ExecutionSession;
0037
0038
0039 class ExecutorProcessControl {
0040 friend class ExecutionSession;
0041 public:
0042
0043
0044
0045
0046
0047
0048
0049 class IncomingWFRHandler {
0050 friend class ExecutorProcessControl;
0051 public:
0052 IncomingWFRHandler() = default;
0053 explicit operator bool() const { return !!H; }
0054 void operator()(shared::WrapperFunctionResult WFR) { H(std::move(WFR)); }
0055 private:
0056 template <typename FnT> IncomingWFRHandler(FnT &&Fn)
0057 : H(std::forward<FnT>(Fn)) {}
0058
0059 unique_function<void(shared::WrapperFunctionResult)> H;
0060 };
0061
0062
0063
0064
0065
0066
0067
0068 class RunInPlace {
0069 public:
0070 template <typename FnT>
0071 IncomingWFRHandler operator()(FnT &&Fn) {
0072 return IncomingWFRHandler(std::forward<FnT>(Fn));
0073 }
0074 };
0075
0076
0077
0078
0079
0080
0081 class RunAsTask {
0082 public:
0083 RunAsTask(TaskDispatcher &D) : D(D) {}
0084
0085 template <typename FnT>
0086 IncomingWFRHandler operator()(FnT &&Fn) {
0087 return IncomingWFRHandler(
0088 [&D = this->D, Fn = std::move(Fn)]
0089 (shared::WrapperFunctionResult WFR) mutable {
0090 D.dispatch(
0091 makeGenericNamedTask(
0092 [Fn = std::move(Fn), WFR = std::move(WFR)]() mutable {
0093 Fn(std::move(WFR));
0094 }, "WFR handler task"));
0095 });
0096 }
0097 private:
0098 TaskDispatcher &D;
0099 };
0100
0101
0102 class MemoryAccess {
0103 public:
0104
0105 using WriteResultFn = unique_function<void(Error)>;
0106
0107 virtual ~MemoryAccess();
0108
0109 virtual void writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
0110 WriteResultFn OnWriteComplete) = 0;
0111
0112 virtual void writeUInt16sAsync(ArrayRef<tpctypes::UInt16Write> Ws,
0113 WriteResultFn OnWriteComplete) = 0;
0114
0115 virtual void writeUInt32sAsync(ArrayRef<tpctypes::UInt32Write> Ws,
0116 WriteResultFn OnWriteComplete) = 0;
0117
0118 virtual void writeUInt64sAsync(ArrayRef<tpctypes::UInt64Write> Ws,
0119 WriteResultFn OnWriteComplete) = 0;
0120
0121 virtual void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws,
0122 WriteResultFn OnWriteComplete) = 0;
0123
0124 virtual void writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws,
0125 WriteResultFn OnWriteComplete) = 0;
0126
0127 Error writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws) {
0128 std::promise<MSVCPError> ResultP;
0129 auto ResultF = ResultP.get_future();
0130 writeUInt8sAsync(Ws,
0131 [&](Error Err) { ResultP.set_value(std::move(Err)); });
0132 return ResultF.get();
0133 }
0134
0135 Error writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws) {
0136 std::promise<MSVCPError> ResultP;
0137 auto ResultF = ResultP.get_future();
0138 writeUInt16sAsync(Ws,
0139 [&](Error Err) { ResultP.set_value(std::move(Err)); });
0140 return ResultF.get();
0141 }
0142
0143 Error writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws) {
0144 std::promise<MSVCPError> ResultP;
0145 auto ResultF = ResultP.get_future();
0146 writeUInt32sAsync(Ws,
0147 [&](Error Err) { ResultP.set_value(std::move(Err)); });
0148 return ResultF.get();
0149 }
0150
0151 Error writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws) {
0152 std::promise<MSVCPError> ResultP;
0153 auto ResultF = ResultP.get_future();
0154 writeUInt64sAsync(Ws,
0155 [&](Error Err) { ResultP.set_value(std::move(Err)); });
0156 return ResultF.get();
0157 }
0158
0159 Error writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws) {
0160 std::promise<MSVCPError> ResultP;
0161 auto ResultF = ResultP.get_future();
0162 writeBuffersAsync(Ws,
0163 [&](Error Err) { ResultP.set_value(std::move(Err)); });
0164 return ResultF.get();
0165 }
0166
0167 Error writePointers(ArrayRef<tpctypes::PointerWrite> Ws) {
0168 std::promise<MSVCPError> ResultP;
0169 auto ResultF = ResultP.get_future();
0170 writePointersAsync(Ws,
0171 [&](Error Err) { ResultP.set_value(std::move(Err)); });
0172 return ResultF.get();
0173 }
0174 };
0175
0176
0177
0178 struct JITDispatchInfo {
0179 ExecutorAddr JITDispatchFunction;
0180 ExecutorAddr JITDispatchContext;
0181 };
0182
0183 ExecutorProcessControl(std::shared_ptr<SymbolStringPool> SSP,
0184 std::unique_ptr<TaskDispatcher> D)
0185 : SSP(std::move(SSP)), D(std::move(D)) {}
0186
0187 virtual ~ExecutorProcessControl();
0188
0189
0190
0191 ExecutionSession &getExecutionSession() {
0192 assert(ES && "No ExecutionSession associated yet");
0193 return *ES;
0194 }
0195
0196
0197 SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); }
0198
0199
0200 std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; }
0201
0202 TaskDispatcher &getDispatcher() { return *D; }
0203
0204
0205 const Triple &getTargetTriple() const { return TargetTriple; }
0206
0207
0208 unsigned getPageSize() const { return PageSize; }
0209
0210
0211 const JITDispatchInfo &getJITDispatchInfo() const { return JDI; }
0212
0213
0214 MemoryAccess &getMemoryAccess() const {
0215 assert(MemAccess && "No MemAccess object set.");
0216 return *MemAccess;
0217 }
0218
0219
0220 jitlink::JITLinkMemoryManager &getMemMgr() const {
0221 assert(MemMgr && "No MemMgr object set");
0222 return *MemMgr;
0223 }
0224
0225
0226 DylibManager &getDylibMgr() const {
0227 assert(DylibMgr && "No DylibMgr object set");
0228 return *DylibMgr;
0229 }
0230
0231
0232 const StringMap<std::vector<char>> &getBootstrapMap() const {
0233 return BootstrapMap;
0234 }
0235
0236
0237 template <typename T, typename SPSTagT>
0238 Error getBootstrapMapValue(StringRef Key, std::optional<T> &Val) const {
0239 Val = std::nullopt;
0240
0241 auto I = BootstrapMap.find(Key);
0242 if (I == BootstrapMap.end())
0243 return Error::success();
0244
0245 T Tmp;
0246 shared::SPSInputBuffer IB(I->second.data(), I->second.size());
0247 if (!shared::SPSArgList<SPSTagT>::deserialize(IB, Tmp))
0248 return make_error<StringError>("Could not deserialize value for key " +
0249 Key,
0250 inconvertibleErrorCode());
0251
0252 Val = std::move(Tmp);
0253 return Error::success();
0254 }
0255
0256
0257 const StringMap<ExecutorAddr> &getBootstrapSymbolsMap() const {
0258 return BootstrapSymbols;
0259 }
0260
0261
0262
0263
0264 Error getBootstrapSymbols(
0265 ArrayRef<std::pair<ExecutorAddr &, StringRef>> Pairs) const {
0266 for (const auto &KV : Pairs) {
0267 auto I = BootstrapSymbols.find(KV.second);
0268 if (I == BootstrapSymbols.end())
0269 return make_error<StringError>("Symbol \"" + KV.second +
0270 "\" not found "
0271 "in bootstrap symbols map",
0272 inconvertibleErrorCode());
0273
0274 KV.first = I->second;
0275 }
0276 return Error::success();
0277 }
0278
0279
0280 virtual Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
0281 ArrayRef<std::string> Args) = 0;
0282
0283
0284
0285 virtual Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) = 0;
0286
0287
0288
0289 virtual Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr,
0290 int Arg) = 0;
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300 virtual void callWrapperAsync(ExecutorAddr WrapperFnAddr,
0301 IncomingWFRHandler OnComplete,
0302 ArrayRef<char> ArgBuffer) = 0;
0303
0304
0305
0306 template <typename RunPolicyT, typename FnT>
0307 void callWrapperAsync(RunPolicyT &&Runner, ExecutorAddr WrapperFnAddr,
0308 FnT &&OnComplete, ArrayRef<char> ArgBuffer) {
0309 callWrapperAsync(
0310 WrapperFnAddr, Runner(std::forward<FnT>(OnComplete)), ArgBuffer);
0311 }
0312
0313
0314
0315 template <typename FnT>
0316 void callWrapperAsync(ExecutorAddr WrapperFnAddr, FnT &&OnComplete,
0317 ArrayRef<char> ArgBuffer) {
0318 callWrapperAsync(RunAsTask(*D), WrapperFnAddr,
0319 std::forward<FnT>(OnComplete), ArgBuffer);
0320 }
0321
0322
0323
0324
0325
0326
0327
0328 shared::WrapperFunctionResult callWrapper(ExecutorAddr WrapperFnAddr,
0329 ArrayRef<char> ArgBuffer) {
0330 std::promise<shared::WrapperFunctionResult> RP;
0331 auto RF = RP.get_future();
0332 callWrapperAsync(
0333 RunInPlace(), WrapperFnAddr,
0334 [&](shared::WrapperFunctionResult R) {
0335 RP.set_value(std::move(R));
0336 }, ArgBuffer);
0337 return RF.get();
0338 }
0339
0340
0341
0342 template <typename SPSSignature, typename RunPolicyT, typename SendResultT,
0343 typename... ArgTs>
0344 void callSPSWrapperAsync(RunPolicyT &&Runner, ExecutorAddr WrapperFnAddr,
0345 SendResultT &&SendResult, const ArgTs &...Args) {
0346 shared::WrapperFunction<SPSSignature>::callAsync(
0347 [this, WrapperFnAddr, Runner = std::move(Runner)]
0348 (auto &&SendResult, const char *ArgData, size_t ArgSize) mutable {
0349 this->callWrapperAsync(std::move(Runner), WrapperFnAddr,
0350 std::move(SendResult),
0351 ArrayRef<char>(ArgData, ArgSize));
0352 },
0353 std::forward<SendResultT>(SendResult), Args...);
0354 }
0355
0356
0357
0358 template <typename SPSSignature, typename SendResultT, typename... ArgTs>
0359 void callSPSWrapperAsync(ExecutorAddr WrapperFnAddr, SendResultT &&SendResult,
0360 const ArgTs &...Args) {
0361 callSPSWrapperAsync<SPSSignature>(RunAsTask(*D), WrapperFnAddr,
0362 std::forward<SendResultT>(SendResult),
0363 Args...);
0364 }
0365
0366
0367
0368
0369
0370
0371 template <typename SPSSignature, typename... WrapperCallArgTs>
0372 Error callSPSWrapper(ExecutorAddr WrapperFnAddr,
0373 WrapperCallArgTs &&...WrapperCallArgs) {
0374 return shared::WrapperFunction<SPSSignature>::call(
0375 [this, WrapperFnAddr](const char *ArgData, size_t ArgSize) {
0376 return callWrapper(WrapperFnAddr, ArrayRef<char>(ArgData, ArgSize));
0377 },
0378 std::forward<WrapperCallArgTs>(WrapperCallArgs)...);
0379 }
0380
0381
0382
0383
0384 virtual Error disconnect() = 0;
0385
0386 protected:
0387
0388 std::shared_ptr<SymbolStringPool> SSP;
0389 std::unique_ptr<TaskDispatcher> D;
0390 ExecutionSession *ES = nullptr;
0391 Triple TargetTriple;
0392 unsigned PageSize = 0;
0393 JITDispatchInfo JDI;
0394 MemoryAccess *MemAccess = nullptr;
0395 jitlink::JITLinkMemoryManager *MemMgr = nullptr;
0396 DylibManager *DylibMgr = nullptr;
0397 StringMap<std::vector<char>> BootstrapMap;
0398 StringMap<ExecutorAddr> BootstrapSymbols;
0399 };
0400
0401 class InProcessMemoryAccess : public ExecutorProcessControl::MemoryAccess {
0402 public:
0403 InProcessMemoryAccess(bool IsArch64Bit) : IsArch64Bit(IsArch64Bit) {}
0404 void writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
0405 WriteResultFn OnWriteComplete) override;
0406
0407 void writeUInt16sAsync(ArrayRef<tpctypes::UInt16Write> Ws,
0408 WriteResultFn OnWriteComplete) override;
0409
0410 void writeUInt32sAsync(ArrayRef<tpctypes::UInt32Write> Ws,
0411 WriteResultFn OnWriteComplete) override;
0412
0413 void writeUInt64sAsync(ArrayRef<tpctypes::UInt64Write> Ws,
0414 WriteResultFn OnWriteComplete) override;
0415
0416 void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws,
0417 WriteResultFn OnWriteComplete) override;
0418
0419 void writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws,
0420 WriteResultFn OnWriteComplete) override;
0421
0422 private:
0423 bool IsArch64Bit;
0424 };
0425
0426
0427
0428
0429 class UnsupportedExecutorProcessControl : public ExecutorProcessControl,
0430 private InProcessMemoryAccess {
0431 public:
0432 UnsupportedExecutorProcessControl(
0433 std::shared_ptr<SymbolStringPool> SSP = nullptr,
0434 std::unique_ptr<TaskDispatcher> D = nullptr, const std::string &TT = "",
0435 unsigned PageSize = 0)
0436 : ExecutorProcessControl(
0437 SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>(),
0438 D ? std::move(D) : std::make_unique<InPlaceTaskDispatcher>()),
0439 InProcessMemoryAccess(Triple(TT).isArch64Bit()) {
0440 this->TargetTriple = Triple(TT);
0441 this->PageSize = PageSize;
0442 this->MemAccess = this;
0443 }
0444
0445 Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
0446 ArrayRef<std::string> Args) override {
0447 llvm_unreachable("Unsupported");
0448 }
0449
0450 Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) override {
0451 llvm_unreachable("Unsupported");
0452 }
0453
0454 Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override {
0455 llvm_unreachable("Unsupported");
0456 }
0457
0458 void callWrapperAsync(ExecutorAddr WrapperFnAddr,
0459 IncomingWFRHandler OnComplete,
0460 ArrayRef<char> ArgBuffer) override {
0461 llvm_unreachable("Unsupported");
0462 }
0463
0464 Error disconnect() override { return Error::success(); }
0465 };
0466
0467
0468 class SelfExecutorProcessControl : public ExecutorProcessControl,
0469 private InProcessMemoryAccess,
0470 private DylibManager {
0471 public:
0472 SelfExecutorProcessControl(
0473 std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,
0474 Triple TargetTriple, unsigned PageSize,
0475 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr);
0476
0477
0478
0479
0480
0481
0482 static Expected<std::unique_ptr<SelfExecutorProcessControl>>
0483 Create(std::shared_ptr<SymbolStringPool> SSP = nullptr,
0484 std::unique_ptr<TaskDispatcher> D = nullptr,
0485 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr = nullptr);
0486
0487 Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
0488 ArrayRef<std::string> Args) override;
0489
0490 Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) override;
0491
0492 Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override;
0493
0494 void callWrapperAsync(ExecutorAddr WrapperFnAddr,
0495 IncomingWFRHandler OnComplete,
0496 ArrayRef<char> ArgBuffer) override;
0497
0498 Error disconnect() override;
0499
0500 private:
0501 static shared::CWrapperFunctionResult
0502 jitDispatchViaWrapperFunctionManager(void *Ctx, const void *FnTag,
0503 const char *Data, size_t Size);
0504
0505 Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override;
0506
0507 void lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
0508 SymbolLookupCompleteFn F) override;
0509
0510 std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
0511 #ifdef __APPLE__
0512 std::unique_ptr<UnwindInfoManager> UnwindInfoMgr;
0513 #endif
0514 char GlobalManglingPrefix = 0;
0515 };
0516
0517 }
0518 }
0519
0520 #endif