blob: 4c6162ac4b8b4bea1d00d0b683c28c380904ebbd [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
Andrew Scull0372a572018-11-16 15:47:06 +000034 /// Returns the subset of the given symbols that the caller is responsible for
35 /// materializing.
36 virtual SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) = 0;
Andrew Scullcdfcccc2018-10-05 20:58:37 +010037
38 /// For each symbol in Symbols that can be found, assigns that symbols
Andrew Scull0372a572018-11-16 15:47:06 +000039 /// value in Query. Returns the set of symbols that could not be found.
Andrew Scullcdfcccc2018-10-05 20:58:37 +010040 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.
Andrew Scull0372a572018-11-16 15:47:06 +000049template <typename GetResponsibilitySetFn, typename LookupFn>
Andrew Scullcdfcccc2018-10-05 20:58:37 +010050class LambdaSymbolResolver final : public SymbolResolver {
51public:
Andrew Scull0372a572018-11-16 15:47:06 +000052 template <typename GetResponsibilitySetFnRef, typename LookupFnRef>
53 LambdaSymbolResolver(GetResponsibilitySetFnRef &&GetResponsibilitySet,
54 LookupFnRef &&Lookup)
55 : GetResponsibilitySet(
56 std::forward<GetResponsibilitySetFnRef>(GetResponsibilitySet)),
Andrew Scullcdfcccc2018-10-05 20:58:37 +010057 Lookup(std::forward<LookupFnRef>(Lookup)) {}
58
Andrew Scull0372a572018-11-16 15:47:06 +000059 SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
60 return GetResponsibilitySet(Symbols);
Andrew Scullcdfcccc2018-10-05 20:58:37 +010061 }
62
63 SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
64 SymbolNameSet Symbols) final {
65 return Lookup(std::move(Query), std::move(Symbols));
66 }
67
68private:
Andrew Scull0372a572018-11-16 15:47:06 +000069 GetResponsibilitySetFn GetResponsibilitySet;
Andrew Scullcdfcccc2018-10-05 20:58:37 +010070 LookupFn Lookup;
71};
72
73/// Creates a SymbolResolver implementation from the pair of supplied
74/// function objects.
Andrew Scull0372a572018-11-16 15:47:06 +000075template <typename GetResponsibilitySetFn, typename LookupFn>
Andrew Scullcdfcccc2018-10-05 20:58:37 +010076std::unique_ptr<LambdaSymbolResolver<
77 typename std::remove_cv<
Andrew Scull0372a572018-11-16 15:47:06 +000078 typename std::remove_reference<GetResponsibilitySetFn>::type>::type,
Andrew Scullcdfcccc2018-10-05 20:58:37 +010079 typename std::remove_cv<
80 typename std::remove_reference<LookupFn>::type>::type>>
Andrew Scull0372a572018-11-16 15:47:06 +000081createSymbolResolver(GetResponsibilitySetFn &&GetResponsibilitySet,
82 LookupFn &&Lookup) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +010083 using LambdaSymbolResolverImpl = LambdaSymbolResolver<
84 typename std::remove_cv<
Andrew Scull0372a572018-11-16 15:47:06 +000085 typename std::remove_reference<GetResponsibilitySetFn>::type>::type,
Andrew Scullcdfcccc2018-10-05 20:58:37 +010086 typename std::remove_cv<
87 typename std::remove_reference<LookupFn>::type>::type>;
88 return llvm::make_unique<LambdaSymbolResolverImpl>(
Andrew Scull0372a572018-11-16 15:47:06 +000089 std::forward<GetResponsibilitySetFn>(GetResponsibilitySet),
90 std::forward<LookupFn>(Lookup));
Andrew Scullcdfcccc2018-10-05 20:58:37 +010091}
92
Andrew Scull0372a572018-11-16 15:47:06 +000093/// Legacy adapter. Remove once we kill off the old ORC layers.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010094class JITSymbolResolverAdapter : public JITSymbolResolver {
95public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +010096 JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R,
97 MaterializationResponsibility *MR);
Andrew Scull0372a572018-11-16 15:47:06 +000098 Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override;
99 void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100100
101private:
102 ExecutionSession &ES;
103 std::set<SymbolStringPtr> ResolvedStrings;
104 SymbolResolver &R;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100105 MaterializationResponsibility *MR;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100106};
107
Andrew Scull0372a572018-11-16 15:47:06 +0000108/// 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.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100113///
Andrew Scull0372a572018-11-16 15:47:06 +0000114/// Useful for implementing getResponsibilitySet bodies that query legacy
115/// resolvers.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100116template <typename FindSymbolFn>
Andrew Scull0372a572018-11-16 15:47:06 +0000117Expected<SymbolNameSet>
118getResponsibilitySetWithLegacyFn(const SymbolNameSet &Symbols,
119 FindSymbolFn FindSymbol) {
120 SymbolNameSet Result;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100121
122 for (auto &S : Symbols) {
Andrew Scull0372a572018-11-16 15:47:06 +0000123 if (JITSymbol Sym = FindSymbol(*S)) {
124 if (!Sym.getFlags().isStrong())
125 Result.insert(S);
126 } else if (auto Err = Sym.takeError())
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100127 return std::move(Err);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100128 }
129
Andrew Scull0372a572018-11-16 15:47:06 +0000130 return Result;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100131}
132
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100133/// Use the given legacy-style FindSymbol function (i.e. a function that
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100134/// 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100137/// error then Query.notifyFailed(...) is called with that error and the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100138/// function returns immediately. On success, returns the set of symbols
139/// not found.
140///
141/// Useful for implementing lookup bodies that query legacy resolvers.
142template <typename FindSymbolFn>
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100143SymbolNameSet
144lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query,
145 const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100146 SymbolNameSet SymbolsNotFound;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100147 bool NewSymbolsResolved = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100148
149 for (auto &S : Symbols) {
150 if (JITSymbol Sym = FindSymbol(*S)) {
151 if (auto Addr = Sym.getAddress()) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100152 Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
153 Query.notifySymbolReady();
154 NewSymbolsResolved = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100155 } else {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100156 ES.legacyFailQuery(Query, Addr.takeError());
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100157 return SymbolNameSet();
158 }
159 } else if (auto Err = Sym.takeError()) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100160 ES.legacyFailQuery(Query, std::move(Err));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100161 return SymbolNameSet();
162 } else
163 SymbolsNotFound.insert(S);
164 }
165
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100166 if (NewSymbolsResolved && Query.isFullyResolved())
167 Query.handleFullyResolved();
168
169 if (NewSymbolsResolved && Query.isFullyReady())
170 Query.handleFullyReady();
171
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100172 return SymbolsNotFound;
173}
174
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100175/// An ORC SymbolResolver implementation that uses a legacy
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100176/// findSymbol-like function to perform lookup;
177template <typename LegacyLookupFn>
178class LegacyLookupFnResolver final : public SymbolResolver {
179public:
180 using ErrorReporter = std::function<void(Error)>;
181
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100182 LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
183 ErrorReporter ReportError)
184 : ES(ES), LegacyLookup(std::move(LegacyLookup)),
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100185 ReportError(std::move(ReportError)) {}
186
Andrew Scull0372a572018-11-16 15:47:06 +0000187 SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
188 if (auto ResponsibilitySet =
189 getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup))
190 return std::move(*ResponsibilitySet);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100191 else {
Andrew Scull0372a572018-11-16 15:47:06 +0000192 ReportError(ResponsibilitySet.takeError());
193 return SymbolNameSet();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100194 }
195 }
196
197 SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
198 SymbolNameSet Symbols) final {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100199 return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100200 }
201
202private:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100203 ExecutionSession &ES;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100204 LegacyLookupFn LegacyLookup;
205 ErrorReporter ReportError;
206};
207
208template <typename LegacyLookupFn>
209std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>>
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100210createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100211 std::function<void(Error)> ErrorReporter) {
212 return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>(
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100213 ES, std::move(LegacyLookup), std::move(ErrorReporter));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100214}
215
216} // End namespace orc
217} // End namespace llvm
218
219#endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H