blob: e0e552652769eee47458fe791496a44e62a9db16 [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 Scullcdfcccc2018-10-05 20:58:37 +0100151 Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
152 Query.notifySymbolReady();
153 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 Scullcdfcccc2018-10-05 20:58:37 +0100165 if (NewSymbolsResolved && Query.isFullyResolved())
166 Query.handleFullyResolved();
167
168 if (NewSymbolsResolved && Query.isFullyReady())
169 Query.handleFullyReady();
170
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100171 return SymbolsNotFound;
172}
173
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100174/// An ORC SymbolResolver implementation that uses a legacy
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100175/// findSymbol-like function to perform lookup;
176template <typename LegacyLookupFn>
177class LegacyLookupFnResolver final : public SymbolResolver {
178public:
179 using ErrorReporter = std::function<void(Error)>;
180
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100181 LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
182 ErrorReporter ReportError)
183 : ES(ES), LegacyLookup(std::move(LegacyLookup)),
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100184 ReportError(std::move(ReportError)) {}
185
Andrew Scull0372a572018-11-16 15:47:06 +0000186 SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
187 if (auto ResponsibilitySet =
188 getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup))
189 return std::move(*ResponsibilitySet);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100190 else {
Andrew Scull0372a572018-11-16 15:47:06 +0000191 ReportError(ResponsibilitySet.takeError());
192 return SymbolNameSet();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100193 }
194 }
195
196 SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
197 SymbolNameSet Symbols) final {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100198 return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100199 }
200
201private:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100202 ExecutionSession &ES;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100203 LegacyLookupFn LegacyLookup;
204 ErrorReporter ReportError;
205};
206
207template <typename LegacyLookupFn>
208std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>>
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100209createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100210 std::function<void(Error)> ErrorReporter) {
211 return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>(
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100212 ES, std::move(LegacyLookup), std::move(ErrorReporter));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100213}
214
215} // End namespace orc
216} // End namespace llvm
217
218#endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H