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 typename std::remove_cv<
77 typename std::remove_reference<GetResponsibilitySetFn>::type>::type,
78 typename std::remove_cv<
79 typename std::remove_reference<LookupFn>::type>::type>>
createSymbolResolver(GetResponsibilitySetFn && GetResponsibilitySet,LookupFn && Lookup)80 createSymbolResolver(GetResponsibilitySetFn &&GetResponsibilitySet,
81 LookupFn &&Lookup) {
82 using LambdaSymbolResolverImpl = LambdaSymbolResolver<
83 typename std::remove_cv<
84 typename std::remove_reference<GetResponsibilitySetFn>::type>::type,
85 typename std::remove_cv<
86 typename std::remove_reference<LookupFn>::type>::type>;
87 return std::make_unique<LambdaSymbolResolverImpl>(
88 std::forward<GetResponsibilitySetFn>(GetResponsibilitySet),
89 std::forward<LookupFn>(Lookup));
90 }
91
92 /// Legacy adapter. Remove once we kill off the old ORC layers.
93 class JITSymbolResolverAdapter : public JITSymbolResolver {
94 public:
95 JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R,
96 MaterializationResponsibility *MR);
97 Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override;
98 void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override;
99
100 private:
101 ExecutionSession &ES;
102 std::set<SymbolStringPtr> ResolvedStrings;
103 SymbolResolver &R;
104 MaterializationResponsibility *MR;
105 };
106
107 /// Use the given legacy-style FindSymbol function (i.e. a function that takes
108 /// a const std::string& or StringRef and returns a JITSymbol) to get the
109 /// subset of symbols that the caller is responsible for materializing. If any
110 /// JITSymbol returned by FindSymbol is in an error state the function returns
111 /// immediately with that error.
112 ///
113 /// Useful for implementing getResponsibilitySet bodies that query legacy
114 /// resolvers.
115 template <typename FindSymbolFn>
116 Expected<SymbolNameSet>
getResponsibilitySetWithLegacyFn(const SymbolNameSet & Symbols,FindSymbolFn FindSymbol)117 getResponsibilitySetWithLegacyFn(const SymbolNameSet &Symbols,
118 FindSymbolFn FindSymbol) {
119 SymbolNameSet Result;
120
121 for (auto &S : Symbols) {
122 if (JITSymbol Sym = FindSymbol(*S)) {
123 if (!Sym.getFlags().isStrong())
124 Result.insert(S);
125 } else if (auto Err = Sym.takeError())
126 return std::move(Err);
127 }
128
129 return Result;
130 }
131
132 /// Use the given legacy-style FindSymbol function (i.e. a function that
133 /// takes a const std::string& or StringRef and returns a JITSymbol) to
134 /// find the address and flags for each symbol in Symbols and store the
135 /// result in Query. If any JITSymbol returned by FindSymbol is in an
136 /// error then Query.notifyFailed(...) is called with that error and the
137 /// function returns immediately. On success, returns the set of symbols
138 /// not found.
139 ///
140 /// Useful for implementing lookup bodies that query legacy resolvers.
141 template <typename FindSymbolFn>
142 SymbolNameSet
lookupWithLegacyFn(ExecutionSession & ES,AsynchronousSymbolQuery & Query,const SymbolNameSet & Symbols,FindSymbolFn FindSymbol)143 lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query,
144 const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) {
145 SymbolNameSet SymbolsNotFound;
146 bool NewSymbolsResolved = false;
147
148 for (auto &S : Symbols) {
149 if (JITSymbol Sym = FindSymbol(*S)) {
150 if (auto Addr = Sym.getAddress()) {
151 Query.notifySymbolMetRequiredState(
152 S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
153 NewSymbolsResolved = true;
154 } else {
155 ES.legacyFailQuery(Query, Addr.takeError());
156 return SymbolNameSet();
157 }
158 } else if (auto Err = Sym.takeError()) {
159 ES.legacyFailQuery(Query, std::move(Err));
160 return SymbolNameSet();
161 } else
162 SymbolsNotFound.insert(S);
163 }
164
165 if (NewSymbolsResolved && Query.isComplete())
166 Query.handleComplete();
167
168 return SymbolsNotFound;
169 }
170
171 /// An ORC SymbolResolver implementation that uses a legacy
172 /// findSymbol-like function to perform lookup;
173 template <typename LegacyLookupFn>
174 class LegacyLookupFnResolver final : public SymbolResolver {
175 public:
176 using ErrorReporter = std::function<void(Error)>;
177
LegacyLookupFnResolver(ExecutionSession & ES,LegacyLookupFn LegacyLookup,ErrorReporter ReportError)178 LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
179 ErrorReporter ReportError)
180 : ES(ES), LegacyLookup(std::move(LegacyLookup)),
181 ReportError(std::move(ReportError)) {}
182
getResponsibilitySet(const SymbolNameSet & Symbols)183 SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
184 if (auto ResponsibilitySet =
185 getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup))
186 return std::move(*ResponsibilitySet);
187 else {
188 ReportError(ResponsibilitySet.takeError());
189 return SymbolNameSet();
190 }
191 }
192
lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,SymbolNameSet Symbols)193 SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
194 SymbolNameSet Symbols) final {
195 return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
196 }
197
198 private:
199 ExecutionSession &ES;
200 LegacyLookupFn LegacyLookup;
201 ErrorReporter ReportError;
202 };
203
204 template <typename LegacyLookupFn>
205 std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>>
createLegacyLookupResolver(ExecutionSession & ES,LegacyLookupFn LegacyLookup,std::function<void (Error)> ErrorReporter)206 createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
207 std::function<void(Error)> ErrorReporter) {
208 return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>(
209 ES, std::move(LegacyLookup), std::move(ErrorReporter));
210 }
211
212 } // End namespace orc
213 } // End namespace llvm
214
215 #endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H
216