1 //===--- Legacy.h -- Adapters for ExecutionEngine API interop ---*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Contains core ORC APIs.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_EXECUTIONENGINE_ORC_LEGACY_H
14 #define LLVM_EXECUTIONENGINE_ORC_LEGACY_H
16 #include "llvm/ExecutionEngine/JITSymbol.h"
17 #include "llvm/ExecutionEngine/Orc/Core.h"
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.
27 /// FIXME: SymbolResolvers should go away and be replaced with VSOs with
28 /// defenition generators.
29 class SymbolResolver
{
31 virtual ~SymbolResolver() = default;
33 /// Returns the subset of the given symbols that the caller is responsible for
35 virtual SymbolNameSet
getResponsibilitySet(const SymbolNameSet
&Symbols
) = 0;
37 /// For each symbol in Symbols that can be found, assigns that symbols
38 /// value in Query. Returns the set of symbols that could not be found.
39 virtual SymbolNameSet
lookup(std::shared_ptr
<AsynchronousSymbolQuery
> Query
,
40 SymbolNameSet Symbols
) = 0;
43 virtual void anchor();
46 /// Implements SymbolResolver with a pair of supplied function objects
47 /// for convenience. See createSymbolResolver.
48 template <typename GetResponsibilitySetFn
, typename LookupFn
>
49 class LambdaSymbolResolver final
: public SymbolResolver
{
51 template <typename GetResponsibilitySetFnRef
, typename LookupFnRef
>
52 LambdaSymbolResolver(GetResponsibilitySetFnRef
&&GetResponsibilitySet
,
54 : GetResponsibilitySet(
55 std::forward
<GetResponsibilitySetFnRef
>(GetResponsibilitySet
)),
56 Lookup(std::forward
<LookupFnRef
>(Lookup
)) {}
58 SymbolNameSet
getResponsibilitySet(const SymbolNameSet
&Symbols
) final
{
59 return GetResponsibilitySet(Symbols
);
62 SymbolNameSet
lookup(std::shared_ptr
<AsynchronousSymbolQuery
> Query
,
63 SymbolNameSet Symbols
) final
{
64 return Lookup(std::move(Query
), std::move(Symbols
));
68 GetResponsibilitySetFn GetResponsibilitySet
;
72 /// Creates a SymbolResolver implementation from the pair of supplied
74 template <typename GetResponsibilitySetFn
, typename LookupFn
>
75 std::unique_ptr
<LambdaSymbolResolver
<
76 typename
std::remove_cv
<
77 typename
std::remove_reference
<GetResponsibilitySetFn
>::type
>::type
,
78 typename
std::remove_cv
<
79 typename
std::remove_reference
<LookupFn
>::type
>::type
>>
80 createSymbolResolver(GetResponsibilitySetFn
&&GetResponsibilitySet
,
82 using LambdaSymbolResolverImpl
= LambdaSymbolResolver
<
83 typename
std::remove_cv
<
84 typename
std::remove_reference
<GetResponsibilitySetFn
>::type
>::type
,
85 typename
std::remove_cv
<
86 typename
std::remove_reference
<LookupFn
>::type
>::type
>;
87 return std::make_unique
<LambdaSymbolResolverImpl
>(
88 std::forward
<GetResponsibilitySetFn
>(GetResponsibilitySet
),
89 std::forward
<LookupFn
>(Lookup
));
92 /// Legacy adapter. Remove once we kill off the old ORC layers.
93 class JITSymbolResolverAdapter
: public JITSymbolResolver
{
95 JITSymbolResolverAdapter(ExecutionSession
&ES
, SymbolResolver
&R
,
96 MaterializationResponsibility
*MR
);
97 Expected
<LookupSet
> getResponsibilitySet(const LookupSet
&Symbols
) override
;
98 void lookup(const LookupSet
&Symbols
, OnResolvedFunction OnResolved
) override
;
101 ExecutionSession
&ES
;
102 std::set
<SymbolStringPtr
> ResolvedStrings
;
104 MaterializationResponsibility
*MR
;
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.
113 /// Useful for implementing getResponsibilitySet bodies that query legacy
115 template <typename FindSymbolFn
>
116 Expected
<SymbolNameSet
>
117 getResponsibilitySetWithLegacyFn(const SymbolNameSet
&Symbols
,
118 FindSymbolFn FindSymbol
) {
119 SymbolNameSet Result
;
121 for (auto &S
: Symbols
) {
122 if (JITSymbol Sym
= FindSymbol(*S
)) {
123 if (!Sym
.getFlags().isStrong())
125 } else if (auto Err
= Sym
.takeError())
126 return std::move(Err
);
132 /// Use the given legacy-style FindSymbol function (i.e. a function that
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
136 /// error then Query.notifyFailed(...) is called with that error and the
137 /// function returns immediately. On success, returns the set of symbols
140 /// Useful for implementing lookup bodies that query legacy resolvers.
141 template <typename FindSymbolFn
>
143 lookupWithLegacyFn(ExecutionSession
&ES
, AsynchronousSymbolQuery
&Query
,
144 const SymbolNameSet
&Symbols
, FindSymbolFn FindSymbol
) {
145 SymbolNameSet SymbolsNotFound
;
146 bool NewSymbolsResolved
= false;
148 for (auto &S
: Symbols
) {
149 if (JITSymbol Sym
= FindSymbol(*S
)) {
150 if (auto Addr
= Sym
.getAddress()) {
151 Query
.notifySymbolMetRequiredState(
152 S
, JITEvaluatedSymbol(*Addr
, Sym
.getFlags()));
153 NewSymbolsResolved
= true;
155 ES
.legacyFailQuery(Query
, Addr
.takeError());
156 return SymbolNameSet();
158 } else if (auto Err
= Sym
.takeError()) {
159 ES
.legacyFailQuery(Query
, std::move(Err
));
160 return SymbolNameSet();
162 SymbolsNotFound
.insert(S
);
165 if (NewSymbolsResolved
&& Query
.isComplete())
166 Query
.handleComplete();
168 return SymbolsNotFound
;
171 /// An ORC SymbolResolver implementation that uses a legacy
172 /// findSymbol-like function to perform lookup;
173 template <typename LegacyLookupFn
>
174 class LegacyLookupFnResolver final
: public SymbolResolver
{
176 using ErrorReporter
= std::function
<void(Error
)>;
178 LegacyLookupFnResolver(ExecutionSession
&ES
, LegacyLookupFn LegacyLookup
,
179 ErrorReporter ReportError
)
180 : ES(ES
), LegacyLookup(std::move(LegacyLookup
)),
181 ReportError(std::move(ReportError
)) {}
183 SymbolNameSet
getResponsibilitySet(const SymbolNameSet
&Symbols
) final
{
184 if (auto ResponsibilitySet
=
185 getResponsibilitySetWithLegacyFn(Symbols
, LegacyLookup
))
186 return std::move(*ResponsibilitySet
);
188 ReportError(ResponsibilitySet
.takeError());
189 return SymbolNameSet();
193 SymbolNameSet
lookup(std::shared_ptr
<AsynchronousSymbolQuery
> Query
,
194 SymbolNameSet Symbols
) final
{
195 return lookupWithLegacyFn(ES
, *Query
, Symbols
, LegacyLookup
);
199 ExecutionSession
&ES
;
200 LegacyLookupFn LegacyLookup
;
201 ErrorReporter ReportError
;
204 template <typename LegacyLookupFn
>
205 std::shared_ptr
<LegacyLookupFnResolver
<LegacyLookupFn
>>
206 createLegacyLookupResolver(ExecutionSession
&ES
, LegacyLookupFn LegacyLookup
,
207 std::function
<void(Error
)> ErrorReporter
) {
208 return std::make_shared
<LegacyLookupFnResolver
<LegacyLookupFn
>>(
209 ES
, std::move(LegacyLookup
), std::move(ErrorReporter
));
212 } // End namespace orc
213 } // End namespace llvm
215 #endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H