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 virtual ~SymbolResolver() = default;
33
34 /// Returns the flags for each symbol in Symbols that can be found,
35 /// along with the set of symbol that could not be found.
36 virtual SymbolFlagsMap lookupFlags(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 LookupFlagsFn, typename LookupFn>
50 class LambdaSymbolResolver final : public SymbolResolver {
51 public:
52 template <typename LookupFlagsFnRef, typename LookupFnRef>
LambdaSymbolResolver(LookupFlagsFnRef && LookupFlags,LookupFnRef && Lookup)53 LambdaSymbolResolver(LookupFlagsFnRef &&LookupFlags, LookupFnRef &&Lookup)
54 : LookupFlags(std::forward<LookupFlagsFnRef>(LookupFlags)),
55 Lookup(std::forward<LookupFnRef>(Lookup)) {}
56
lookupFlags(const SymbolNameSet & Symbols)57 SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final {
58 return LookupFlags(Symbols);
59 }
60
lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,SymbolNameSet Symbols)61 SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
62 SymbolNameSet Symbols) final {
63 return Lookup(std::move(Query), std::move(Symbols));
64 }
65
66 private:
67 LookupFlagsFn LookupFlags;
68 LookupFn Lookup;
69 };
70
71 /// Creates a SymbolResolver implementation from the pair of supplied
72 /// function objects.
73 template <typename LookupFlagsFn, typename LookupFn>
74 std::unique_ptr<LambdaSymbolResolver<
75 typename std::remove_cv<
76 typename std::remove_reference<LookupFlagsFn>::type>::type,
77 typename std::remove_cv<
78 typename std::remove_reference<LookupFn>::type>::type>>
createSymbolResolver(LookupFlagsFn && LookupFlags,LookupFn && Lookup)79 createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) {
80 using LambdaSymbolResolverImpl = LambdaSymbolResolver<
81 typename std::remove_cv<
82 typename std::remove_reference<LookupFlagsFn>::type>::type,
83 typename std::remove_cv<
84 typename std::remove_reference<LookupFn>::type>::type>;
85 return llvm::make_unique<LambdaSymbolResolverImpl>(
86 std::forward<LookupFlagsFn>(LookupFlags), std::forward<LookupFn>(Lookup));
87 }
88
89 class JITSymbolResolverAdapter : public JITSymbolResolver {
90 public:
91 JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R,
92 MaterializationResponsibility *MR);
93 Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) override;
94 Expected<LookupResult> lookup(const LookupSet &Symbols) 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
104 /// takes a const std::string& or StringRef and returns a JITSymbol) to
105 /// find the flags for each symbol in Symbols and store their flags in
106 /// SymbolFlags. If any JITSymbol returned by FindSymbol is in an error
107 /// state the function returns immediately with that error, otherwise it
108 /// returns the set of symbols not found.
109 ///
110 /// Useful for implementing lookupFlags bodies that query legacy resolvers.
111 template <typename FindSymbolFn>
lookupFlagsWithLegacyFn(const SymbolNameSet & Symbols,FindSymbolFn FindSymbol)112 Expected<SymbolFlagsMap> lookupFlagsWithLegacyFn(const SymbolNameSet &Symbols,
113 FindSymbolFn FindSymbol) {
114 SymbolFlagsMap SymbolFlags;
115
116 for (auto &S : Symbols) {
117 if (JITSymbol Sym = FindSymbol(*S))
118 SymbolFlags[S] = Sym.getFlags();
119 else if (auto Err = Sym.takeError())
120 return std::move(Err);
121 }
122
123 return SymbolFlags;
124 }
125
126 /// Use the given legacy-style FindSymbol function (i.e. a function that
127 /// takes a const std::string& or StringRef and returns a JITSymbol) to
128 /// find the address and flags for each symbol in Symbols and store the
129 /// result in Query. If any JITSymbol returned by FindSymbol is in an
130 /// error then Query.notifyFailed(...) is called with that error and the
131 /// function returns immediately. On success, returns the set of symbols
132 /// not found.
133 ///
134 /// Useful for implementing lookup bodies that query legacy resolvers.
135 template <typename FindSymbolFn>
136 SymbolNameSet
lookupWithLegacyFn(ExecutionSession & ES,AsynchronousSymbolQuery & Query,const SymbolNameSet & Symbols,FindSymbolFn FindSymbol)137 lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query,
138 const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) {
139 SymbolNameSet SymbolsNotFound;
140 bool NewSymbolsResolved = false;
141
142 for (auto &S : Symbols) {
143 if (JITSymbol Sym = FindSymbol(*S)) {
144 if (auto Addr = Sym.getAddress()) {
145 Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
146 Query.notifySymbolReady();
147 NewSymbolsResolved = true;
148 } else {
149 ES.legacyFailQuery(Query, Addr.takeError());
150 return SymbolNameSet();
151 }
152 } else if (auto Err = Sym.takeError()) {
153 ES.legacyFailQuery(Query, std::move(Err));
154 return SymbolNameSet();
155 } else
156 SymbolsNotFound.insert(S);
157 }
158
159 if (NewSymbolsResolved && Query.isFullyResolved())
160 Query.handleFullyResolved();
161
162 if (NewSymbolsResolved && Query.isFullyReady())
163 Query.handleFullyReady();
164
165 return SymbolsNotFound;
166 }
167
168 /// An ORC SymbolResolver implementation that uses a legacy
169 /// findSymbol-like function to perform lookup;
170 template <typename LegacyLookupFn>
171 class LegacyLookupFnResolver final : public SymbolResolver {
172 public:
173 using ErrorReporter = std::function<void(Error)>;
174
LegacyLookupFnResolver(ExecutionSession & ES,LegacyLookupFn LegacyLookup,ErrorReporter ReportError)175 LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
176 ErrorReporter ReportError)
177 : ES(ES), LegacyLookup(std::move(LegacyLookup)),
178 ReportError(std::move(ReportError)) {}
179
lookupFlags(const SymbolNameSet & Symbols)180 SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final {
181 if (auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup))
182 return std::move(*SymbolFlags);
183 else {
184 ReportError(SymbolFlags.takeError());
185 return SymbolFlagsMap();
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