1 //===--- Legacy.h -- Adapters for ExecutionEngine API interop ---*- 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 // Contains core ORC APIs.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_LEGACY_H
14 #define LLVM_EXECUTIONENGINE_ORC_LEGACY_H
15
16 #include "llvm/ExecutionEngine/JITSymbol.h"
17 #include "llvm/ExecutionEngine/Orc/Core.h"
18
19 namespace llvm {
20 namespace orc {
21
22 /// SymbolResolver is a composable interface for looking up symbol flags
23 /// and addresses using the AsynchronousSymbolQuery type. It will
24 /// eventually replace the LegacyJITSymbolResolver interface as the
25 /// stardard ORC symbol resolver type.
26 ///
27 /// FIXME: SymbolResolvers should go away and be replaced with VSOs with
28 /// defenition generators.
29 class SymbolResolver {
30 public:
31 virtual ~SymbolResolver() = default;
32
33 /// Returns the subset of the given symbols that the caller is responsible for
34 /// materializing.
35 virtual SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) = 0;
36
37 /// For each symbol in Symbols that can be found, assigns that symbols
38 /// value in Query. Returns the set of symbols that could not be found.
39 virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
40 SymbolNameSet Symbols) = 0;
41
42 private:
43 virtual void anchor();
44 };
45
46 /// Implements SymbolResolver with a pair of supplied function objects
47 /// for convenience. See createSymbolResolver.
48 template <typename GetResponsibilitySetFn, typename LookupFn>
49 class LambdaSymbolResolver final : public SymbolResolver {
50 public:
51 template <typename GetResponsibilitySetFnRef, typename LookupFnRef>
LambdaSymbolResolver(GetResponsibilitySetFnRef && GetResponsibilitySet,LookupFnRef && Lookup)52 LambdaSymbolResolver(GetResponsibilitySetFnRef &&GetResponsibilitySet,
53 LookupFnRef &&Lookup)
54 : GetResponsibilitySet(
55 std::forward<GetResponsibilitySetFnRef>(GetResponsibilitySet)),
56 Lookup(std::forward<LookupFnRef>(Lookup)) {}
57
getResponsibilitySet(const SymbolNameSet & Symbols)58 SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
59 return GetResponsibilitySet(Symbols);
60 }
61
lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,SymbolNameSet Symbols)62 SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
63 SymbolNameSet Symbols) final {
64 return Lookup(std::move(Query), std::move(Symbols));
65 }
66
67 private:
68 GetResponsibilitySetFn GetResponsibilitySet;
69 LookupFn Lookup;
70 };
71
72 /// Creates a SymbolResolver implementation from the pair of supplied
73 /// function objects.
74 template <typename GetResponsibilitySetFn, typename LookupFn>
75 std::unique_ptr<LambdaSymbolResolver<
76 std::remove_cv_t<std::remove_reference_t<GetResponsibilitySetFn>>,
77 std::remove_cv_t<std::remove_reference_t<LookupFn>>>>
createSymbolResolver(GetResponsibilitySetFn && GetResponsibilitySet,LookupFn && Lookup)78 createSymbolResolver(GetResponsibilitySetFn &&GetResponsibilitySet,
79 LookupFn &&Lookup) {
80 using LambdaSymbolResolverImpl = LambdaSymbolResolver<
81 std::remove_cv_t<std::remove_reference_t<GetResponsibilitySetFn>>,
82 std::remove_cv_t<std::remove_reference_t<LookupFn>>>;
83 return std::make_unique<LambdaSymbolResolverImpl>(
84 std::forward<GetResponsibilitySetFn>(GetResponsibilitySet),
85 std::forward<LookupFn>(Lookup));
86 }
87
88 /// Legacy adapter. Remove once we kill off the old ORC layers.
89 class JITSymbolResolverAdapter : public JITSymbolResolver {
90 public:
91 JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R,
92 MaterializationResponsibility *MR);
93 Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override;
94 void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override;
95
96 private:
97 ExecutionSession &ES;
98 std::set<SymbolStringPtr> ResolvedStrings;
99 SymbolResolver &R;
100 MaterializationResponsibility *MR;
101 };
102
103 /// Use the given legacy-style FindSymbol function (i.e. a function that takes
104 /// a const std::string& or StringRef and returns a JITSymbol) to get the
105 /// subset of symbols that the caller is responsible for materializing. If any
106 /// JITSymbol returned by FindSymbol is in an error state the function returns
107 /// immediately with that error.
108 ///
109 /// Useful for implementing getResponsibilitySet bodies that query legacy
110 /// resolvers.
111 template <typename FindSymbolFn>
112 Expected<SymbolNameSet>
getResponsibilitySetWithLegacyFn(const SymbolNameSet & Symbols,FindSymbolFn FindSymbol)113 getResponsibilitySetWithLegacyFn(const SymbolNameSet &Symbols,
114 FindSymbolFn FindSymbol) {
115 SymbolNameSet Result;
116
117 for (auto &S : Symbols) {
118 if (JITSymbol Sym = FindSymbol(*S)) {
119 if (!Sym.getFlags().isStrong())
120 Result.insert(S);
121 } else if (auto Err = Sym.takeError())
122 return std::move(Err);
123 }
124
125 return Result;
126 }
127
128 /// Use the given legacy-style FindSymbol function (i.e. a function that
129 /// takes a const std::string& or StringRef and returns a JITSymbol) to
130 /// find the address and flags for each symbol in Symbols and store the
131 /// result in Query. If any JITSymbol returned by FindSymbol is in an
132 /// error then Query.notifyFailed(...) is called with that error and the
133 /// function returns immediately. On success, returns the set of symbols
134 /// not found.
135 ///
136 /// Useful for implementing lookup bodies that query legacy resolvers.
137 template <typename FindSymbolFn>
138 SymbolNameSet
lookupWithLegacyFn(ExecutionSession & ES,AsynchronousSymbolQuery & Query,const SymbolNameSet & Symbols,FindSymbolFn FindSymbol)139 lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query,
140 const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) {
141 SymbolNameSet SymbolsNotFound;
142 bool NewSymbolsResolved = false;
143
144 for (auto &S : Symbols) {
145 if (JITSymbol Sym = FindSymbol(*S)) {
146 if (auto Addr = Sym.getAddress()) {
147 Query.notifySymbolMetRequiredState(
148 S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
149 NewSymbolsResolved = true;
150 } else {
151 ES.legacyFailQuery(Query, Addr.takeError());
152 return SymbolNameSet();
153 }
154 } else if (auto Err = Sym.takeError()) {
155 ES.legacyFailQuery(Query, std::move(Err));
156 return SymbolNameSet();
157 } else
158 SymbolsNotFound.insert(S);
159 }
160
161 if (NewSymbolsResolved && Query.isComplete())
162 Query.handleComplete();
163
164 return SymbolsNotFound;
165 }
166
167 /// An ORC SymbolResolver implementation that uses a legacy
168 /// findSymbol-like function to perform lookup;
169 template <typename LegacyLookupFn>
170 class LegacyLookupFnResolver final : public SymbolResolver {
171 public:
172 using ErrorReporter = std::function<void(Error)>;
173
LegacyLookupFnResolver(ExecutionSession & ES,LegacyLookupFn LegacyLookup,ErrorReporter ReportError)174 LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
175 ErrorReporter ReportError)
176 : ES(ES), LegacyLookup(std::move(LegacyLookup)),
177 ReportError(std::move(ReportError)) {}
178
getResponsibilitySet(const SymbolNameSet & Symbols)179 SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
180 if (auto ResponsibilitySet =
181 getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup))
182 return std::move(*ResponsibilitySet);
183 else {
184 ReportError(ResponsibilitySet.takeError());
185 return SymbolNameSet();
186 }
187 }
188
lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,SymbolNameSet Symbols)189 SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
190 SymbolNameSet Symbols) final {
191 return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
192 }
193
194 private:
195 ExecutionSession &ES;
196 LegacyLookupFn LegacyLookup;
197 ErrorReporter ReportError;
198 };
199
200 template <typename LegacyLookupFn>
201 std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>>
createLegacyLookupResolver(ExecutionSession & ES,LegacyLookupFn LegacyLookup,std::function<void (Error)> ErrorReporter)202 createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
203 std::function<void(Error)> ErrorReporter) {
204 return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>(
205 ES, std::move(LegacyLookup), std::move(ErrorReporter));
206 }
207
208 } // End namespace orc
209 } // End namespace llvm
210
211 #endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H
212