blob: 52c8c162ff0b834f34439e53a6e540a40375db9b [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===--- 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
20namespace llvm {
21namespace orc {
22
Andrew Scullcdfcccc2018-10-05 20:58:37 +010023/// 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.
30class SymbolResolver {
31public:
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
43private:
44 virtual void anchor();
45};
46
47/// Implements SymbolResolver with a pair of supplied function objects
48/// for convenience. See createSymbolResolver.
49template <typename LookupFlagsFn, typename LookupFn>
50class LambdaSymbolResolver final : public SymbolResolver {
51public:
52 template <typename LookupFlagsFnRef, typename LookupFnRef>
53 LambdaSymbolResolver(LookupFlagsFnRef &&LookupFlags, LookupFnRef &&Lookup)
54 : LookupFlags(std::forward<LookupFlagsFnRef>(LookupFlags)),
55 Lookup(std::forward<LookupFnRef>(Lookup)) {}
56
57 SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final {
58 return LookupFlags(Symbols);
59 }
60
61 SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
62 SymbolNameSet Symbols) final {
63 return Lookup(std::move(Query), std::move(Symbols));
64 }
65
66private:
67 LookupFlagsFn LookupFlags;
68 LookupFn Lookup;
69};
70
71/// Creates a SymbolResolver implementation from the pair of supplied
72/// function objects.
73template <typename LookupFlagsFn, typename LookupFn>
74std::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>>
79createSymbolResolver(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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010089class JITSymbolResolverAdapter : public JITSymbolResolver {
90public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +010091 JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R,
92 MaterializationResponsibility *MR);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010093 Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) override;
94 Expected<LookupResult> lookup(const LookupSet &Symbols) override;
95
96private:
97 ExecutionSession &ES;
98 std::set<SymbolStringPtr> ResolvedStrings;
99 SymbolResolver &R;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100100 MaterializationResponsibility *MR;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100101};
102
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100103/// Use the given legacy-style FindSymbol function (i.e. a function that
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100104/// 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.
111template <typename FindSymbolFn>
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100112Expected<SymbolFlagsMap> lookupFlagsWithLegacyFn(const SymbolNameSet &Symbols,
113 FindSymbolFn FindSymbol) {
114 SymbolFlagsMap SymbolFlags;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100115
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);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100121 }
122
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100123 return SymbolFlags;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100124}
125
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100126/// Use the given legacy-style FindSymbol function (i.e. a function that
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100127/// 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100130/// error then Query.notifyFailed(...) is called with that error and the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100131/// function returns immediately. On success, returns the set of symbols
132/// not found.
133///
134/// Useful for implementing lookup bodies that query legacy resolvers.
135template <typename FindSymbolFn>
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100136SymbolNameSet
137lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query,
138 const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100139 SymbolNameSet SymbolsNotFound;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100140 bool NewSymbolsResolved = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100141
142 for (auto &S : Symbols) {
143 if (JITSymbol Sym = FindSymbol(*S)) {
144 if (auto Addr = Sym.getAddress()) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100145 Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
146 Query.notifySymbolReady();
147 NewSymbolsResolved = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100148 } else {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100149 ES.legacyFailQuery(Query, Addr.takeError());
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100150 return SymbolNameSet();
151 }
152 } else if (auto Err = Sym.takeError()) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100153 ES.legacyFailQuery(Query, std::move(Err));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100154 return SymbolNameSet();
155 } else
156 SymbolsNotFound.insert(S);
157 }
158
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100159 if (NewSymbolsResolved && Query.isFullyResolved())
160 Query.handleFullyResolved();
161
162 if (NewSymbolsResolved && Query.isFullyReady())
163 Query.handleFullyReady();
164
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100165 return SymbolsNotFound;
166}
167
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100168/// An ORC SymbolResolver implementation that uses a legacy
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100169/// findSymbol-like function to perform lookup;
170template <typename LegacyLookupFn>
171class LegacyLookupFnResolver final : public SymbolResolver {
172public:
173 using ErrorReporter = std::function<void(Error)>;
174
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100175 LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
176 ErrorReporter ReportError)
177 : ES(ES), LegacyLookup(std::move(LegacyLookup)),
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100178 ReportError(std::move(ReportError)) {}
179
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100180 SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final {
181 if (auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup))
182 return std::move(*SymbolFlags);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100183 else {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100184 ReportError(SymbolFlags.takeError());
185 return SymbolFlagsMap();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100186 }
187 }
188
189 SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
190 SymbolNameSet Symbols) final {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100191 return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100192 }
193
194private:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100195 ExecutionSession &ES;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100196 LegacyLookupFn LegacyLookup;
197 ErrorReporter ReportError;
198};
199
200template <typename LegacyLookupFn>
201std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>>
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100202createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100203 std::function<void(Error)> ErrorReporter) {
204 return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>(
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100205 ES, std::move(LegacyLookup), std::move(ErrorReporter));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100206}
207
208} // End namespace orc
209} // End namespace llvm
210
211#endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H