Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1 | //===--- Legacy.h -- Adapters for ExecutionEngine API interop ---*- C++ -*-===// |
| 2 | // |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 3 | // 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 Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 6 | // |
| 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 | |
| 19 | namespace llvm { |
| 20 | namespace orc { |
| 21 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 22 | /// 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. |
| 29 | class SymbolResolver { |
| 30 | public: |
| 31 | virtual ~SymbolResolver() = default; |
| 32 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 33 | /// Returns the subset of the given symbols that the caller is responsible for |
| 34 | /// materializing. |
| 35 | virtual SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) = 0; |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 36 | |
| 37 | /// For each symbol in Symbols that can be found, assigns that symbols |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 38 | /// value in Query. Returns the set of symbols that could not be found. |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 39 | virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, |
| 40 | SymbolNameSet Symbols) = 0; |
| 41 | |
| 42 | private: |
| 43 | virtual void anchor(); |
| 44 | }; |
| 45 | |
| 46 | /// Implements SymbolResolver with a pair of supplied function objects |
| 47 | /// for convenience. See createSymbolResolver. |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 48 | template <typename GetResponsibilitySetFn, typename LookupFn> |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 49 | class LambdaSymbolResolver final : public SymbolResolver { |
| 50 | public: |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 51 | template <typename GetResponsibilitySetFnRef, typename LookupFnRef> |
| 52 | LambdaSymbolResolver(GetResponsibilitySetFnRef &&GetResponsibilitySet, |
| 53 | LookupFnRef &&Lookup) |
| 54 | : GetResponsibilitySet( |
| 55 | std::forward<GetResponsibilitySetFnRef>(GetResponsibilitySet)), |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 56 | Lookup(std::forward<LookupFnRef>(Lookup)) {} |
| 57 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 58 | SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final { |
| 59 | return GetResponsibilitySet(Symbols); |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 60 | } |
| 61 | |
| 62 | SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, |
| 63 | SymbolNameSet Symbols) final { |
| 64 | return Lookup(std::move(Query), std::move(Symbols)); |
| 65 | } |
| 66 | |
| 67 | private: |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 68 | GetResponsibilitySetFn GetResponsibilitySet; |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 69 | LookupFn Lookup; |
| 70 | }; |
| 71 | |
| 72 | /// Creates a SymbolResolver implementation from the pair of supplied |
| 73 | /// function objects. |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 74 | template <typename GetResponsibilitySetFn, typename LookupFn> |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 75 | std::unique_ptr<LambdaSymbolResolver< |
| 76 | typename std::remove_cv< |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 77 | typename std::remove_reference<GetResponsibilitySetFn>::type>::type, |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 78 | typename std::remove_cv< |
| 79 | typename std::remove_reference<LookupFn>::type>::type>> |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 80 | createSymbolResolver(GetResponsibilitySetFn &&GetResponsibilitySet, |
| 81 | LookupFn &&Lookup) { |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 82 | using LambdaSymbolResolverImpl = LambdaSymbolResolver< |
| 83 | typename std::remove_cv< |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 84 | typename std::remove_reference<GetResponsibilitySetFn>::type>::type, |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 85 | typename std::remove_cv< |
| 86 | typename std::remove_reference<LookupFn>::type>::type>; |
| 87 | return llvm::make_unique<LambdaSymbolResolverImpl>( |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 88 | std::forward<GetResponsibilitySetFn>(GetResponsibilitySet), |
| 89 | std::forward<LookupFn>(Lookup)); |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 90 | } |
| 91 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 92 | /// Legacy adapter. Remove once we kill off the old ORC layers. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 93 | class JITSymbolResolverAdapter : public JITSymbolResolver { |
| 94 | public: |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 95 | JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R, |
| 96 | MaterializationResponsibility *MR); |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 97 | Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override; |
| 98 | void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 99 | |
| 100 | private: |
| 101 | ExecutionSession &ES; |
| 102 | std::set<SymbolStringPtr> ResolvedStrings; |
| 103 | SymbolResolver &R; |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 104 | MaterializationResponsibility *MR; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 105 | }; |
| 106 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 107 | /// 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 Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 112 | /// |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 113 | /// Useful for implementing getResponsibilitySet bodies that query legacy |
| 114 | /// resolvers. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 115 | template <typename FindSymbolFn> |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 116 | Expected<SymbolNameSet> |
| 117 | getResponsibilitySetWithLegacyFn(const SymbolNameSet &Symbols, |
| 118 | FindSymbolFn FindSymbol) { |
| 119 | SymbolNameSet Result; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 120 | |
| 121 | for (auto &S : Symbols) { |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 122 | if (JITSymbol Sym = FindSymbol(*S)) { |
| 123 | if (!Sym.getFlags().isStrong()) |
| 124 | Result.insert(S); |
| 125 | } else if (auto Err = Sym.takeError()) |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 126 | return std::move(Err); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 127 | } |
| 128 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 129 | return Result; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 130 | } |
| 131 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 132 | /// Use the given legacy-style FindSymbol function (i.e. a function that |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 133 | /// 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 Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 136 | /// error then Query.notifyFailed(...) is called with that error and the |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 137 | /// function returns immediately. On success, returns the set of symbols |
| 138 | /// not found. |
| 139 | /// |
| 140 | /// Useful for implementing lookup bodies that query legacy resolvers. |
| 141 | template <typename FindSymbolFn> |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 142 | SymbolNameSet |
| 143 | lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query, |
| 144 | const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 145 | SymbolNameSet SymbolsNotFound; |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 146 | bool NewSymbolsResolved = false; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 147 | |
| 148 | for (auto &S : Symbols) { |
| 149 | if (JITSymbol Sym = FindSymbol(*S)) { |
| 150 | if (auto Addr = Sym.getAddress()) { |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame^] | 151 | Query.notifySymbolMetRequiredState( |
| 152 | S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 153 | NewSymbolsResolved = true; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 154 | } else { |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 155 | ES.legacyFailQuery(Query, Addr.takeError()); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 156 | return SymbolNameSet(); |
| 157 | } |
| 158 | } else if (auto Err = Sym.takeError()) { |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 159 | ES.legacyFailQuery(Query, std::move(Err)); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 160 | return SymbolNameSet(); |
| 161 | } else |
| 162 | SymbolsNotFound.insert(S); |
| 163 | } |
| 164 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame^] | 165 | if (NewSymbolsResolved && Query.isComplete()) |
| 166 | Query.handleComplete(); |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 167 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 168 | return SymbolsNotFound; |
| 169 | } |
| 170 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 171 | /// An ORC SymbolResolver implementation that uses a legacy |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 172 | /// findSymbol-like function to perform lookup; |
| 173 | template <typename LegacyLookupFn> |
| 174 | class LegacyLookupFnResolver final : public SymbolResolver { |
| 175 | public: |
| 176 | using ErrorReporter = std::function<void(Error)>; |
| 177 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 178 | LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup, |
| 179 | ErrorReporter ReportError) |
| 180 | : ES(ES), LegacyLookup(std::move(LegacyLookup)), |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 181 | ReportError(std::move(ReportError)) {} |
| 182 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 183 | SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final { |
| 184 | if (auto ResponsibilitySet = |
| 185 | getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup)) |
| 186 | return std::move(*ResponsibilitySet); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 187 | else { |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 188 | ReportError(ResponsibilitySet.takeError()); |
| 189 | return SymbolNameSet(); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 190 | } |
| 191 | } |
| 192 | |
| 193 | SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, |
| 194 | SymbolNameSet Symbols) final { |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 195 | return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 196 | } |
| 197 | |
| 198 | private: |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 199 | ExecutionSession &ES; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 200 | LegacyLookupFn LegacyLookup; |
| 201 | ErrorReporter ReportError; |
| 202 | }; |
| 203 | |
| 204 | template <typename LegacyLookupFn> |
| 205 | std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>> |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 206 | createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup, |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 207 | std::function<void(Error)> ErrorReporter) { |
| 208 | return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>( |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 209 | ES, std::move(LegacyLookup), std::move(ErrorReporter)); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 210 | } |
| 211 | |
| 212 | } // End namespace orc |
| 213 | } // End namespace llvm |
| 214 | |
| 215 | #endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H |