1//===- LookupAndApply.cpp - Compose a lookup from handlers ----------------===//
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/LookupAndApply.h"
10
11#include "llvm/Support/MSVCErrorWorkarounds.h"
12
13#include <future>
14
15namespace llvm::orc {
16
17void lookupAndApply(unique_function<void(Error)> OnApplied, LookupKind K,
18 const JITDylibSearchOrder &SearchOrder,
19 ArrayRef<LookupPrepareFn> PrepareFns) {
20
21 /// Empty PrepareFns list trivially succeeds.
22 if (PrepareFns.empty())
23 return OnApplied(Error::success());
24
25 /// Otherwise an empty SearchOrder trivially fails: Without it we don't have
26 /// the ExecutionSession that we need to pass into the prepare functions.
27 if (SearchOrder.empty())
28 return OnApplied(
29 make_error<StringError>(Args: "lookupAndApply failed: search order is empty",
30 Args: inconvertibleErrorCode()));
31
32 auto &ES = SearchOrder.front().first->getExecutionSession();
33
34 // Build one Mangler for the whole group, so name-mangling prepare functions
35 // don't each construct their own.
36 Mangler Mangle(ES.getTargetTriple());
37
38 // Collect the symbols to look up. Each prepare function hands back the
39 // applicator that will act on the result; the prepare functions themselves
40 // are not needed beyond this point.
41 SymbolLookupSet Symbols;
42 std::vector<LookupApplyFn> Applies;
43 Applies.reserve(n: PrepareFns.size());
44 for (const auto &PF : PrepareFns)
45 Applies.push_back(x: PF(Symbols, ES, Mangle));
46
47 // PrepareFns are independent, so two of them may legitimately ask for the
48 // same symbol. ExecutionSession::lookup requires a duplicate-free set, and
49 // the applicators read the result by name, so merging here is invisible to
50 // them.
51 Symbols.mergeEntries();
52
53 ES.lookup(
54 K, SearchOrder, Symbols: std::move(Symbols), RequiredState: SymbolState::Ready,
55 NotifyComplete: [Applies = std::move(Applies),
56 OnApplied = std::move(OnApplied)](Expected<SymbolMap> Result) mutable {
57 if (!Result)
58 return OnApplied(Result.takeError());
59 for (auto &Apply : Applies)
60 Apply(*Result);
61 OnApplied(Error::success());
62 },
63 RegisterDependencies: NoDependenciesToRegister);
64}
65
66Error lookupAndApply(LookupKind K, const JITDylibSearchOrder &SearchOrder,
67 ArrayRef<LookupPrepareFn> PrepareFns) {
68 std::promise<MSVCPError> ResultP;
69 auto ResultF = ResultP.get_future();
70 lookupAndApply(OnApplied: [&](Error Err) { ResultP.set_value(std::move(Err)); }, K,
71 SearchOrder, PrepareFns);
72 return ResultF.get();
73}
74
75void lookupAndApply(unique_function<void(Error)> OnApplied, JITDylib &JD,
76 ArrayRef<LookupPrepareFn> PrepareFns) {
77 lookupAndApply(OnApplied: std::move(OnApplied), K: LookupKind::Static,
78 SearchOrder: makeJITDylibSearchOrder(JDs: &JD), PrepareFns);
79}
80
81Error lookupAndApply(JITDylib &JD, ArrayRef<LookupPrepareFn> PrepareFns) {
82 return lookupAndApply(K: LookupKind::Static, SearchOrder: makeJITDylibSearchOrder(JDs: &JD),
83 PrepareFns);
84}
85
86} // namespace llvm::orc
87