1//===--- SimpleExecutorDylibManager.cpp - Executor-side dylib management --===//
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/TargetProcess/SimpleExecutorDylibManager.h"
10#include "llvm/ExecutionEngine/Orc/Shared/Mangler.h"
11#include "llvm/TargetParser/Host.h"
12#include "llvm/TargetParser/Triple.h"
13
14#include "llvm/ExecutionEngine/Orc/Shared/SPSCI/NativeDylibManagerSPSCI.h"
15
16#include "llvm/Support/MSVCErrorWorkarounds.h"
17
18#include <future>
19
20#define DEBUG_TYPE "orc"
21
22namespace llvm {
23namespace orc {
24namespace rt_bootstrap {
25
26SimpleExecutorDylibManager::~SimpleExecutorDylibManager() {
27 assert(Dylibs.empty() && "shutdown not called?");
28}
29
30Expected<tpctypes::DylibHandle>
31SimpleExecutorDylibManager::open(const std::string &Path, uint64_t Mode) {
32 if (Mode != 0)
33 return make_error<StringError>(Args: "open: non-zero mode bits not yet supported",
34 Args: inconvertibleErrorCode());
35
36 const char *PathCStr = Path.empty() ? nullptr : Path.c_str();
37 std::string ErrMsg;
38
39 auto DL = sys::DynamicLibrary::getPermanentLibrary(filename: PathCStr, errMsg: &ErrMsg);
40 if (!DL.isValid())
41 return make_error<StringError>(Args: std::move(ErrMsg), Args: inconvertibleErrorCode());
42
43 std::lock_guard<std::mutex> Lock(M);
44 auto H = ExecutorAddr::fromPtr(Ptr: DL.getOSSpecificHandle());
45 Resolvers.push_back(x: std::make_unique<DylibSymbolResolver>(args&: H));
46 Dylibs.insert(V: DL.getOSSpecificHandle());
47 return ExecutorAddr::fromPtr(Ptr: Resolvers.back().get());
48}
49
50ExecutorResolver::ResolveResult
51SimpleExecutorDylibManager::resolve(ExecutorAddr Resolver,
52 RemoteSymbolLookupSet Lookup) {
53 using TmpResult = MSVCPExpected<std::vector<std::optional<ExecutorAddr>>>;
54 std::promise<TmpResult> P;
55 auto F = P.get_future();
56 Resolver.toPtr<ExecutorResolver *>()->resolveAsync(
57 L: std::move(Lookup), OnResolve: [&](TmpResult R) { P.set_value(std::move(R)); });
58 return F.get();
59}
60
61Error SimpleExecutorDylibManager::shutdown() {
62
63 DylibSet DS;
64 {
65 std::lock_guard<std::mutex> Lock(M);
66 std::swap(a&: DS, b&: Dylibs);
67 }
68
69 // There is no removal of dylibs at the moment, so nothing to do here.
70 return Error::success();
71}
72
73void SimpleExecutorDylibManager::addBootstrapSymbols(
74 StringMap<ExecutorAddr> &M) {
75 Mangler Mangle{Triple(sys::getProcessTriple())};
76 // SimpleExecutorDylibManager is the LLVM-side implementation of the runtime's
77 // NativeDylibManager controller interface, so it publishes its bootstrap
78 // symbols under the NativeDylibManager_* names. The class itself will be
79 // renamed to NativeDylibManager to match in a future cleanup.
80 M[Mangle.mangledCopy(Name: rt::sps_ci::NativeDylibManagerInstanceName)] =
81 ExecutorAddr::fromPtr(Ptr: this);
82 M[Mangle.mangledCopy(Name: rt::sps_ci::DylibMgrOpen::Name)] =
83 ExecutorAddr::fromPtr(Ptr: &openWrapper);
84 M[Mangle.mangledCopy(Name: rt::sps_ci::DylibMgrResolve::Name)] =
85 ExecutorAddr::fromPtr(Ptr: &resolveWrapper);
86}
87
88llvm::orc::shared::CWrapperFunctionBuffer
89SimpleExecutorDylibManager::openWrapper(const char *ArgData, size_t ArgSize) {
90 return shared::WrapperFunction<rt::sps_ci::DylibMgrOpen::SPSSig>::handle(
91 ArgData, ArgSize,
92 Handler: shared::makeMethodWrapperHandler(
93 Method: &SimpleExecutorDylibManager::open))
94 .release();
95}
96
97llvm::orc::shared::CWrapperFunctionBuffer
98SimpleExecutorDylibManager::resolveWrapper(const char *ArgData,
99 size_t ArgSize) {
100 return shared::WrapperFunction<rt::sps_ci::DylibMgrResolve::SPSSig>::handle(
101 ArgData, ArgSize,
102 Handler: shared::makeMethodWrapperHandler(
103 Method: &SimpleExecutorDylibManager::resolve))
104 .release();
105}
106
107} // namespace rt_bootstrap
108} // end namespace orc
109} // end namespace llvm
110