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