1 //===--- Legacy.h -- Adapters for ExecutionEngine API interop ---*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Contains core ORC APIs.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_EXECUTIONENGINE_ORC_LEGACY_H
15 #define LLVM_EXECUTIONENGINE_ORC_LEGACY_H
17 #include "llvm/ExecutionEngine/JITSymbol.h"
18 #include "llvm/ExecutionEngine/Orc/Core.h"
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.
28 /// FIXME: SymbolResolvers should go away and be replaced with VSOs with
29 /// defenition generators.
30 class SymbolResolver {
32 virtual ~SymbolResolver() = default;
34 /// Returns the subset of the given symbols that the caller is responsible for
36 virtual SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) = 0;
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;
44 virtual void anchor();
47 /// Implements SymbolResolver with a pair of supplied function objects
48 /// for convenience. See createSymbolResolver.
49 template <typename GetResponsibilitySetFn, typename LookupFn>
50 class LambdaSymbolResolver final : public SymbolResolver {
52 template <typename GetResponsibilitySetFnRef, typename LookupFnRef>
53 LambdaSymbolResolver(GetResponsibilitySetFnRef &&GetResponsibilitySet,
55 : GetResponsibilitySet(
56 std::forward<GetResponsibilitySetFnRef>(GetResponsibilitySet)),
57 Lookup(std::forward<LookupFnRef>(Lookup)) {}
59 SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
60 return GetResponsibilitySet(Symbols);
63 SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
64 SymbolNameSet Symbols) final {
65 return Lookup(std::move(Query), std::move(Symbols));
69 GetResponsibilitySetFn GetResponsibilitySet;
73 /// Creates a SymbolResolver implementation from the pair of supplied
75 template <typename GetResponsibilitySetFn, typename LookupFn>
76 std::unique_ptr<LambdaSymbolResolver<
77 typename std::remove_cv<
78 typename std::remove_reference<GetResponsibilitySetFn>::type>::type,
79 typename std::remove_cv<
80 typename std::remove_reference<LookupFn>::type>::type>>
81 createSymbolResolver(GetResponsibilitySetFn &&GetResponsibilitySet,
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 std::forward<LookupFn>(Lookup));
93 /// Legacy adapter. Remove once we kill off the old ORC layers.
94 class JITSymbolResolverAdapter : public JITSymbolResolver {
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;
102 ExecutionSession &ES;
103 std::set<SymbolStringPtr> ResolvedStrings;
105 MaterializationResponsibility *MR;
108 /// 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.
114 /// Useful for implementing getResponsibilitySet bodies that query legacy
116 template <typename FindSymbolFn>
117 Expected<SymbolNameSet>
118 getResponsibilitySetWithLegacyFn(const SymbolNameSet &Symbols,
119 FindSymbolFn FindSymbol) {
120 SymbolNameSet Result;
122 for (auto &S : Symbols) {
123 if (JITSymbol Sym = FindSymbol(*S)) {
124 if (!Sym.getFlags().isStrong())
126 } else if (auto Err = Sym.takeError())
127 return std::move(Err);
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 /// result in Query. If any JITSymbol returned by FindSymbol is in an
137 /// error then Query.notifyFailed(...) is called with that error and the
138 /// function returns immediately. On success, returns the set of symbols
141 /// Useful for implementing lookup bodies that query legacy resolvers.
142 template <typename FindSymbolFn>
144 lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query,
145 const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) {
146 SymbolNameSet SymbolsNotFound;
147 bool NewSymbolsResolved = false;
149 for (auto &S : Symbols) {
150 if (JITSymbol Sym = FindSymbol(*S)) {
151 if (auto Addr = Sym.getAddress()) {
152 Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
153 Query.notifySymbolReady();
154 NewSymbolsResolved = true;
156 ES.legacyFailQuery(Query, Addr.takeError());
157 return SymbolNameSet();
159 } else if (auto Err = Sym.takeError()) {
160 ES.legacyFailQuery(Query, std::move(Err));
161 return SymbolNameSet();
163 SymbolsNotFound.insert(S);
166 if (NewSymbolsResolved && Query.isFullyResolved())
167 Query.handleFullyResolved();
169 if (NewSymbolsResolved && Query.isFullyReady())
170 Query.handleFullyReady();
172 return SymbolsNotFound;
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 {
180 using ErrorReporter = std::function<void(Error)>;
182 LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
183 ErrorReporter ReportError)
184 : ES(ES), LegacyLookup(std::move(LegacyLookup)),
185 ReportError(std::move(ReportError)) {}
187 SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
188 if (auto ResponsibilitySet =
189 getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup))
190 return std::move(*ResponsibilitySet);
192 ReportError(ResponsibilitySet.takeError());
193 return SymbolNameSet();
197 SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
198 SymbolNameSet Symbols) final {
199 return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
203 ExecutionSession &ES;
204 LegacyLookupFn LegacyLookup;
205 ErrorReporter ReportError;
208 template <typename LegacyLookupFn>
209 std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>>
210 createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
211 std::function<void(Error)> ErrorReporter) {
212 return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>(
213 ES, std::move(LegacyLookup), std::move(ErrorReporter));
216 } // End namespace orc
217 } // End namespace llvm
219 #endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H