blob: f9cbbf6ff180fb3f83d006d97804f7ce5435111b [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===--- Legacy.h -- Adapters for ExecutionEngine API interop ---*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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
19namespace llvm {
20namespace orc {
21
Andrew Scullcdfcccc2018-10-05 20:58:37 +010022/// 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.
29class SymbolResolver {
30public:
31 virtual ~SymbolResolver() = default;
32
Andrew Scull0372a572018-11-16 15:47:06 +000033 /// Returns the subset of the given symbols that the caller is responsible for
34 /// materializing.
35 virtual SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) = 0;
Andrew Scullcdfcccc2018-10-05 20:58:37 +010036
37 /// For each symbol in Symbols that can be found, assigns that symbols
Andrew Scull0372a572018-11-16 15:47:06 +000038 /// value in Query. Returns the set of symbols that could not be found.
Andrew Scullcdfcccc2018-10-05 20:58:37 +010039 virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
40 SymbolNameSet Symbols) = 0;
41
42private:
43 virtual void anchor();
44};
45
46/// Implements SymbolResolver with a pair of supplied function objects
47/// for convenience. See createSymbolResolver.
Andrew Scull0372a572018-11-16 15:47:06 +000048template <typename GetResponsibilitySetFn, typename LookupFn>
Andrew Scullcdfcccc2018-10-05 20:58:37 +010049class LambdaSymbolResolver final : public SymbolResolver {
50public:
Andrew Scull0372a572018-11-16 15:47:06 +000051 template <typename GetResponsibilitySetFnRef, typename LookupFnRef>
52 LambdaSymbolResolver(GetResponsibilitySetFnRef &&GetResponsibilitySet,
53 LookupFnRef &&Lookup)
54 : GetResponsibilitySet(
55 std::forward<GetResponsibilitySetFnRef>(GetResponsibilitySet)),
Andrew Scullcdfcccc2018-10-05 20:58:37 +010056 Lookup(std::forward<LookupFnRef>(Lookup)) {}
57
Andrew Scull0372a572018-11-16 15:47:06 +000058 SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
59 return GetResponsibilitySet(Symbols);
Andrew Scullcdfcccc2018-10-05 20:58:37 +010060 }
61
62 SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
63 SymbolNameSet Symbols) final {
64 return Lookup(std::move(Query), std::move(Symbols));
65 }
66
67private:
Andrew Scull0372a572018-11-16 15:47:06 +000068 GetResponsibilitySetFn GetResponsibilitySet;
Andrew Scullcdfcccc2018-10-05 20:58:37 +010069 LookupFn Lookup;
70};
71
72/// Creates a SymbolResolver implementation from the pair of supplied
73/// function objects.
Andrew Scull0372a572018-11-16 15:47:06 +000074template <typename GetResponsibilitySetFn, typename LookupFn>
Andrew Scullcdfcccc2018-10-05 20:58:37 +010075std::unique_ptr<LambdaSymbolResolver<
76 typename std::remove_cv<
Andrew Scull0372a572018-11-16 15:47:06 +000077 typename std::remove_reference<GetResponsibilitySetFn>::type>::type,
Andrew Scullcdfcccc2018-10-05 20:58:37 +010078 typename std::remove_cv<
79 typename std::remove_reference<LookupFn>::type>::type>>
Andrew Scull0372a572018-11-16 15:47:06 +000080createSymbolResolver(GetResponsibilitySetFn &&GetResponsibilitySet,
81 LookupFn &&Lookup) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +010082 using LambdaSymbolResolverImpl = LambdaSymbolResolver<
83 typename std::remove_cv<
Andrew Scull0372a572018-11-16 15:47:06 +000084 typename std::remove_reference<GetResponsibilitySetFn>::type>::type,
Andrew Scullcdfcccc2018-10-05 20:58:37 +010085 typename std::remove_cv<
86 typename std::remove_reference<LookupFn>::type>::type>;
87 return llvm::make_unique<LambdaSymbolResolverImpl>(
Andrew Scull0372a572018-11-16 15:47:06 +000088 std::forward<GetResponsibilitySetFn>(GetResponsibilitySet),
89 std::forward<LookupFn>(Lookup));
Andrew Scullcdfcccc2018-10-05 20:58:37 +010090}
91
Andrew Scull0372a572018-11-16 15:47:06 +000092/// Legacy adapter. Remove once we kill off the old ORC layers.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010093class JITSymbolResolverAdapter : public JITSymbolResolver {
94public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +010095 JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R,
96 MaterializationResponsibility *MR);
Andrew Scull0372a572018-11-16 15:47:06 +000097 Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override;
98 void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010099
100private:
101 ExecutionSession &ES;
102 std::set<SymbolStringPtr> ResolvedStrings;
103 SymbolResolver &R;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100104 MaterializationResponsibility *MR;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100105};
106
Andrew Scull0372a572018-11-16 15:47:06 +0000107/// 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.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100112///
Andrew Scull0372a572018-11-16 15:47:06 +0000113/// Useful for implementing getResponsibilitySet bodies that query legacy
114/// resolvers.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100115template <typename FindSymbolFn>
Andrew Scull0372a572018-11-16 15:47:06 +0000116Expected<SymbolNameSet>
117getResponsibilitySetWithLegacyFn(const SymbolNameSet &Symbols,
118 FindSymbolFn FindSymbol) {
119 SymbolNameSet Result;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100120
121 for (auto &S : Symbols) {
Andrew Scull0372a572018-11-16 15:47:06 +0000122 if (JITSymbol Sym = FindSymbol(*S)) {
123 if (!Sym.getFlags().isStrong())
124 Result.insert(S);
125 } else if (auto Err = Sym.takeError())
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100126 return std::move(Err);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100127 }
128
Andrew Scull0372a572018-11-16 15:47:06 +0000129 return Result;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100130}
131
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100132/// Use the given legacy-style FindSymbol function (i.e. a function that
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100133/// 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100136/// error then Query.notifyFailed(...) is called with that error and the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100137/// function returns immediately. On success, returns the set of symbols
138/// not found.
139///
140/// Useful for implementing lookup bodies that query legacy resolvers.
141template <typename FindSymbolFn>
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100142SymbolNameSet
143lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query,
144 const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100145 SymbolNameSet SymbolsNotFound;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100146 bool NewSymbolsResolved = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100147
148 for (auto &S : Symbols) {
149 if (JITSymbol Sym = FindSymbol(*S)) {
150 if (auto Addr = Sym.getAddress()) {
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100151 Query.notifySymbolMetRequiredState(
152 S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100153 NewSymbolsResolved = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100154 } else {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100155 ES.legacyFailQuery(Query, Addr.takeError());
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100156 return SymbolNameSet();
157 }
158 } else if (auto Err = Sym.takeError()) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100159 ES.legacyFailQuery(Query, std::move(Err));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100160 return SymbolNameSet();
161 } else
162 SymbolsNotFound.insert(S);
163 }
164
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100165 if (NewSymbolsResolved && Query.isComplete())
166 Query.handleComplete();
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100167
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100168 return SymbolsNotFound;
169}
170
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100171/// An ORC SymbolResolver implementation that uses a legacy
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100172/// findSymbol-like function to perform lookup;
173template <typename LegacyLookupFn>
174class LegacyLookupFnResolver final : public SymbolResolver {
175public:
176 using ErrorReporter = std::function<void(Error)>;
177
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100178 LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
179 ErrorReporter ReportError)
180 : ES(ES), LegacyLookup(std::move(LegacyLookup)),
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100181 ReportError(std::move(ReportError)) {}
182
Andrew Scull0372a572018-11-16 15:47:06 +0000183 SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
184 if (auto ResponsibilitySet =
185 getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup))
186 return std::move(*ResponsibilitySet);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100187 else {
Andrew Scull0372a572018-11-16 15:47:06 +0000188 ReportError(ResponsibilitySet.takeError());
189 return SymbolNameSet();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100190 }
191 }
192
193 SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
194 SymbolNameSet Symbols) final {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100195 return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100196 }
197
198private:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100199 ExecutionSession &ES;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100200 LegacyLookupFn LegacyLookup;
201 ErrorReporter ReportError;
202};
203
204template <typename LegacyLookupFn>
205std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>>
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100206createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100207 std::function<void(Error)> ErrorReporter) {
208 return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>(
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100209 ES, std::move(LegacyLookup), std::move(ErrorReporter));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100210}
211
212} // End namespace orc
213} // End namespace llvm
214
215#endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H