[lld] r208753 - Add observers to Input Graph

Rui Ueyama ruiu at google.com
Tue May 13 22:31:55 PDT 2014


Author: ruiu
Date: Wed May 14 00:31:54 2014
New Revision: 208753

URL: http://llvm.org/viewvc/llvm-project?rev=208753&view=rev
Log:
Add observers to Input Graph

Make it possible to add observers to an Input Graph, so that files
returned from an Input Graph can be examined before they are
passed to Resolver.

To implement some PE/COFF features we need to know all the symbols
that *can* be solved, including ones in archive files that are not
yet to be read.

Currently, Resolver only maintains a set of symbols that are
already read. It has no knowledge on symbols in skipped files in
an archive file.

There are many ways to implement that. I chose to apply the
observer pattern here because it seems most non-intrusive. We don't
want to mess up Resolver with architecture specific features.
Even in PE/COFF, the feature that needs this mechanism is minor.
So I chose not to modify Resolver, but add a hook to Input Graph.

Differential Revision: http://reviews.llvm.org/D3735

Modified:
    lld/trunk/include/lld/Core/ArchiveLibraryFile.h
    lld/trunk/include/lld/Core/InputGraph.h
    lld/trunk/lib/Core/InputGraph.cpp
    lld/trunk/lib/ReaderWriter/FileArchive.cpp
    lld/trunk/unittests/DriverTests/InputGraphTest.cpp

Modified: lld/trunk/include/lld/Core/ArchiveLibraryFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/ArchiveLibraryFile.h?rev=208753&r1=208752&r2=208753&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/ArchiveLibraryFile.h (original)
+++ lld/trunk/include/lld/Core/ArchiveLibraryFile.h Wed May 14 00:31:54 2014
@@ -12,6 +12,8 @@
 
 #include "lld/Core/File.h"
 
+#include <set>
+
 namespace lld {
 
 ///
@@ -36,6 +38,12 @@ public:
   virtual error_code
   parseAllMembers(std::vector<std::unique_ptr<File>> &result) const = 0;
 
+  /// Returns a set of all defined symbols in the archive, i.e. all
+  /// resolvable symbol using this file.
+  virtual std::set<StringRef> getDefinedSymbols() const {
+    return std::set<StringRef>();
+  }
+
 protected:
   /// only subclasses of ArchiveLibraryFile can be instantiated
   ArchiveLibraryFile(StringRef path) : File(path, kindArchiveLibrary) {}

Modified: lld/trunk/include/lld/Core/InputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputGraph.h?rev=208753&r1=208752&r2=208753&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/InputGraph.h (original)
+++ lld/trunk/include/lld/Core/InputGraph.h Wed May 14 00:31:54 2014
@@ -19,6 +19,7 @@
 #include "lld/Core/File.h"
 #include "llvm/Option/ArgList.h"
 
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/ErrorOr.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
@@ -67,6 +68,11 @@ public:
   /// whether it should iterate over again or terminate or not.
   void notifyProgress();
 
+  /// Adds an observer of getNextFile(). Each time a new file is about to be
+  /// returned from getNextFile(), registered observers are called with the file
+  /// being returned.
+  void registerObserver(llvm::function_ref<void(File *)> fn);
+
   /// \brief Adds a node into the InputGraph
   void addInputElement(std::unique_ptr<InputElement>);
 
@@ -93,6 +99,7 @@ protected:
   // Index of the next element to be processed
   uint32_t _nextElementIndex;
   InputElement *_currentInputElement;
+  std::vector<llvm::function_ref<void(File *)>> _observers;
 
 private:
   ErrorOr<InputElement *> getNextInputElement();

Modified: lld/trunk/lib/Core/InputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputGraph.cpp?rev=208753&r1=208752&r2=208753&view=diff
==============================================================================
--- lld/trunk/lib/Core/InputGraph.cpp (original)
+++ lld/trunk/lib/Core/InputGraph.cpp Wed May 14 00:31:54 2014
@@ -21,9 +21,12 @@ ErrorOr<File &> InputGraph::getNextFile(
   // it will succeed. If not, try to get the next file in the input graph.
   for (;;) {
     if (_currentInputElement) {
-      ErrorOr<File &> nextFile = _currentInputElement->getNextFile();
-      if (nextFile.getError() != InputGraphError::no_more_files)
-        return std::move(nextFile);
+      ErrorOr<File &> next = _currentInputElement->getNextFile();
+      if (next.getError() != InputGraphError::no_more_files) {
+        for (llvm::function_ref<void(File *)> observer : _observers)
+          observer(&next.get());
+        return std::move(next);
+      }
     }
 
     ErrorOr<InputElement *> elt = getNextInputElement();
@@ -35,6 +38,10 @@ ErrorOr<File &> InputGraph::getNextFile(
 
 void InputGraph::notifyProgress() { _currentInputElement->notifyProgress(); }
 
+void InputGraph::registerObserver(llvm::function_ref<void(File *)> fn) {
+  _observers.push_back(fn);
+}
+
 void InputGraph::addInputElement(std::unique_ptr<InputElement> ie) {
   _inputArgs.push_back(std::move(ie));
 }

Modified: lld/trunk/lib/ReaderWriter/FileArchive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/FileArchive.cpp?rev=208753&r1=208752&r2=208753&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/FileArchive.cpp (original)
+++ lld/trunk/lib/ReaderWriter/FileArchive.cpp Wed May 14 00:31:54 2014
@@ -97,6 +97,14 @@ public:
     return _absoluteAtoms;
   }
 
+  /// Returns a set of all defined symbols in the archive.
+  std::set<StringRef> getDefinedSymbols() const override {
+    std::set<StringRef> ret;
+    for (const auto &e : _symbolMemberMap)
+      ret.insert(e.first);
+    return ret;
+  }
+
 protected:
   error_code
   instantiateMember(Archive::child_iterator member,

Modified: lld/trunk/unittests/DriverTests/InputGraphTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/InputGraphTest.cpp?rev=208753&r1=208752&r2=208753&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/InputGraphTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/InputGraphTest.cpp Wed May 14 00:31:54 2014
@@ -191,3 +191,18 @@ TEST_F(InputGraphTest, Normalize) {
   EXPECT_EQ("file6", getNext());
   expectEnd();
 }
+
+TEST_F(InputGraphTest, Observer) {
+  std::vector<std::string> files;
+  _graph->registerObserver([&](File *file) { files.push_back(file->path()); });
+
+  _graph->addInputElement(createFile1("file1"));
+  _graph->addInputElement(createFile1("file2"));
+  EXPECT_EQ("file1", getNext());
+  EXPECT_EQ("file2", getNext());
+  expectEnd();
+
+  EXPECT_EQ(2U, files.size());
+  EXPECT_EQ("file1", files[0]);
+  EXPECT_EQ("file2", files[1]);
+}





More information about the llvm-commits mailing list