1 //===- ExecutorProcessControl.h - Executor process control APIs -*- C++ -*-===// 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 // 9 // Utilities for interacting with the executor processes. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTORPROCESSCONTROL_H 14 #define LLVM_EXECUTIONENGINE_ORC_EXECUTORPROCESSCONTROL_H 15 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" 18 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" 19 #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h" 20 #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h" 21 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h" 22 #include "llvm/ExecutionEngine/Orc/TaskDispatch.h" 23 #include "llvm/Support/DynamicLibrary.h" 24 #include "llvm/Support/MSVCErrorWorkarounds.h" 25 #include "llvm/TargetParser/Triple.h" 26 27 #include <future> 28 #include <mutex> 29 #include <vector> 30 31 namespace llvm { 32 namespace orc { 33 34 class ExecutionSession; 35 class SymbolLookupSet; 36 37 /// ExecutorProcessControl supports interaction with a JIT target process. 38 class ExecutorProcessControl { 39 friend class ExecutionSession; 40 public: 41 42 /// A handler or incoming WrapperFunctionResults -- either return values from 43 /// callWrapper* calls, or incoming JIT-dispatch requests. 44 /// 45 /// IncomingWFRHandlers are constructible from 46 /// unique_function<void(shared::WrapperFunctionResult)>s using the 47 /// runInPlace function or a RunWithDispatch object. 48 class IncomingWFRHandler { 49 friend class ExecutorProcessControl; 50 public: 51 IncomingWFRHandler() = default; 52 explicit operator bool() const { return !!H; } operator()53 void operator()(shared::WrapperFunctionResult WFR) { H(std::move(WFR)); } 54 private: IncomingWFRHandler(FnT && Fn)55 template <typename FnT> IncomingWFRHandler(FnT &&Fn) 56 : H(std::forward<FnT>(Fn)) {} 57 58 unique_function<void(shared::WrapperFunctionResult)> H; 59 }; 60 61 /// Constructs an IncomingWFRHandler from a function object that is callable 62 /// as void(shared::WrapperFunctionResult). The function object will be called 63 /// directly. This should be used with care as it may block listener threads 64 /// in remote EPCs. It is only suitable for simple tasks (e.g. setting a 65 /// future), or for performing some quick analysis before dispatching "real" 66 /// work as a Task. 67 class RunInPlace { 68 public: 69 template <typename FnT> operator()70 IncomingWFRHandler operator()(FnT &&Fn) { 71 return IncomingWFRHandler(std::forward<FnT>(Fn)); 72 } 73 }; 74 75 /// Constructs an IncomingWFRHandler from a function object by creating a new 76 /// function object that dispatches the original using a TaskDispatcher, 77 /// wrapping the original as a GenericNamedTask. 78 /// 79 /// This is the default approach for running WFR handlers. 80 class RunAsTask { 81 public: RunAsTask(TaskDispatcher & D)82 RunAsTask(TaskDispatcher &D) : D(D) {} 83 84 template <typename FnT> operator()85 IncomingWFRHandler operator()(FnT &&Fn) { 86 return IncomingWFRHandler( 87 [&D = this->D, Fn = std::move(Fn)] 88 (shared::WrapperFunctionResult WFR) mutable { 89 D.dispatch( 90 makeGenericNamedTask( 91 [Fn = std::move(Fn), WFR = std::move(WFR)]() mutable { 92 Fn(std::move(WFR)); 93 }, "WFR handler task")); 94 }); 95 } 96 private: 97 TaskDispatcher &D; 98 }; 99 100 /// APIs for manipulating memory in the target process. 101 class MemoryAccess { 102 public: 103 /// Callback function for asynchronous writes. 104 using WriteResultFn = unique_function<void(Error)>; 105 106 virtual ~MemoryAccess(); 107 108 virtual void writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws, 109 WriteResultFn OnWriteComplete) = 0; 110 111 virtual void writeUInt16sAsync(ArrayRef<tpctypes::UInt16Write> Ws, 112 WriteResultFn OnWriteComplete) = 0; 113 114 virtual void writeUInt32sAsync(ArrayRef<tpctypes::UInt32Write> Ws, 115 WriteResultFn OnWriteComplete) = 0; 116 117 virtual void writeUInt64sAsync(ArrayRef<tpctypes::UInt64Write> Ws, 118 WriteResultFn OnWriteComplete) = 0; 119 120 virtual void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws, 121 WriteResultFn OnWriteComplete) = 0; 122 123 virtual void writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws, 124 WriteResultFn OnWriteComplete) = 0; 125 writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws)126 Error writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws) { 127 std::promise<MSVCPError> ResultP; 128 auto ResultF = ResultP.get_future(); 129 writeUInt8sAsync(Ws, 130 [&](Error Err) { ResultP.set_value(std::move(Err)); }); 131 return ResultF.get(); 132 } 133 writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws)134 Error writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws) { 135 std::promise<MSVCPError> ResultP; 136 auto ResultF = ResultP.get_future(); 137 writeUInt16sAsync(Ws, 138 [&](Error Err) { ResultP.set_value(std::move(Err)); }); 139 return ResultF.get(); 140 } 141 writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws)142 Error writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws) { 143 std::promise<MSVCPError> ResultP; 144 auto ResultF = ResultP.get_future(); 145 writeUInt32sAsync(Ws, 146 [&](Error Err) { ResultP.set_value(std::move(Err)); }); 147 return ResultF.get(); 148 } 149 writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws)150 Error writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws) { 151 std::promise<MSVCPError> ResultP; 152 auto ResultF = ResultP.get_future(); 153 writeUInt64sAsync(Ws, 154 [&](Error Err) { ResultP.set_value(std::move(Err)); }); 155 return ResultF.get(); 156 } 157 writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws)158 Error writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws) { 159 std::promise<MSVCPError> ResultP; 160 auto ResultF = ResultP.get_future(); 161 writeBuffersAsync(Ws, 162 [&](Error Err) { ResultP.set_value(std::move(Err)); }); 163 return ResultF.get(); 164 } 165 writePointers(ArrayRef<tpctypes::PointerWrite> Ws)166 Error writePointers(ArrayRef<tpctypes::PointerWrite> Ws) { 167 std::promise<MSVCPError> ResultP; 168 auto ResultF = ResultP.get_future(); 169 writePointersAsync(Ws, 170 [&](Error Err) { ResultP.set_value(std::move(Err)); }); 171 return ResultF.get(); 172 } 173 }; 174 175 /// A pair of a dylib and a set of symbols to be looked up. 176 struct LookupRequest { LookupRequestLookupRequest177 LookupRequest(tpctypes::DylibHandle Handle, const SymbolLookupSet &Symbols) 178 : Handle(Handle), Symbols(Symbols) {} 179 tpctypes::DylibHandle Handle; 180 const SymbolLookupSet &Symbols; 181 }; 182 183 /// Contains the address of the dispatch function and context that the ORC 184 /// runtime can use to call functions in the JIT. 185 struct JITDispatchInfo { 186 ExecutorAddr JITDispatchFunction; 187 ExecutorAddr JITDispatchContext; 188 }; 189 ExecutorProcessControl(std::shared_ptr<SymbolStringPool> SSP,std::unique_ptr<TaskDispatcher> D)190 ExecutorProcessControl(std::shared_ptr<SymbolStringPool> SSP, 191 std::unique_ptr<TaskDispatcher> D) 192 : SSP(std::move(SSP)), D(std::move(D)) {} 193 194 virtual ~ExecutorProcessControl(); 195 196 /// Return the ExecutionSession associated with this instance. 197 /// Not callable until the ExecutionSession has been associated. getExecutionSession()198 ExecutionSession &getExecutionSession() { 199 assert(ES && "No ExecutionSession associated yet"); 200 return *ES; 201 } 202 203 /// Intern a symbol name in the SymbolStringPool. intern(StringRef SymName)204 SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); } 205 206 /// Return a shared pointer to the SymbolStringPool for this instance. getSymbolStringPool()207 std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; } 208 getDispatcher()209 TaskDispatcher &getDispatcher() { return *D; } 210 211 /// Return the Triple for the target process. getTargetTriple()212 const Triple &getTargetTriple() const { return TargetTriple; } 213 214 /// Get the page size for the target process. getPageSize()215 unsigned getPageSize() const { return PageSize; } 216 217 /// Get the JIT dispatch function and context address for the executor. getJITDispatchInfo()218 const JITDispatchInfo &getJITDispatchInfo() const { return JDI; } 219 220 /// Return a MemoryAccess object for the target process. getMemoryAccess()221 MemoryAccess &getMemoryAccess() const { 222 assert(MemAccess && "No MemAccess object set."); 223 return *MemAccess; 224 } 225 226 /// Return a JITLinkMemoryManager for the target process. getMemMgr()227 jitlink::JITLinkMemoryManager &getMemMgr() const { 228 assert(MemMgr && "No MemMgr object set"); 229 return *MemMgr; 230 } 231 232 /// Returns the bootstrap map. getBootstrapMap()233 const StringMap<std::vector<char>> &getBootstrapMap() const { 234 return BootstrapMap; 235 } 236 237 /// Look up and SPS-deserialize a bootstrap map value. 238 /// 239 /// 240 template <typename T, typename SPSTagT> getBootstrapMapValue(StringRef Key,std::optional<T> & Val)241 Error getBootstrapMapValue(StringRef Key, std::optional<T> &Val) const { 242 Val = std::nullopt; 243 244 auto I = BootstrapMap.find(Key); 245 if (I == BootstrapMap.end()) 246 return Error::success(); 247 248 T Tmp; 249 shared::SPSInputBuffer IB(I->second.data(), I->second.size()); 250 if (!shared::SPSArgList<SPSTagT>::deserialize(IB, Tmp)) 251 return make_error<StringError>("Could not deserialize value for key " + 252 Key, 253 inconvertibleErrorCode()); 254 255 Val = std::move(Tmp); 256 return Error::success(); 257 } 258 259 /// Returns the bootstrap symbol map. getBootstrapSymbolsMap()260 const StringMap<ExecutorAddr> &getBootstrapSymbolsMap() const { 261 return BootstrapSymbols; 262 } 263 264 /// For each (ExecutorAddr&, StringRef) pair, looks up the string in the 265 /// bootstrap symbols map and writes its address to the ExecutorAddr if 266 /// found. If any symbol is not found then the function returns an error. getBootstrapSymbols(ArrayRef<std::pair<ExecutorAddr &,StringRef>> Pairs)267 Error getBootstrapSymbols( 268 ArrayRef<std::pair<ExecutorAddr &, StringRef>> Pairs) const { 269 for (const auto &KV : Pairs) { 270 auto I = BootstrapSymbols.find(KV.second); 271 if (I == BootstrapSymbols.end()) 272 return make_error<StringError>("Symbol \"" + KV.second + 273 "\" not found " 274 "in bootstrap symbols map", 275 inconvertibleErrorCode()); 276 277 KV.first = I->second; 278 } 279 return Error::success(); 280 } 281 282 /// Load the dynamic library at the given path and return a handle to it. 283 /// If LibraryPath is null this function will return the global handle for 284 /// the target process. 285 virtual Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) = 0; 286 287 /// Search for symbols in the target process. 288 /// 289 /// The result of the lookup is a 2-dimensional array of target addresses 290 /// that correspond to the lookup order. If a required symbol is not 291 /// found then this method will return an error. If a weakly referenced 292 /// symbol is not found then it be assigned a '0' value. 293 Expected<std::vector<tpctypes::LookupResult>> lookupSymbols(ArrayRef<LookupRequest> Request)294 lookupSymbols(ArrayRef<LookupRequest> Request) { 295 std::promise<MSVCPExpected<std::vector<tpctypes::LookupResult>>> RP; 296 auto RF = RP.get_future(); 297 lookupSymbolsAsync(Request, 298 [&RP](auto Result) { RP.set_value(std::move(Result)); }); 299 return RF.get(); 300 } 301 302 using SymbolLookupCompleteFn = 303 unique_function<void(Expected<std::vector<tpctypes::LookupResult>>)>; 304 305 /// Search for symbols in the target process. 306 /// 307 /// The result of the lookup is a 2-dimensional array of target addresses 308 /// that correspond to the lookup order. If a required symbol is not 309 /// found then this method will return an error. If a weakly referenced 310 /// symbol is not found then it be assigned a '0' value. 311 virtual void lookupSymbolsAsync(ArrayRef<LookupRequest> Request, 312 SymbolLookupCompleteFn F) = 0; 313 314 /// Run function with a main-like signature. 315 virtual Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr, 316 ArrayRef<std::string> Args) = 0; 317 318 // TODO: move this to ORC runtime. 319 /// Run function with a int (*)(void) signature. 320 virtual Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) = 0; 321 322 // TODO: move this to ORC runtime. 323 /// Run function with a int (*)(int) signature. 324 virtual Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, 325 int Arg) = 0; 326 327 /// Run a wrapper function in the executor. The given WFRHandler will be 328 /// called on the result when it is returned. 329 /// 330 /// The wrapper function should be callable as: 331 /// 332 /// \code{.cpp} 333 /// CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size); 334 /// \endcode{.cpp} 335 virtual void callWrapperAsync(ExecutorAddr WrapperFnAddr, 336 IncomingWFRHandler OnComplete, 337 ArrayRef<char> ArgBuffer) = 0; 338 339 /// Run a wrapper function in the executor using the given Runner to dispatch 340 /// OnComplete when the result is ready. 341 template <typename RunPolicyT, typename FnT> callWrapperAsync(RunPolicyT && Runner,ExecutorAddr WrapperFnAddr,FnT && OnComplete,ArrayRef<char> ArgBuffer)342 void callWrapperAsync(RunPolicyT &&Runner, ExecutorAddr WrapperFnAddr, 343 FnT &&OnComplete, ArrayRef<char> ArgBuffer) { 344 callWrapperAsync( 345 WrapperFnAddr, Runner(std::forward<FnT>(OnComplete)), ArgBuffer); 346 } 347 348 /// Run a wrapper function in the executor. OnComplete will be dispatched 349 /// as a GenericNamedTask using this instance's TaskDispatch object. 350 template <typename FnT> callWrapperAsync(ExecutorAddr WrapperFnAddr,FnT && OnComplete,ArrayRef<char> ArgBuffer)351 void callWrapperAsync(ExecutorAddr WrapperFnAddr, FnT &&OnComplete, 352 ArrayRef<char> ArgBuffer) { 353 callWrapperAsync(RunAsTask(*D), WrapperFnAddr, 354 std::forward<FnT>(OnComplete), ArgBuffer); 355 } 356 357 /// Run a wrapper function in the executor. The wrapper function should be 358 /// callable as: 359 /// 360 /// \code{.cpp} 361 /// CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size); 362 /// \endcode{.cpp} callWrapper(ExecutorAddr WrapperFnAddr,ArrayRef<char> ArgBuffer)363 shared::WrapperFunctionResult callWrapper(ExecutorAddr WrapperFnAddr, 364 ArrayRef<char> ArgBuffer) { 365 std::promise<shared::WrapperFunctionResult> RP; 366 auto RF = RP.get_future(); 367 callWrapperAsync( 368 RunInPlace(), WrapperFnAddr, 369 [&](shared::WrapperFunctionResult R) { 370 RP.set_value(std::move(R)); 371 }, ArgBuffer); 372 return RF.get(); 373 } 374 375 /// Run a wrapper function using SPS to serialize the arguments and 376 /// deserialize the results. 377 template <typename SPSSignature, typename RunPolicyT, typename SendResultT, 378 typename... ArgTs> callSPSWrapperAsync(RunPolicyT && Runner,ExecutorAddr WrapperFnAddr,SendResultT && SendResult,const ArgTs &...Args)379 void callSPSWrapperAsync(RunPolicyT &&Runner, ExecutorAddr WrapperFnAddr, 380 SendResultT &&SendResult, const ArgTs &...Args) { 381 shared::WrapperFunction<SPSSignature>::callAsync( 382 [this, WrapperFnAddr, Runner = std::move(Runner)] 383 (auto &&SendResult, const char *ArgData, size_t ArgSize) mutable { 384 this->callWrapperAsync(std::move(Runner), WrapperFnAddr, 385 std::move(SendResult), 386 ArrayRef<char>(ArgData, ArgSize)); 387 }, 388 std::forward<SendResultT>(SendResult), Args...); 389 } 390 391 /// Run a wrapper function using SPS to serialize the arguments and 392 /// deserialize the results. 393 template <typename SPSSignature, typename SendResultT, typename... ArgTs> callSPSWrapperAsync(ExecutorAddr WrapperFnAddr,SendResultT && SendResult,const ArgTs &...Args)394 void callSPSWrapperAsync(ExecutorAddr WrapperFnAddr, SendResultT &&SendResult, 395 const ArgTs &...Args) { 396 callSPSWrapperAsync<SPSSignature>(RunAsTask(*D), WrapperFnAddr, 397 std::forward<SendResultT>(SendResult), 398 Args...); 399 } 400 401 /// Run a wrapper function using SPS to serialize the arguments and 402 /// deserialize the results. 403 /// 404 /// If SPSSignature is a non-void function signature then the second argument 405 /// (the first in the Args list) should be a reference to a return value. 406 template <typename SPSSignature, typename... WrapperCallArgTs> callSPSWrapper(ExecutorAddr WrapperFnAddr,WrapperCallArgTs &&...WrapperCallArgs)407 Error callSPSWrapper(ExecutorAddr WrapperFnAddr, 408 WrapperCallArgTs &&...WrapperCallArgs) { 409 return shared::WrapperFunction<SPSSignature>::call( 410 [this, WrapperFnAddr](const char *ArgData, size_t ArgSize) { 411 return callWrapper(WrapperFnAddr, ArrayRef<char>(ArgData, ArgSize)); 412 }, 413 std::forward<WrapperCallArgTs>(WrapperCallArgs)...); 414 } 415 416 /// Disconnect from the target process. 417 /// 418 /// This should be called after the JIT session is shut down. 419 virtual Error disconnect() = 0; 420 421 protected: 422 423 std::shared_ptr<SymbolStringPool> SSP; 424 std::unique_ptr<TaskDispatcher> D; 425 ExecutionSession *ES = nullptr; 426 Triple TargetTriple; 427 unsigned PageSize = 0; 428 JITDispatchInfo JDI; 429 MemoryAccess *MemAccess = nullptr; 430 jitlink::JITLinkMemoryManager *MemMgr = nullptr; 431 StringMap<std::vector<char>> BootstrapMap; 432 StringMap<ExecutorAddr> BootstrapSymbols; 433 }; 434 435 class InProcessMemoryAccess : public ExecutorProcessControl::MemoryAccess { 436 public: InProcessMemoryAccess(bool IsArch64Bit)437 InProcessMemoryAccess(bool IsArch64Bit) : IsArch64Bit(IsArch64Bit) {} 438 void writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws, 439 WriteResultFn OnWriteComplete) override; 440 441 void writeUInt16sAsync(ArrayRef<tpctypes::UInt16Write> Ws, 442 WriteResultFn OnWriteComplete) override; 443 444 void writeUInt32sAsync(ArrayRef<tpctypes::UInt32Write> Ws, 445 WriteResultFn OnWriteComplete) override; 446 447 void writeUInt64sAsync(ArrayRef<tpctypes::UInt64Write> Ws, 448 WriteResultFn OnWriteComplete) override; 449 450 void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws, 451 WriteResultFn OnWriteComplete) override; 452 453 void writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws, 454 WriteResultFn OnWriteComplete) override; 455 456 private: 457 bool IsArch64Bit; 458 }; 459 460 /// A ExecutorProcessControl instance that asserts if any of its methods are 461 /// used. Suitable for use is unit tests, and by ORC clients who haven't moved 462 /// to ExecutorProcessControl-based APIs yet. 463 class UnsupportedExecutorProcessControl : public ExecutorProcessControl, 464 private InProcessMemoryAccess { 465 public: 466 UnsupportedExecutorProcessControl( 467 std::shared_ptr<SymbolStringPool> SSP = nullptr, 468 std::unique_ptr<TaskDispatcher> D = nullptr, const std::string &TT = "", 469 unsigned PageSize = 0) 470 : ExecutorProcessControl( 471 SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>(), 472 D ? std::move(D) : std::make_unique<InPlaceTaskDispatcher>()), 473 InProcessMemoryAccess(Triple(TT).isArch64Bit()) { 474 this->TargetTriple = Triple(TT); 475 this->PageSize = PageSize; 476 this->MemAccess = this; 477 } 478 loadDylib(const char * DylibPath)479 Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override { 480 llvm_unreachable("Unsupported"); 481 } 482 lookupSymbolsAsync(ArrayRef<LookupRequest> Request,SymbolLookupCompleteFn F)483 void lookupSymbolsAsync(ArrayRef<LookupRequest> Request, 484 SymbolLookupCompleteFn F) override { 485 llvm_unreachable("Unsupported"); 486 } 487 runAsMain(ExecutorAddr MainFnAddr,ArrayRef<std::string> Args)488 Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr, 489 ArrayRef<std::string> Args) override { 490 llvm_unreachable("Unsupported"); 491 } 492 runAsVoidFunction(ExecutorAddr VoidFnAddr)493 Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) override { 494 llvm_unreachable("Unsupported"); 495 } 496 runAsIntFunction(ExecutorAddr IntFnAddr,int Arg)497 Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override { 498 llvm_unreachable("Unsupported"); 499 } 500 callWrapperAsync(ExecutorAddr WrapperFnAddr,IncomingWFRHandler OnComplete,ArrayRef<char> ArgBuffer)501 void callWrapperAsync(ExecutorAddr WrapperFnAddr, 502 IncomingWFRHandler OnComplete, 503 ArrayRef<char> ArgBuffer) override { 504 llvm_unreachable("Unsupported"); 505 } 506 disconnect()507 Error disconnect() override { return Error::success(); } 508 }; 509 510 /// A ExecutorProcessControl implementation targeting the current process. 511 class SelfExecutorProcessControl : public ExecutorProcessControl, 512 private InProcessMemoryAccess { 513 public: 514 SelfExecutorProcessControl( 515 std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D, 516 Triple TargetTriple, unsigned PageSize, 517 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr); 518 519 /// Create a SelfExecutorProcessControl with the given symbol string pool and 520 /// memory manager. 521 /// If no symbol string pool is given then one will be created. 522 /// If no memory manager is given a jitlink::InProcessMemoryManager will 523 /// be created and used by default. 524 static Expected<std::unique_ptr<SelfExecutorProcessControl>> 525 Create(std::shared_ptr<SymbolStringPool> SSP = nullptr, 526 std::unique_ptr<TaskDispatcher> D = nullptr, 527 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr = nullptr); 528 529 Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override; 530 531 void lookupSymbolsAsync(ArrayRef<LookupRequest> Request, 532 SymbolLookupCompleteFn F) override; 533 534 Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr, 535 ArrayRef<std::string> Args) override; 536 537 Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) override; 538 539 Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override; 540 541 void callWrapperAsync(ExecutorAddr WrapperFnAddr, 542 IncomingWFRHandler OnComplete, 543 ArrayRef<char> ArgBuffer) override; 544 545 Error disconnect() override; 546 547 private: 548 static shared::CWrapperFunctionResult 549 jitDispatchViaWrapperFunctionManager(void *Ctx, const void *FnTag, 550 const char *Data, size_t Size); 551 552 std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr; 553 char GlobalManglingPrefix = 0; 554 }; 555 556 } // end namespace orc 557 } // end namespace llvm 558 559 #endif // LLVM_EXECUTIONENGINE_ORC_EXECUTORPROCESSCONTROL_H 560