xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp (revision 315ee00fa9616b0a192b6834911f98bcf5316a6b)
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  
9  #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
10  
11  #include "llvm/ExecutionEngine/Orc/Core.h"
12  #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
13  #include "llvm/Support/FormatVariadic.h"
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  
22  ExecutorProcessControl::MemoryAccess::~MemoryAccess() = default;
23  
24  ExecutorProcessControl::~ExecutorProcessControl() = default;
25  
26  SelfExecutorProcessControl::SelfExecutorProcessControl(
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>(
35          sys::Process::getPageSizeEstimate());
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  
47  Expected<std::unique_ptr<SelfExecutorProcessControl>>
48  SelfExecutorProcessControl::Create(
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  
64    auto PageSize = sys::Process::getPageSize();
65    if (!PageSize)
66      return PageSize.takeError();
67  
68    Triple TT(sys::getProcessTriple());
69  
70    return std::make_unique<SelfExecutorProcessControl>(
71        std::move(SSP), std::move(D), std::move(TT), *PageSize,
72        std::move(MemMgr));
73  }
74  
75  Expected<tpctypes::DylibHandle>
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  
84  Expected<std::vector<tpctypes::LookupResult>>
85  SelfExecutorProcessControl::lookupSymbols(ArrayRef<LookupRequest> Request) {
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  
109  Expected<int32_t>
110  SelfExecutorProcessControl::runAsMain(ExecutorAddr MainFnAddr,
111                                        ArrayRef<std::string> Args) {
112    using MainTy = int (*)(int, char *[]);
113    return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args);
114  }
115  
116  Expected<int32_t>
117  SelfExecutorProcessControl::runAsVoidFunction(ExecutorAddr VoidFnAddr) {
118    using VoidTy = int (*)();
119    return orc::runAsVoidFunction(VoidFnAddr.toPtr<VoidTy>());
120  }
121  
122  Expected<int32_t>
123  SelfExecutorProcessControl::runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) {
124    using IntTy = int (*)(int);
125    return orc::runAsIntFunction(IntFnAddr.toPtr<IntTy>(), Arg);
126  }
127  
128  void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr,
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  
137  Error SelfExecutorProcessControl::disconnect() {
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)
189        ->getExecutionSession()
190        .runJITDispatchHandler(
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
202