[llvm] r323375 - [ORC] Add a LambdaSymbolResolver convenience class and docs for SymbolResolver.
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 24 13:21:11 PST 2018
Author: lhames
Date: Wed Jan 24 13:21:10 2018
New Revision: 323375
URL: http://llvm.org/viewvc/llvm-project?rev=323375&view=rev
Log:
[ORC] Add a LambdaSymbolResolver convenience class and docs for SymbolResolver.
This patch adds a LambdaSymbolResolver convenience utility that can create an
orc::SymbolResolver from a pair of function objects that supply the behavior for
the lookupFlags and lookup methods.
This class plays the same role for orc::SymbolResolver as the legacy
LambdaResolver class plays for LegacyJITSymbolResolver, and will replace the
latter class once all ORC APIs are migrated to orc::SymbolResolver.
This patch also adds some documentation for the orc::SymbolResolver class as
this was left out of the original commit.
Modified:
llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h
llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp
Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h?rev=323375&r1=323374&r2=323375&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h Wed Jan 24 13:21:10 2018
@@ -100,10 +100,20 @@ struct LookupFlagsResult {
SymbolNameSet SymbolsNotFound;
};
+/// @brief SymbolResolver is a composable interface for looking up symbol flags
+/// and addresses using the AsynchronousSymbolQuery type. It will
+/// eventually replace the LegacyJITSymbolResolver interface as the
+/// stardard ORC symbol resolver type.
class SymbolResolver {
public:
virtual ~SymbolResolver() = default;
+
+ /// @brief Returns the flags for each symbol in Symbols that can be found,
+ /// along with the set of symbol that could not be found.
virtual LookupFlagsResult lookupFlags(const SymbolNameSet &Symbols) = 0;
+
+ /// @brief For each symbol in Symbols that can be found, assigns that symbols
+ /// value in Query. Returns the set of symbols that could not be found.
virtual SymbolNameSet lookup(AsynchronousSymbolQuery &Query,
SymbolNameSet Symbols) = 0;
@@ -111,6 +121,48 @@ private:
virtual void anchor();
};
+/// @brief Implements SymbolResolver with a pair of supplied function objects
+/// for convenience. See createSymbolResolver.
+template <typename LookupFlagsFn, typename LookupFn>
+class LambdaSymbolResolver final : public SymbolResolver {
+public:
+ template <typename LookupFlagsFnRef, typename LookupFnRef>
+ LambdaSymbolResolver(LookupFlagsFnRef &&LookupFlags, LookupFnRef &&Lookup)
+ : LookupFlags(std::forward<LookupFlagsFnRef>(LookupFlags)),
+ Lookup(std::forward<LookupFnRef>(Lookup)) {}
+
+ LookupFlagsResult lookupFlags(const SymbolNameSet &Symbols) final {
+ return LookupFlags(Symbols);
+ }
+
+ SymbolNameSet lookup(AsynchronousSymbolQuery &Query,
+ SymbolNameSet Symbols) final {
+ return Lookup(Query, std::move(Symbols));
+ }
+
+private:
+ LookupFlagsFn LookupFlags;
+ LookupFn Lookup;
+};
+
+/// @brief Creates a SymbolResolver implementation from the pair of supplied
+/// function objects.
+template <typename LookupFlagsFn, typename LookupFn>
+std::unique_ptr<LambdaSymbolResolver<
+ typename std::remove_cv<
+ typename std::remove_reference<LookupFlagsFn>::type>::type,
+ typename std::remove_cv<
+ typename std::remove_reference<LookupFn>::type>::type>>
+createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) {
+ using LambdaSymbolResolverImpl = LambdaSymbolResolver<
+ typename std::remove_cv<
+ typename std::remove_reference<LookupFlagsFn>::type>::type,
+ typename std::remove_cv<
+ typename std::remove_reference<LookupFn>::type>::type>;
+ return llvm::make_unique<LambdaSymbolResolverImpl>(
+ std::forward<LookupFlagsFn>(LookupFlags), std::forward<LookupFn>(Lookup));
+}
+
/// @brief Represents a source of symbol definitions which may be materialized
/// (turned into data / code through some materialization process) or
/// discarded (if the definition is overridden by a stronger one).
Modified: llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp?rev=323375&r1=323374&r2=323375&view=diff
==============================================================================
--- llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp (original)
+++ llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp Wed Jan 24 13:21:10 2018
@@ -258,4 +258,70 @@ TEST(CoreAPIsTest, AddAndMaterializeLazy
EXPECT_TRUE(OnReadyRun) << "OnReady was not run";
}
+TEST(CoreAPIsTest, TestLambdaSymbolResolver) {
+ JITEvaluatedSymbol FooSym(0xdeadbeef, JITSymbolFlags::Exported);
+ JITEvaluatedSymbol BarSym(0xcafef00d, JITSymbolFlags::Exported);
+
+ SymbolStringPool SP;
+ auto Foo = SP.intern("foo");
+ auto Bar = SP.intern("bar");
+ auto Baz = SP.intern("baz");
+
+ VSO V;
+ cantFail(V.define({{Foo, FooSym}, {Bar, BarSym}}));
+
+ auto Resolver = createSymbolResolver(
+ [&](const SymbolNameSet &Symbols) { return V.lookupFlags(Symbols); },
+ [&](AsynchronousSymbolQuery &Q, SymbolNameSet Symbols) {
+ auto LR = V.lookup(Q, Symbols);
+ assert(LR.MaterializationWork.empty() &&
+ "Test generated unexpected materialization "
+ "work?");
+ return std::move(LR.UnresolvedSymbols);
+ });
+
+ SymbolNameSet Symbols({Foo, Bar, Baz});
+
+ LookupFlagsResult LFR = Resolver->lookupFlags(Symbols);
+
+ EXPECT_EQ(LFR.SymbolFlags.size(), 2U)
+ << "lookupFlags returned the wrong number of results";
+ EXPECT_EQ(LFR.SymbolFlags.count(Foo), 1U)
+ << "Missing lookupFlags result for foo";
+ EXPECT_EQ(LFR.SymbolFlags.count(Bar), 1U)
+ << "Missing lookupFlags result for bar";
+ EXPECT_EQ(LFR.SymbolFlags[Foo], FooSym.getFlags())
+ << "Incorrect lookupFlags result for Foo";
+ EXPECT_EQ(LFR.SymbolFlags[Bar], BarSym.getFlags())
+ << "Incorrect lookupFlags result for Bar";
+ EXPECT_EQ(LFR.SymbolsNotFound.size(), 1U)
+ << "Expected one symbol not found in lookupFlags";
+ EXPECT_EQ(LFR.SymbolsNotFound.count(Baz), 1U)
+ << "Expected baz not to be found in lookupFlags";
+
+ bool OnResolvedRun = false;
+
+ auto OnResolved = [&](Expected<SymbolMap> Result) {
+ OnResolvedRun = true;
+ EXPECT_TRUE(!!Result) << "Unexpected error";
+ EXPECT_EQ(Result->size(), 2U) << "Unexpected number of resolved symbols";
+ EXPECT_EQ(Result->count(Foo), 1U) << "Missing lookup result for foo";
+ EXPECT_EQ(Result->count(Bar), 1U) << "Missing lookup result for bar";
+ EXPECT_EQ((*Result)[Foo].getAddress(), FooSym.getAddress())
+ << "Incorrect address for foo";
+ EXPECT_EQ((*Result)[Bar].getAddress(), BarSym.getAddress())
+ << "Incorrect address for bar";
+ };
+ auto OnReady = [&](Error Err) {
+ EXPECT_FALSE(!!Err) << "Finalization should never fail in this test";
+ };
+
+ AsynchronousSymbolQuery Q({Foo, Bar}, OnResolved, OnReady);
+ auto Unresolved = Resolver->lookup(Q, Symbols);
+
+ EXPECT_EQ(Unresolved.size(), 1U) << "Expected one unresolved symbol";
+ EXPECT_EQ(Unresolved.count(Baz), 1U) << "Expected baz to not be resolved";
+ EXPECT_TRUE(OnResolvedRun) << "OnResolved was never run";
+}
+
} // namespace
More information about the llvm-commits
mailing list