[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