[lld] r225859 - Revert "Convert other drivers to use WrapperNode" and subsequent commits.

Rui Ueyama ruiu at google.com
Tue Jan 13 16:21:35 PST 2015


Author: ruiu
Date: Tue Jan 13 18:21:34 2015
New Revision: 225859

URL: http://llvm.org/viewvc/llvm-project?rev=225859&view=rev
Log:
Revert "Convert other drivers to use WrapperNode" and subsequent commits.

r225764 broke a basic functionality on Mac OS. This change reverts
r225764, r225766, r225767, r225769, r225814, r225816, r225829, and r225832.

Added:
    lld/trunk/include/lld/Driver/DarwinInputGraph.h
    lld/trunk/include/lld/Driver/GnuLdInputGraph.h
    lld/trunk/include/lld/Driver/WinLinkInputGraph.h
    lld/trunk/lib/Driver/DarwinInputGraph.cpp
    lld/trunk/lib/Driver/GnuLdInputGraph.cpp
    lld/trunk/lib/Driver/WinLinkInputGraph.cpp
    lld/trunk/test/Driver/libsearch-inputGraph.test
    lld/trunk/unittests/DriverTests/InputGraphTest.cpp
Modified:
    lld/trunk/docs/Readers.rst
    lld/trunk/include/lld/Core/ArchiveLibraryFile.h
    lld/trunk/include/lld/Core/File.h
    lld/trunk/include/lld/Core/InputGraph.h
    lld/trunk/include/lld/Core/Resolver.h
    lld/trunk/include/lld/Driver/Driver.h
    lld/trunk/include/lld/Driver/WrapperInputGraph.h
    lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
    lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
    lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
    lld/trunk/include/lld/ReaderWriter/Reader.h
    lld/trunk/lib/Core/InputGraph.cpp
    lld/trunk/lib/Core/Resolver.cpp
    lld/trunk/lib/Driver/CMakeLists.txt
    lld/trunk/lib/Driver/CoreDriver.cpp
    lld/trunk/lib/Driver/DarwinLdDriver.cpp
    lld/trunk/lib/Driver/Driver.cpp
    lld/trunk/lib/Driver/GnuLdDriver.cpp
    lld/trunk/lib/Driver/WinLinkDriver.cpp
    lld/trunk/lib/Passes/RoundTripNativePass.cpp
    lld/trunk/lib/Passes/RoundTripYAMLPass.cpp
    lld/trunk/lib/ReaderWriter/ELF/ELFReader.h
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFReader.h
    lld/trunk/lib/ReaderWriter/FileArchive.cpp
    lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
    lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
    lld/trunk/lib/ReaderWriter/Native/ReaderNative.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
    lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
    lld/trunk/lib/ReaderWriter/Reader.cpp
    lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
    lld/trunk/test/pecoff/hello64.test
    lld/trunk/unittests/DriverTests/CMakeLists.txt
    lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp

Modified: lld/trunk/docs/Readers.rst
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/docs/Readers.rst?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/docs/Readers.rst (original)
+++ lld/trunk/docs/Readers.rst Tue Jan 13 18:21:34 2015
@@ -66,7 +66,7 @@ Readers are factories
 ---------------------
 
 The linker will usually only instantiate your Reader once.  That one Reader will
-have its loadFile() method called many times with different input files.
+have its parseFile() method called many times with different input files.
 To support multithreaded linking, the Reader may be parsing multiple input
 files in parallel. Therefore, there should be no parsing state in you Reader
 object.  Any parsing state should be in ivars of your File subclass or in
@@ -74,8 +74,8 @@ some temporary object.
 
 The key method to implement in a reader is::
 
-  virtual error_code loadFile(LinkerInput &input,
-                              std::vector<std::unique_ptr<File>> &result);
+  virtual error_code parseFile(LinkerInput &input,
+                               std::vector<std::unique_ptr<File>> &result);
 
 It takes a memory buffer (which contains the contents of the object file
 being read) and returns an instantiated lld::File object which is

Modified: lld/trunk/include/lld/Core/ArchiveLibraryFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/ArchiveLibraryFile.h?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/ArchiveLibraryFile.h (original)
+++ lld/trunk/include/lld/Core/ArchiveLibraryFile.h Tue Jan 13 18:21:34 2015
@@ -35,7 +35,7 @@ public:
   virtual const File *find(StringRef name, bool dataSymbolOnly) const = 0;
 
   virtual std::error_code
-  parseAllMembers(std::vector<std::unique_ptr<File>> &result) = 0;
+  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.

Modified: lld/trunk/include/lld/Core/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/File.h?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/File.h (original)
+++ lld/trunk/include/lld/Core/File.h Tue Jan 13 18:21:34 2015
@@ -274,8 +274,7 @@ protected:
 /// can do unit testing a driver using non-existing file paths.
 class ErrorFile : public File {
 public:
-  ErrorFile(StringRef path, std::error_code ec)
-      : File(path, kindObject), _ec(ec) {}
+  ErrorFile(StringRef p, std::error_code ec) : File(p, kindObject), _ec(ec) {}
 
   std::error_code doParse() override { return _ec; }
 

Modified: lld/trunk/include/lld/Core/InputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputGraph.h?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/InputGraph.h (original)
+++ lld/trunk/include/lld/Core/InputGraph.h Tue Jan 13 18:21:34 2015
@@ -49,7 +49,18 @@ public:
   typedef FileVectorT::iterator FileIterT;
 
   /// \brief Initialize the inputgraph
-  InputGraph() : _index(0) {}
+  InputGraph() : _nextElementIndex(0), _currentInputElement(nullptr) {}
+  virtual ~InputGraph();
+
+  /// getNextFile returns the next file that needs to be processed by
+  /// the resolver. When there are no more files to be processed, an
+  /// nullptr is returned.
+  File *getNextFile();
+
+  /// 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(std::function<void(File *)>);
 
   /// \brief Adds a node into the InputGraph
   void addInputElement(std::unique_ptr<InputElement>);
@@ -57,16 +68,34 @@ public:
   /// \brief Adds a node at the beginning of the InputGraph
   void addInputElementFront(std::unique_ptr<InputElement>);
 
-  InputElementVectorT &inputElements() { return _inputArgs; }
+  /// Normalize the InputGraph. It calls getReplacements() on each element.
+  void normalize();
+
+  InputElementVectorT &inputElements() {
+    return _inputArgs;
+  }
+
+  // Returns the current group size if we are at an --end-group.
+  // Otherwise returns 0.
+  int getGroupSize();
+  void skipGroup();
 
   // \brief Returns the number of input files.
   size_t size() const { return _inputArgs.size(); }
 
+  /// \brief Dump the input Graph
+  bool dump(raw_ostream &diagnostics = llvm::errs());
+
 protected:
   // Input arguments
   InputElementVectorT _inputArgs;
   // Index of the next element to be processed
-  size_t _index;
+  uint32_t _nextElementIndex;
+  InputElement *_currentInputElement;
+  std::vector<std::function<void(File *)>> _observers;
+
+private:
+  InputElement *getNextInputElement();
 };
 
 /// \brief This describes each element in the InputGraph. The Kind
@@ -96,6 +125,11 @@ public:
   /// Get the next file to be processed by the resolver
   virtual File *getNextFile() = 0;
 
+  /// Get the elements that we want to expand with.
+  virtual bool getReplacements(InputGraph::InputElementVectorT &) {
+    return false;
+  }
+
 protected:
   Kind _kind; // The type of the Element
 };
@@ -131,13 +165,9 @@ private:
 class FileNode : public InputElement {
 public:
   FileNode(StringRef path)
-      : InputElement(InputElement::Kind::File), _path(path), _done(false) {
+      : InputElement(InputElement::Kind::File), _path(path), _nextFileIndex(0) {
   }
 
-  FileNode(StringRef path, std::unique_ptr<File> f)
-      : InputElement(InputElement::Kind::File), _path(path), _file(std::move(f)),
-        _done(false) {}
-
   virtual ErrorOr<StringRef> getPath(const LinkingContext &) const {
     return _path;
   }
@@ -156,33 +186,36 @@ public:
   }
 
   /// \brief Get the list of files
-  File *getFile() { return _file.get(); }
+  range<InputGraph::FileIterT> files() {
+    return make_range(_files.begin(), _files.end());
+  }
 
   /// \brief add a file to the list of files
   virtual void addFiles(InputGraph::FileVectorT files) {
     assert(files.size() == 1);
-    assert(!_file);
-    _file = std::move(files[0]);
+    assert(_files.empty());
+    for (std::unique_ptr<File> &ai : files)
+      _files.push_back(std::move(ai));
   }
 
+  bool getReplacements(InputGraph::InputElementVectorT &result) override;
+
   /// \brief Return the next File thats part of this node to the
   /// resolver.
   File *getNextFile() override {
-    assert(_file);
-    if (_done)
+    if (_nextFileIndex == _files.size())
       return nullptr;
-    _done = true;
-    return _file.get();
+    return _files[_nextFileIndex++].get();
   }
 
   std::error_code parse(const LinkingContext &, raw_ostream &) override;
 
 protected:
   StringRef _path;                       // The path of the Input file
-  std::unique_ptr<File> _file;           // An lld File object
+  InputGraph::FileVectorT _files;        // A vector of lld File objects
 
   // The next file that would be processed by the resolver
-  bool _done;
+  uint32_t _nextFileIndex;
 };
 
 /// \brief Represents Internal Input files
@@ -190,13 +223,15 @@ class SimpleFileNode : public FileNode {
 public:
   SimpleFileNode(StringRef path) : FileNode(path) {}
   SimpleFileNode(StringRef path, std::unique_ptr<File> f)
-      : FileNode(path, std::move(f)) {}
+      : FileNode(path) {
+    _files.push_back(std::move(f));
+  }
 
   virtual ~SimpleFileNode() {}
 
   /// \brief add a file to the list of files
   virtual void appendInputFile(std::unique_ptr<File> f) {
-    _file = std::move(f);
+    _files.push_back(std::move(f));
   }
 };
 

Modified: lld/trunk/include/lld/Core/Resolver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Resolver.h (original)
+++ lld/trunk/include/lld/Core/Resolver.h Tue Jan 13 18:21:34 2015
@@ -55,8 +55,8 @@ public:
 private:
   typedef std::function<void(StringRef, bool)> UndefCallback;
 
-  bool undefinesAdded(int begin, int end);
-  File *getFile(int &index, int &groupLevel);
+  bool undefinesAdded(int count);
+  File *nextFile(bool &inGroup);
 
   /// \brief Add section group/.gnu.linkonce if it does not exist previously.
   void maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom);

Added: lld/trunk/include/lld/Driver/DarwinInputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/DarwinInputGraph.h?rev=225859&view=auto
==============================================================================
--- lld/trunk/include/lld/Driver/DarwinInputGraph.h (added)
+++ lld/trunk/include/lld/Driver/DarwinInputGraph.h Tue Jan 13 18:21:34 2015
@@ -0,0 +1,56 @@
+//===- lld/Driver/DarwinInputGraph.h - Input Graph Node for Mach-O linker -===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// Handles Options for MachO linking and provides InputElements
+/// for MachO linker
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_DRIVER_DARWIN_INPUT_GRAPH_H
+#define LLD_DRIVER_DARWIN_INPUT_GRAPH_H
+
+#include "lld/Core/ArchiveLibraryFile.h"
+#include "lld/Core/InputGraph.h"
+#include "lld/ReaderWriter/MachOLinkingContext.h"
+
+namespace lld {
+
+/// \brief Represents a MachO File
+class MachOFileNode : public FileNode {
+public:
+  MachOFileNode(StringRef path, MachOLinkingContext &ctx)
+      : FileNode(path), _context(ctx), _isWholeArchive(false),
+        _upwardDylib(false) {}
+
+  /// \brief Parse the input file to lld::File.
+  std::error_code parse(const LinkingContext &ctx,
+                        raw_ostream &diagnostics) override;
+
+  void setLoadWholeArchive(bool value=true) {
+    _isWholeArchive = value;
+  }
+
+  void setUpwardDylib(bool value=true) {
+    _upwardDylib = value;
+  }
+
+private:
+  void narrowFatBuffer(std::unique_ptr<MemoryBuffer> &mb, StringRef filePath);
+
+  MachOLinkingContext &_context;
+  std::unique_ptr<const ArchiveLibraryFile> _archiveFile;
+  bool _isWholeArchive;
+  bool _upwardDylib;
+};
+
+} // namespace lld
+
+#endif

Modified: lld/trunk/include/lld/Driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/Driver.h?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/Driver.h (original)
+++ lld/trunk/include/lld/Driver/Driver.h Tue Jan 13 18:21:34 2015
@@ -36,7 +36,7 @@ typedef std::vector<std::unique_ptr<File
 
 FileVector makeErrorFile(StringRef path, std::error_code ec);
 FileVector parseMemberFiles(FileVector &files);
-FileVector loadFile(LinkingContext &ctx, StringRef path, bool wholeArchive);
+FileVector parseFile(LinkingContext &ctx, StringRef path, bool wholeArchive);
 
 /// Base class for all Drivers.
 class Driver {

Added: lld/trunk/include/lld/Driver/GnuLdInputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/GnuLdInputGraph.h?rev=225859&view=auto
==============================================================================
--- lld/trunk/include/lld/Driver/GnuLdInputGraph.h (added)
+++ lld/trunk/include/lld/Driver/GnuLdInputGraph.h Tue Jan 13 18:21:34 2015
@@ -0,0 +1,85 @@
+//===- lld/Driver/GnuLdInputGraph.h - Input Graph Node for ELF linker------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// Handles Options for the GNU style linker for ELF and provides InputElements
+/// for the GNU style linker for ELF
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_DRIVER_GNU_LD_INPUT_GRAPH_H
+#define LLD_DRIVER_GNU_LD_INPUT_GRAPH_H
+
+#include "lld/Core/ArchiveLibraryFile.h"
+#include "lld/Core/InputGraph.h"
+#include "lld/Core/Resolver.h"
+#include "lld/ReaderWriter/ELFLinkingContext.h"
+
+namespace lld {
+
+/// \brief Represents a ELF File
+class ELFFileNode : public FileNode {
+public:
+  /// \brief The attributes class provides a way for a input file to look into
+  /// all the positional attributes that were specified in the command line.
+  /// There are few positional operators and the number of arguments to the
+  /// ELFFileNode class keeps growing. This achieves code to be clean as well.
+  class Attributes {
+  public:
+    Attributes()
+        : _isWholeArchive(false), _asNeeded(false), _isDashlPrefix(false),
+          _isSysRooted(false) {}
+    void setWholeArchive(bool isWholeArchive) {
+      _isWholeArchive = isWholeArchive;
+    }
+    void setAsNeeded(bool asNeeded) { _asNeeded = asNeeded; }
+    void setDashlPrefix(bool isDashlPrefix) { _isDashlPrefix = isDashlPrefix; }
+    void setSysRooted(bool isSysRooted) { _isSysRooted = isSysRooted; }
+
+  public:
+    bool _isWholeArchive;
+    bool _asNeeded;
+    bool _isDashlPrefix;
+    bool _isSysRooted;
+  };
+
+  ELFFileNode(ELFLinkingContext &ctx, StringRef path, Attributes &attributes)
+      : FileNode(path), _elfLinkingContext(ctx), _attributes(attributes) {}
+
+  ErrorOr<StringRef> getPath(const LinkingContext &ctx) const override;
+
+  /// \brief create an error string for printing purposes
+  std::string errStr(std::error_code) override;
+
+  /// \brief Dump the Input Element
+  bool dump(raw_ostream &diagnostics) override {
+    diagnostics << "Name    : " << *getPath(_elfLinkingContext) << "\n"
+                << "Type    : ELF File\n"
+                << "Attributes :\n"
+                << "  - wholeArchive : "
+                << ((_attributes._isWholeArchive) ? "true" : "false") << "\n"
+                << "  - asNeeded : "
+                << ((_attributes._asNeeded) ? "true" : "false") << "\n";
+    return true;
+  }
+
+  /// \brief Parse the input file to lld::File.
+  std::error_code parse(const LinkingContext &, raw_ostream &) override;
+
+private:
+  llvm::BumpPtrAllocator _alloc;
+  const ELFLinkingContext &_elfLinkingContext;
+  std::unique_ptr<const ArchiveLibraryFile> _archiveFile;
+  const Attributes _attributes;
+};
+
+} // namespace lld
+
+#endif

Added: lld/trunk/include/lld/Driver/WinLinkInputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/WinLinkInputGraph.h?rev=225859&view=auto
==============================================================================
--- lld/trunk/include/lld/Driver/WinLinkInputGraph.h (added)
+++ lld/trunk/include/lld/Driver/WinLinkInputGraph.h Tue Jan 13 18:21:34 2015
@@ -0,0 +1,45 @@
+//===- lld/Driver/WinLinkInputGraph.h - Input Graph Node for COFF linker --===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// Handles Options for PECOFF linking and provides InputElements
+/// for PECOFF linker
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_DRIVER_WIN_LINK_INPUT_GRAPH_H
+#define LLD_DRIVER_WIN_LINK_INPUT_GRAPH_H
+
+#include "lld/Core/InputGraph.h"
+#include "lld/ReaderWriter/PECOFFLinkingContext.h"
+#include <map>
+
+namespace lld {
+
+/// \brief Represents a PECOFF File
+class PECOFFFileNode : public FileNode {
+public:
+  PECOFFFileNode(PECOFFLinkingContext &ctx, StringRef path)
+      : FileNode(path), _ctx(ctx), _parsed(false) {}
+
+  /// \brief Parse the input file to lld::File.
+  std::error_code parse(const LinkingContext &ctx,
+                        raw_ostream &diagnostics) override;
+
+protected:
+  const PECOFFLinkingContext &_ctx;
+
+private:
+  bool _parsed;
+};
+
+} // namespace lld
+
+#endif

Modified: lld/trunk/include/lld/Driver/WrapperInputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/WrapperInputGraph.h?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/WrapperInputGraph.h (original)
+++ lld/trunk/include/lld/Driver/WrapperInputGraph.h Tue Jan 13 18:21:34 2015
@@ -21,7 +21,9 @@ namespace lld {
 
 class WrapperNode : public FileNode {
 public:
-  WrapperNode(std::unique_ptr<File> f) : FileNode(f->path(), std::move(f)) {}
+  WrapperNode(std::unique_ptr<File> file) : FileNode(file->path()) {
+    _files.push_back(std::move(file));
+  }
 };
 
 }

Modified: lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h Tue Jan 13 18:21:34 2015
@@ -290,28 +290,6 @@ public:
   bool alignSegments() const { return _alignSegments; }
   void setAlignSegments(bool align) { _alignSegments = align; }
 
-  /// \brief The attributes class provides a way for a input file to look into
-  /// all the positional attributes that were specified in the command line.
-  /// There are few positional operators and the number of arguments to the
-  /// ELFFileNode class keeps growing. This achieves code to be clean as well.
-  class Attributes {
-  public:
-    Attributes()
-        : _isWholeArchive(false), _asNeeded(false), _isDashlPrefix(false),
-          _isSysRooted(false) {}
-    void setWholeArchive(bool isWholeArchive) {
-      _isWholeArchive = isWholeArchive;
-    }
-    void setAsNeeded(bool asNeeded) { _asNeeded = asNeeded; }
-    void setDashlPrefix(bool isDashlPrefix) { _isDashlPrefix = isDashlPrefix; }
-    void setSysRooted(bool isSysRooted) { _isSysRooted = isSysRooted; }
-
-    bool _isWholeArchive;
-    bool _asNeeded;
-    bool _isDashlPrefix;
-    bool _isSysRooted;
-  };
-
 private:
   ELFLinkingContext() LLVM_DELETED_FUNCTION;
 

Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Tue Jan 13 18:21:34 2015
@@ -350,7 +350,7 @@ private:
   mutable llvm::StringMap<mach_o::MachODylibFile*> _pathToDylibMap;
   mutable std::set<mach_o::MachODylibFile*> _allDylibs;
   mutable std::set<mach_o::MachODylibFile*> _upwardDylibs;
-  mutable std::vector<std::unique_ptr<File>> _indirectDylibs;
+  mutable std::vector<std::unique_ptr<class MachOFileNode>> _indirectDylibs;
   ExportMode _exportMode;
   llvm::StringSet<> _exportedSymbols;
   DebugInfoMode _debugInfoMode;

Modified: lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Tue Jan 13 18:21:34 2015
@@ -30,28 +30,6 @@ static const uint8_t DEFAULT_DOS_STUB[12
 
 namespace lld {
 
-namespace pecoff {
-class ResolvableSymbols {
-public:
-  void add(File *file);
-
-  const std::set<std::string> &defined() {
-    readAllSymbols();
-    return _defined;
-  }
-
-private:
-  // Files are read lazily, so that it has no runtime overhead if
-  // no one accesses this class.
-  void readAllSymbols();
-
-  std::set<std::string> _defined;
-  std::set<File *> _seen;
-  std::set<File *> _queue;
-  std::mutex _mutex;
-};
-} // end namespace pecoff
-
 class PECOFFLinkingContext : public LinkingContext {
 public:
   PECOFFLinkingContext()
@@ -350,10 +328,6 @@ public:
 
   std::recursive_mutex &getMutex() { return _mutex; }
 
-  pecoff::ResolvableSymbols *getResolvableSymsFile() {
-    return &_resolvableSyms;
-  }
-
 protected:
   /// Method to create a internal file for the entry symbol
   std::unique_ptr<File> createEntrySymbolFile() const override;
@@ -468,8 +442,6 @@ private:
   // Name of the temporary file for lib.exe subcommand. For debugging
   // only.
   std::string _moduleDefinitionFile;
-
-  pecoff::ResolvableSymbols _resolvableSyms;
 };
 
 } // end namespace lld

Modified: lld/trunk/include/lld/ReaderWriter/Reader.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/Reader.h?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/Reader.h (original)
+++ lld/trunk/include/lld/ReaderWriter/Reader.h Tue Jan 13 18:21:34 2015
@@ -55,8 +55,8 @@ public:
   /// file) and create a File object.
   /// The resulting File object takes ownership of the MemoryBuffer.
   virtual std::error_code
-  loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
-           std::vector<std::unique_ptr<File>> &result) const = 0;
+  parseFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
+            std::vector<std::unique_ptr<File>> &result) const = 0;
 };
 
 
@@ -93,8 +93,8 @@ public:
 
   /// Walk the list of registered Readers and find one that can parse the
   /// supplied file and parse it.
-  std::error_code loadFile(std::unique_ptr<MemoryBuffer> mb,
-                           std::vector<std::unique_ptr<File>> &result) const;
+  std::error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
+                            std::vector<std::unique_ptr<File>> &result) const;
 
   /// Walk the list of registered kind tables to convert a Reference Kind
   /// name to a value.

Modified: lld/trunk/lib/Core/InputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputGraph.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/Core/InputGraph.cpp (original)
+++ lld/trunk/lib/Core/InputGraph.cpp Tue Jan 13 18:21:34 2015
@@ -13,6 +13,33 @@
 
 using namespace lld;
 
+InputGraph::~InputGraph() { }
+
+File *InputGraph::getNextFile() {
+  // Try to get the next file of _currentInputElement. If the current input
+  // element points to an archive file, and there's a file left in the archive,
+  // it will succeed. If not, try to get the next file in the input graph.
+  for (;;) {
+    if (_currentInputElement) {
+      File *next = _currentInputElement->getNextFile();
+      if (next) {
+        for (const std::function<void(File *)> &observer : _observers)
+          observer(next);
+        return next;
+      }
+    }
+
+    InputElement *elt = getNextInputElement();
+    if (!elt)
+      return nullptr;
+    _currentInputElement = elt;
+  }
+}
+
+void InputGraph::registerObserver(std::function<void(File *)> fn) {
+  _observers.push_back(fn);
+}
+
 void InputGraph::addInputElement(std::unique_ptr<InputElement> ie) {
   _inputArgs.push_back(std::move(ie));
 }
@@ -21,9 +48,63 @@ void InputGraph::addInputElementFront(st
   _inputArgs.insert(_inputArgs.begin(), std::move(ie));
 }
 
+bool InputGraph::dump(raw_ostream &diagnostics) {
+  for (std::unique_ptr<InputElement> &ie : _inputArgs)
+    if (!ie->dump(diagnostics))
+      return false;
+  return true;
+}
+
+/// \brief Helper functions for the resolver
+InputElement *InputGraph::getNextInputElement() {
+  if (_nextElementIndex >= _inputArgs.size())
+    return nullptr;
+  InputElement *elem = _inputArgs[_nextElementIndex++].get();
+  if (isa<GroupEnd>(elem))
+    return getNextInputElement();
+  return elem;
+}
+
+void InputGraph::normalize() {
+  std::vector<std::unique_ptr<InputElement>> vec;
+  for (std::unique_ptr<InputElement> &elt : _inputArgs) {
+    if (elt->getReplacements(vec))
+      continue;
+    vec.push_back(std::move(elt));
+  }
+  _inputArgs = std::move(vec);
+}
+
+// If we are at the end of a group, return its size (which indicates
+// how many files we need to go back in the command line).
+// Returns 0 if we are not at the end of a group.
+int InputGraph::getGroupSize() {
+  if (_nextElementIndex >= _inputArgs.size())
+    return 0;
+  InputElement *elem = _inputArgs[_nextElementIndex].get();
+  if (const GroupEnd *group = dyn_cast<GroupEnd>(elem))
+    return group->getSize();
+  return 0;
+}
+
+void InputGraph::skipGroup() {
+  if (_nextElementIndex >= _inputArgs.size())
+    return;
+  if (isa<GroupEnd>(_inputArgs[_nextElementIndex].get()))
+    _nextElementIndex++;
+}
+
+bool FileNode::getReplacements(InputGraph::InputElementVectorT &result) {
+  if (_files.size() < 2)
+    return false;
+  for (std::unique_ptr<File> &file : _files)
+    result.push_back(llvm::make_unique<SimpleFileNode>(_path, std::move(file)));
+  return true;
+}
+
 std::error_code FileNode::parse(const LinkingContext &, raw_ostream &) {
-  if (_file)
-    if (std::error_code ec = _file->parse())
+  for (std::unique_ptr<File> &file : _files)
+    if (std::error_code ec = file->parse())
       return ec;
   return std::error_code();
 }

Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Tue Jan 13 18:21:34 2015
@@ -231,52 +231,52 @@ void Resolver::addAtoms(const std::vecto
 
 // Returns true if at least one of N previous files has created an
 // undefined symbol.
-bool Resolver::undefinesAdded(int begin, int end) {
-  std::vector<std::unique_ptr<InputElement>> &inputs =
-      _context.getInputGraph().inputElements();
-  for (int i = begin; i < end; ++i)
-    if (FileNode *node = dyn_cast<FileNode>(inputs[i].get()))
-      if (_newUndefinesAdded[node->getFile()])
-	return true;
+bool Resolver::undefinesAdded(int n) {
+  for (size_t i = _fileIndex - n; i < _fileIndex; ++i)
+    if (_newUndefinesAdded[_files[i]])
+      return true;
   return false;
 }
 
-File *Resolver::getFile(int &index, int &groupLevel) {
-  std::vector<std::unique_ptr<InputElement>> &inputs
-      = _context.getInputGraph().inputElements();
-  if ((size_t)index >= inputs.size())
-    return nullptr;
-  if (GroupEnd *group = dyn_cast<GroupEnd>(inputs[index].get())) {
+File *Resolver::nextFile(bool &inGroup) {
+  if (size_t groupSize = _context.getInputGraph().getGroupSize()) {
     // We are at the end of the current group. If one or more new
     // undefined atom has been added in the last groupSize files, we
     // reiterate over the files.
-    int size = group->getSize();
-    if (undefinesAdded(index - size, index)) {
-      index -= size;
-      ++groupLevel;
-      return getFile(index, groupLevel);
-    }
-    ++index;
-    --groupLevel;
-    return getFile(index, groupLevel);
+    if (undefinesAdded(groupSize))
+      _fileIndex -= groupSize;
+    _context.getInputGraph().skipGroup();
+    return nextFile(inGroup);
+  }
+  if (_fileIndex < _files.size()) {
+    // We are still in the current group.
+    inGroup = true;
+    return _files[_fileIndex++];
   }
-  return cast<FileNode>(inputs[index++].get())->getFile();
+  // We are not in a group. Get a new file.
+  File *file = _context.getInputGraph().getNextFile();
+  if (!file)
+    return nullptr;
+  _files.push_back(&*file);
+  ++_fileIndex;
+  inGroup = false;
+  return file;
 }
 
 // Keep adding atoms until _context.getNextFile() returns an error. This
 // function is where undefined atoms are resolved.
 void Resolver::resolveUndefines() {
   ScopedTask task(getDefaultDomain(), "resolveUndefines");
-  int index = 0;
-  int groupLevel = 0;
+
   for (;;) {
+    bool inGroup = false;
     bool undefAdded = false;
-    File *file = getFile(index, groupLevel);
+    File *file = nextFile(inGroup);
     if (!file)
       return;
     switch (file->kind()) {
     case File::kindObject:
-      if (groupLevel > 0)
+      if (inGroup)
         break;
       assert(!file->hasOrdinal());
       file->setOrdinal(_context.getNextOrdinalAndIncrement());
@@ -293,7 +293,7 @@ void Resolver::resolveUndefines() {
       handleSharedLibrary(*file);
       break;
     }
-    _newUndefinesAdded[file] = undefAdded;
+    _newUndefinesAdded[&*file] = undefAdded;
   }
 }
 

Modified: lld/trunk/lib/Driver/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/CMakeLists.txt?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/Driver/CMakeLists.txt (original)
+++ lld/trunk/lib/Driver/CMakeLists.txt Tue Jan 13 18:21:34 2015
@@ -12,11 +12,14 @@ add_public_tablegen_target(DriverOptions
 
 add_lld_library(lldDriver
   CoreDriver.cpp
+  DarwinInputGraph.cpp
   DarwinLdDriver.cpp
   Driver.cpp
   GnuLdDriver.cpp
+  GnuLdInputGraph.cpp
   UniversalDriver.cpp
   WinLinkDriver.cpp
+  WinLinkInputGraph.cpp
   WinLinkModuleDef.cpp
   )
 

Modified: lld/trunk/lib/Driver/CoreDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/CoreDriver.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/Driver/CoreDriver.cpp (original)
+++ lld/trunk/lib/Driver/CoreDriver.cpp Tue Jan 13 18:21:34 2015
@@ -152,7 +152,7 @@ bool CoreDriver::parse(int argc, const c
 
     case OPT_INPUT: {
       std::vector<std::unique_ptr<File>> files
-        = loadFile(ctx, inputArg->getValue(), false);
+        = parseFile(ctx, inputArg->getValue(), false);
       for (std::unique_ptr<File> &file : files) {
         inputGraph->addInputElement(std::unique_ptr<InputElement>(
             new WrapperNode(std::move(file))));

Added: lld/trunk/lib/Driver/DarwinInputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinInputGraph.cpp?rev=225859&view=auto
==============================================================================
--- lld/trunk/lib/Driver/DarwinInputGraph.cpp (added)
+++ lld/trunk/lib/Driver/DarwinInputGraph.cpp Tue Jan 13 18:21:34 2015
@@ -0,0 +1,83 @@
+//===- lib/ReaderWriter/MachO/DarwinInputGraph.cpp ------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Driver/DarwinInputGraph.h"
+#include "lld/Core/ArchiveLibraryFile.h"
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Reference.h"
+#include "lld/Core/SharedLibraryFile.h"
+
+namespace lld {
+
+
+/// \brief Parse the input file to lld::File.
+std::error_code MachOFileNode::parse(const LinkingContext &ctx,
+                                     raw_ostream &diagnostics)  {
+  ErrorOr<StringRef> filePath = getPath(ctx);
+  if (std::error_code ec = filePath.getError())
+    return ec;
+  ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr =
+      MemoryBuffer::getFileOrSTDIN(*filePath);
+  if (std::error_code ec = mbOrErr.getError())
+    return ec;
+  std::unique_ptr<MemoryBuffer> mb = std::move(mbOrErr.get());
+
+  _context.addInputFileDependency(*filePath);
+  if (ctx.logInputFiles())
+    diagnostics << *filePath << "\n";
+
+  narrowFatBuffer(mb, *filePath);
+
+  std::vector<std::unique_ptr<File>> parsedFiles;
+  if (std::error_code ec = ctx.registry().parseFile(std::move(mb), parsedFiles))
+    return ec;
+  for (std::unique_ptr<File> &pf : parsedFiles) {
+    // If file is a dylib, inform LinkingContext about it.
+    if (SharedLibraryFile *shl = dyn_cast<SharedLibraryFile>(pf.get())) {
+      _context.registerDylib(reinterpret_cast<mach_o::MachODylibFile*>(shl),
+                             _upwardDylib);
+    }
+    // If file is an archive and -all_load, then add all members.
+    if (ArchiveLibraryFile *archive = dyn_cast<ArchiveLibraryFile>(pf.get())) {
+      if (_isWholeArchive) {
+        // Have this node own the FileArchive object.
+        _archiveFile.reset(archive);
+        pf.release();
+        // Add all members to _files vector
+        return archive->parseAllMembers(_files);
+      }
+    }
+    _files.push_back(std::move(pf));
+  }
+  return std::error_code();
+}
+
+
+/// If buffer contains a fat file, find required arch in fat buffer and
+/// switch buffer to point to just that required slice.
+void MachOFileNode::narrowFatBuffer(std::unique_ptr<MemoryBuffer> &mb,
+                                    StringRef filePath) {
+  // Check if buffer is a "fat" file that contains needed arch.
+  uint32_t offset;
+  uint32_t size;
+  if (!_context.sliceFromFatFile(*mb, offset, size)) {
+    return;
+  }
+  // Create new buffer containing just the needed slice.
+  auto subuf = MemoryBuffer::getFileSlice(filePath, size, offset);
+  if (subuf.getError())
+    return;
+  // The assignment to mb will release previous buffer.
+  mb = std::move(subuf.get());
+}
+
+
+} // end namesapce lld

Modified: lld/trunk/lib/Driver/DarwinLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/DarwinLdDriver.cpp Tue Jan 13 18:21:34 2015
@@ -13,11 +13,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#include "lld/Core/File.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/SharedLibraryFile.h"
 #include "lld/Driver/Driver.h"
-#include "lld/Driver/WrapperInputGraph.h"
+#include "lld/Driver/DarwinInputGraph.h"
 #include "lld/ReaderWriter/MachOLinkingContext.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
@@ -25,7 +22,6 @@
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/Host.h"
@@ -72,50 +68,6 @@ public:
   DarwinLdOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){}
 };
 
-std::vector<std::unique_ptr<File>>
-loadFiles(MachOLinkingContext &ctx, StringRef path,
-          raw_ostream &diag, bool wholeArchive, bool upwardDylib) {
-  ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr =
-    MemoryBuffer::getFileOrSTDIN(path);
-  if (std::error_code ec = mbOrErr.getError())
-    return makeErrorFile(path, ec);
-  std::unique_ptr<MemoryBuffer> mb = std::move(mbOrErr.get());
-
-  ctx.addInputFileDependency(path);
-  if (ctx.logInputFiles())
-    diag << path << "\n";
-
-  // If buffer contains a fat file, find required arch in fat buffer
-  // and switch buffer to point to just that required slice.
-  // Check if buffer is a "fat" file that contains needed arch.
-  uint32_t offset;
-  uint32_t size;
-  if (ctx.sliceFromFatFile(*mb, offset, size)) {
-    // Create new buffer containing just the needed slice.
-    auto subuf = MemoryBuffer::getFileSlice(path, size, offset);
-    if (std::error_code ec = subuf.getError())
-      return makeErrorFile(path, ec);
-    // The assignment to mb will release previous buffer.
-    mb = std::move(subuf.get());
-  }
-
-  std::vector<std::unique_ptr<File>> files;
-  if (std::error_code ec = ctx.registry().loadFile(std::move(mb), files))
-    return makeErrorFile(path, ec);
-  for (std::unique_ptr<File> &pf : files) {
-    // If file is a dylib, inform LinkingContext about it.
-    if (SharedLibraryFile *shl = dyn_cast<SharedLibraryFile>(pf.get())) {
-      if (std::error_code ec = shl->parse())
-        return makeErrorFile(path, ec);
-      ctx.registerDylib(reinterpret_cast<mach_o::MachODylibFile*>(shl),
-                        upwardDylib);
-    }
-  }
-  if (wholeArchive)
-    return parseMemberFiles(files);
-  return files;
-}
-
 } // anonymous namespace
 
 // Test may be running on Windows. Canonicalize the path
@@ -133,12 +85,13 @@ static std::string canonicalizePath(Stri
 
 static void addFile(StringRef path, std::unique_ptr<InputGraph> &inputGraph,
                     MachOLinkingContext &ctx, bool loadWholeArchive,
-                    bool upwardDylib, raw_ostream &diag) {
-  std::vector<std::unique_ptr<File>> files =
-      loadFiles(ctx, path, diag, loadWholeArchive, upwardDylib);
-  for (std::unique_ptr<File> &file : files)
-    inputGraph->addInputElement(
-        llvm::make_unique<WrapperNode>(std::move(file)));
+                    bool upwardDylib) {
+  auto node = llvm::make_unique<MachOFileNode>(path, ctx);
+  if (loadWholeArchive)
+    node->setLoadWholeArchive();
+  if (upwardDylib)
+    node->setUpwardDylib();
+  inputGraph->addInputElement(std::move(node));
 }
 
 // Export lists are one symbol per line.  Blank lines are ignored.
@@ -231,10 +184,10 @@ static std::error_code parseOrderFile(St
 // In this variant, the path is to a text file which contains a partial path
 // per line. The <dir> prefix is prepended to each partial path.
 //
-static std::error_code loadFileList(StringRef fileListPath,
-                                    std::unique_ptr<InputGraph> &inputGraph,
-                                    MachOLinkingContext &ctx, bool forceLoad,
-                                    raw_ostream &diagnostics) {
+static std::error_code parseFileList(StringRef fileListPath,
+                                     std::unique_ptr<InputGraph> &inputGraph,
+                                     MachOLinkingContext &ctx, bool forceLoad,
+                                     raw_ostream &diagnostics) {
   // If there is a comma, split off <dir>.
   std::pair<StringRef, StringRef> opt = fileListPath.split(',');
   StringRef filePath = opt.first;
@@ -269,7 +222,7 @@ static std::error_code loadFileList(Stri
     if (ctx.testingFileUsage()) {
       diagnostics << "Found filelist entry " << canonicalizePath(path) << '\n';
     }
-    addFile(path, inputGraph, ctx, forceLoad, false, diagnostics);
+    addFile(path, inputGraph, ctx, forceLoad, false);
     buffer = lineAndRest.second;
   }
   return std::error_code();
@@ -291,6 +244,13 @@ bool DarwinLdDriver::linkMachO(int argc,
     return false;
   if (ctx.doNothing())
     return true;
+
+  // Register possible input file parsers.
+  ctx.registry().addSupportMachOObjects(ctx);
+  ctx.registry().addSupportArchives(ctx.logInputFiles());
+  ctx.registry().addSupportNativeObjects();
+  ctx.registry().addSupportYamlFiles();
+
   return link(ctx, diagnostics);
 }
 
@@ -350,15 +310,15 @@ bool DarwinLdDriver::parse(int argc, con
     }
   }
   // If no -arch specified, scan input files to find first non-fat .o file.
-  if (arch == MachOLinkingContext::arch_unknown) {
+  if ((arch == MachOLinkingContext::arch_unknown)
+      && !parsedArgs->getLastArg(OPT_test_file_usage)) {
     for (auto &inFile: parsedArgs->filtered(OPT_INPUT)) {
       // This is expensive because it opens and maps the file.  But that is
       // ok because no -arch is rare.
       if (MachOLinkingContext::isThinObjectFile(inFile->getValue(), arch))
         break;
     }
-    if (arch == MachOLinkingContext::arch_unknown
-        && !parsedArgs->getLastArg(OPT_test_file_usage)) {
+    if (arch == MachOLinkingContext::arch_unknown) {
       // If no -arch and no options at all, print usage message.
       if (parsedArgs->size() == 0)
         table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
@@ -561,13 +521,6 @@ bool DarwinLdDriver::parse(int argc, con
     }
   }
 
-  // Register possible input file parsers.
-  if (!ctx.doNothing()) {
-    ctx.registry().addSupportMachOObjects(ctx);
-    ctx.registry().addSupportArchives(ctx.logInputFiles());
-    ctx.registry().addSupportNativeObjects();
-    ctx.registry().addSupportYamlFiles();
-  }
   std::unique_ptr<InputGraph> inputGraph(new InputGraph());
 
   // Now construct the set of library search directories, following ld64's
@@ -792,13 +745,13 @@ bool DarwinLdDriver::parse(int argc, con
     default:
       continue;
     case OPT_INPUT:
-      addFile(arg->getValue(), inputGraph, ctx, globalWholeArchive, false, diagnostics);
+      addFile(arg->getValue(), inputGraph, ctx, globalWholeArchive, false);
       break;
     case OPT_upward_library:
-      addFile(arg->getValue(), inputGraph, ctx, false, true, diagnostics);
+      addFile(arg->getValue(), inputGraph, ctx, false, true);
       break;
     case OPT_force_load:
-      addFile(arg->getValue(), inputGraph, ctx, true, false, diagnostics);
+      addFile(arg->getValue(), inputGraph, ctx, true, false);
       break;
     case OPT_l:
     case OPT_upward_l:
@@ -812,7 +765,7 @@ bool DarwinLdDriver::parse(int argc, con
         diagnostics << "Found " << (upward ? "upward " : " ") << "library "
                    << canonicalizePath(resolvedPath.get()) << '\n';
       }
-      addFile(resolvedPath.get(), inputGraph, ctx, globalWholeArchive, upward, diagnostics);
+      addFile(resolvedPath.get(), inputGraph, ctx, globalWholeArchive, upward);
       break;
     case OPT_framework:
     case OPT_upward_framework:
@@ -826,12 +779,12 @@ bool DarwinLdDriver::parse(int argc, con
         diagnostics << "Found " << (upward ? "upward " : " ") << "framework "
                     << canonicalizePath(resolvedPath.get()) << '\n';
       }
-      addFile(resolvedPath.get(), inputGraph, ctx, globalWholeArchive, upward, diagnostics);
+      addFile(resolvedPath.get(), inputGraph, ctx, globalWholeArchive, upward);
       break;
     case OPT_filelist:
-      if (std::error_code ec = loadFileList(arg->getValue(), inputGraph,
-                                            ctx, globalWholeArchive,
-                                            diagnostics)) {
+      if (std::error_code ec = parseFileList(arg->getValue(), inputGraph,
+                                             ctx, globalWholeArchive,
+                                             diagnostics)) {
         diagnostics << "error: " << ec.message()
                     << ", processing '-filelist " << arg->getValue()
                     << "'\n";

Modified: lld/trunk/lib/Driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Driver.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/Driver/Driver.cpp (original)
+++ lld/trunk/lib/Driver/Driver.cpp Tue Jan 13 18:21:34 2015
@@ -49,13 +49,13 @@ FileVector parseMemberFiles(FileVector &
   return members;
 }
 
-FileVector loadFile(LinkingContext &ctx, StringRef path, bool wholeArchive) {
+FileVector parseFile(LinkingContext &ctx, StringRef path, bool wholeArchive) {
   ErrorOr<std::unique_ptr<MemoryBuffer>> mb
       = MemoryBuffer::getFileOrSTDIN(path);
   if (std::error_code ec = mb.getError())
     return makeErrorFile(path, ec);
   std::vector<std::unique_ptr<File>> files;
-  if (std::error_code ec = ctx.registry().loadFile(std::move(mb.get()), files))
+  if (std::error_code ec = ctx.registry().parseFile(std::move(mb.get()), files))
     return makeErrorFile(path, ec);
   if (wholeArchive)
     return parseMemberFiles(files);
@@ -77,6 +77,7 @@ bool Driver::link(LinkingContext &contex
   InputGraph &inputGraph = context.getInputGraph();
   if (!inputGraph.size())
     return false;
+  inputGraph.normalize();
 
   bool fail = false;
 

Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdDriver.cpp Tue Jan 13 18:21:34 2015
@@ -14,8 +14,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lld/Driver/Driver.h"
-#include "lld/Driver/WrapperInputGraph.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
+#include "lld/Driver/GnuLdInputGraph.h"
 #include "lld/ReaderWriter/LinkerScript.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
@@ -173,6 +172,16 @@ bool GnuLdDriver::linkELF(int argc, cons
     return false;
   if (!options)
     return true;
+
+  // Register possible input file parsers.
+  options->registry().addSupportELFObjects(options->mergeCommonStrings(),
+                                           options->targetHandler());
+  options->registry().addSupportArchives(options->logInputFiles());
+  options->registry().addSupportYamlFiles();
+  options->registry().addSupportNativeObjects();
+  if (options->allowLinkWithDynamicLibraries())
+    options->registry().addSupportELFDynamicSharedObjects(
+        options->useShlibUndefines(), options->targetHandler());
   return link(*options, diagnostics);
 }
 
@@ -209,23 +218,6 @@ static bool isLinkerScript(StringRef pat
   return magic == llvm::sys::fs::file_magic::unknown;
 }
 
-static ErrorOr<StringRef>
-findFile(ELFLinkingContext &ctx, StringRef path, bool dashL) {
-  // If the path was referred to by using a -l argument, let's search
-  // for the file in the search path.
-  if (dashL) {
-    ErrorOr<StringRef> pathOrErr = ctx.searchLibrary(path);
-    if (std::error_code ec = pathOrErr.getError())
-      return make_dynamic_error_code(
-          Twine("Unable to find library -l") + path + ": " + ec.message());
-    path = pathOrErr->str();
-  }
-  if (!llvm::sys::fs::exists(path))
-    return make_dynamic_error_code(
-        Twine("lld: cannot find file ") + path);
-  return path;
-}
-
 static bool isPathUnderSysroot(StringRef sysroot, StringRef path) {
   if (sysroot.empty())
     return false;
@@ -242,6 +234,8 @@ evaluateLinkerScript(ELFLinkingContext &
       MemoryBuffer::getFileOrSTDIN(path);
   if (std::error_code ec = mb.getError())
     return ec;
+  if (ctx.logInputFiles())
+    diag << path << "\n";
   auto lexer = llvm::make_unique<script::Lexer>(std::move(mb.get()));
   auto parser = llvm::make_unique<script::Parser>(*lexer);
   script::LinkerScript *script = parser->parse();
@@ -259,26 +253,13 @@ evaluateLinkerScript(ELFLinkingContext &
     int numfiles = 0;
     for (const script::Path &path : group->getPaths()) {
       // TODO : Propagate Set WholeArchive/dashlPrefix
-      ELFLinkingContext::Attributes attr;
+      ELFFileNode::Attributes attr;
       attr.setSysRooted(sysroot);
       attr.setAsNeeded(path._asNeeded);
       attr.setDashlPrefix(path._isDashlPrefix);
-
-      ErrorOr<StringRef> pathOrErr = path._isDashlPrefix
-          ? ctx.searchLibrary(path._path) : ctx.searchFile(path._path, sysroot);
-      if (std::error_code ec = pathOrErr.getError())
-        return make_dynamic_error_code(
-            Twine("Unable to find file ") + path._path + ": " + ec.message());
-
-      std::vector<std::unique_ptr<File>> files
-          = loadFile(ctx, pathOrErr.get(), false);
-      for (std::unique_ptr<File> &file : files) {
-        if (ctx.logInputFiles())
-          diag << file->path() << "\n";
-        inputGraph->addInputElement(
-            std::unique_ptr<InputElement>(new WrapperNode(std::move(file))));
-        ++numfiles;
-      }
+      ++numfiles;
+      inputGraph->addInputElement(llvm::make_unique<ELFFileNode>(
+                                      ctx, ctx.allocateString(path._path), attr));
     }
     inputGraph->addInputElement(llvm::make_unique<GroupEnd>(numfiles));
   }
@@ -360,7 +341,7 @@ bool GnuLdDriver::parse(int argc, const
   std::stack<int> groupStack;
   int numfiles = 0;
 
-  ELFLinkingContext::Attributes attributes;
+  ELFFileNode::Attributes attributes;
 
   bool _outputOptionSet = false;
 
@@ -398,6 +379,7 @@ bool GnuLdDriver::parse(int argc, const
       ctx->setPrintRemainingUndefines(false);
       ctx->setAllowRemainingUndefines(true);
       break;
+
     case OPT_static:
       ctx->setOutputELFType(llvm::ELF::ET_EXEC);
       ctx->setIsStaticExecutable(true);
@@ -433,37 +415,6 @@ bool GnuLdDriver::parse(int argc, const
     }
   }
 
-  for (auto inputArg : *parsedArgs) {
-    switch (inputArg->getOption().getID()) {
-    case OPT_merge_strings:
-      ctx->setMergeCommonStrings(true);
-      break;
-    case OPT_t:
-      ctx->setLogInputFiles(true);
-      break;
-    case OPT_use_shlib_undefs:
-      ctx->setUseShlibUndefines(true);
-      break;
-    case OPT_no_allow_shlib_undefs:
-      ctx->setAllowShlibUndefines(false);
-      break;
-    case OPT_allow_shlib_undefs:
-      ctx->setAllowShlibUndefines(true);
-      break;
-    }
-  }
-
-  // Register possible input file parsers.
-  ctx->registry().addSupportELFObjects(
-      ctx->mergeCommonStrings(),
-      ctx->targetHandler());
-  ctx->registry().addSupportArchives(ctx->logInputFiles());
-  ctx->registry().addSupportYamlFiles();
-  ctx->registry().addSupportNativeObjects();
-  if (ctx->allowLinkWithDynamicLibraries())
-    ctx->registry().addSupportELFDynamicSharedObjects(
-        ctx->useShlibUndefines(), ctx->targetHandler());
-
   // Process all the arguments and create Input Elements
   for (auto inputArg : *parsedArgs) {
     switch (inputArg->getOption().getID()) {
@@ -487,6 +438,26 @@ bool GnuLdDriver::parse(int argc, const
       ctx->setExportDynamic(true);
       break;
 
+    case OPT_merge_strings:
+      ctx->setMergeCommonStrings(true);
+      break;
+
+    case OPT_t:
+      ctx->setLogInputFiles(true);
+      break;
+
+    case OPT_no_allow_shlib_undefs:
+      ctx->setAllowShlibUndefines(false);
+      break;
+
+    case OPT_allow_shlib_undefs:
+      ctx->setAllowShlibUndefines(true);
+      break;
+
+    case OPT_use_shlib_undefs:
+      ctx->setUseShlibUndefines(true);
+      break;
+
     case OPT_allow_multiple_definition:
       ctx->setAllowDuplicates(true);
       break;
@@ -589,19 +560,25 @@ bool GnuLdDriver::parse(int argc, const
       bool dashL = (inputArg->getOption().getID() == OPT_l);
       attributes.setDashlPrefix(dashL);
       StringRef path = inputArg->getValue();
+      std::string realpath = path;
 
-      ErrorOr<StringRef> pathOrErr = findFile(*ctx, path, dashL);
-      if (std::error_code ec = pathOrErr.getError()) {
-        diagnostics << ec.message() << "\n";
+      // If the path was referred to by using a -l argument, let's search
+      // for the file in the search path.
+      if (dashL) {
+        ErrorOr<StringRef> pathOrErr = ctx->searchLibrary(path);
+        if (!pathOrErr) {
+          diagnostics << " Unable to find library -l" << path << "\n";
+          return false;
+        }
+        realpath = pathOrErr->str();
+      }
+      if (!llvm::sys::fs::exists(realpath)) {
+        diagnostics << "lld: cannot find file " << path << "\n";
         return false;
       }
-      std::string realpath = pathOrErr.get();
-
       bool isScript =
           (!path.endswith(".objtxt") && isLinkerScript(realpath, diagnostics));
       if (isScript) {
-        if (ctx->logInputFiles())
-          diagnostics << path << "\n";
         std::error_code ec = evaluateLinkerScript(
             *ctx, inputGraph.get(), realpath, diagnostics);
         if (ec) {
@@ -611,15 +588,9 @@ bool GnuLdDriver::parse(int argc, const
         }
         break;
       }
-      std::vector<std::unique_ptr<File>> files
-          = loadFile(*ctx, realpath, attributes._isWholeArchive);
-      for (std::unique_ptr<File> &file : files) {
-        if (ctx->logInputFiles())
-          diagnostics << file->path() << "\n";
-        inputGraph->addInputElement(
-            std::unique_ptr<InputElement>(new WrapperNode(std::move(file))));
-      }
-      numfiles += files.size();
+      ++numfiles;
+      inputGraph->addInputElement(
+          llvm::make_unique<ELFFileNode>(*ctx, path, attributes));
       break;
     }
 
@@ -689,6 +660,9 @@ bool GnuLdDriver::parse(int argc, const
     }
   }
 
+  if (ctx->outputFileType() == LinkingContext::OutputFileType::YAML)
+    inputGraph->dump(diagnostics);
+
   // Validate the combination of options used.
   if (!ctx->validate(diagnostics))
     return false;

Added: lld/trunk/lib/Driver/GnuLdInputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdInputGraph.cpp?rev=225859&view=auto
==============================================================================
--- lld/trunk/lib/Driver/GnuLdInputGraph.cpp (added)
+++ lld/trunk/lib/Driver/GnuLdInputGraph.cpp Tue Jan 13 18:21:34 2015
@@ -0,0 +1,65 @@
+//===- lib/Driver/GnuLdInputGraph.cpp -------------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Driver/GnuLdInputGraph.h"
+#include "lld/ReaderWriter/LinkerScript.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+using namespace lld;
+
+llvm::ErrorOr<StringRef> ELFFileNode::getPath(const LinkingContext &) const {
+  if (_attributes._isDashlPrefix)
+    return _elfLinkingContext.searchLibrary(_path);
+  return _elfLinkingContext.searchFile(_path, _attributes._isSysRooted);
+}
+
+std::string ELFFileNode::errStr(std::error_code errc) {
+  if (errc == llvm::errc::no_such_file_or_directory) {
+    if (_attributes._isDashlPrefix)
+      return (Twine("Unable to find library -l") + _path).str();
+    return (Twine("Unable to find file ") + _path).str();
+  }
+  return FileNode::errStr(errc);
+}
+
+/// \brief Parse the input file to lld::File.
+std::error_code ELFFileNode::parse(const LinkingContext &ctx,
+                                   raw_ostream &diagnostics) {
+  ErrorOr<StringRef> filePath = getPath(ctx);
+  if (std::error_code ec = filePath.getError())
+    return ec;
+  ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
+      MemoryBuffer::getFileOrSTDIN(*filePath);
+  if (std::error_code ec = mb.getError())
+    return ec;
+  if (ctx.logInputFiles())
+    diagnostics << *filePath << "\n";
+
+  if (_attributes._isWholeArchive) {
+    std::vector<std::unique_ptr<File>> parsedFiles;
+    if (std::error_code ec = ctx.registry().parseFile(
+            std::move(mb.get()), parsedFiles))
+      return ec;
+    assert(parsedFiles.size() == 1);
+    std::unique_ptr<File> f(parsedFiles[0].release());
+    if (const auto *archive = dyn_cast<ArchiveLibraryFile>(f.get())) {
+      // Have this node own the FileArchive object.
+      _archiveFile.reset(archive);
+      f.release();
+      // Add all members to _files vector
+      return archive->parseAllMembers(_files);
+    }
+    // if --whole-archive is around non-archive, just use it as normal.
+    _files.push_back(std::move(f));
+    return std::error_code();
+  }
+  return ctx.registry().parseFile(std::move(mb.get()), _files);
+}

Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
+++ lld/trunk/lib/Driver/WinLinkDriver.cpp Tue Jan 13 18:21:34 2015
@@ -14,8 +14,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "lld/Driver/Driver.h"
+#include "lld/Driver/WinLinkInputGraph.h"
 #include "lld/Driver/WinLinkModuleDef.h"
-#include "lld/Driver/WrapperInputGraph.h"
 #include "lld/ReaderWriter/PECOFFLinkingContext.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
@@ -800,11 +800,13 @@ parseArgs(int argc, const char **argv, P
 
 // Returns true if the given file node has already been added to the input
 // graph.
-static bool hasLibrary(const PECOFFLinkingContext &ctx, File *file) {
-  StringRef path = file->path();
+static bool hasLibrary(const PECOFFLinkingContext &ctx, FileNode *fileNode) {
+  ErrorOr<StringRef> path = fileNode->getPath(ctx);
+  if (!path)
+    return false;
   for (std::unique_ptr<InputElement> &p : ctx.getInputGraph().inputElements())
     if (auto *f = dyn_cast<FileNode>(p.get()))
-      if (*f->getPath(ctx) == path)
+      if (*path == *f->getPath(ctx))
         return true;
   return false;
 }
@@ -836,17 +838,6 @@ static bool maybeRunLibCommand(int argc,
   return true;
 }
 
-/// \brief Parse the input file to lld::File.
-void addFiles(PECOFFLinkingContext &ctx, StringRef path, raw_ostream &diag,
-	      std::vector<std::unique_ptr<File>> &files) {
-  for (std::unique_ptr<File> &file : loadFile(ctx, path, false)) {
-    if (ctx.logInputFiles())
-      diag << file->path() << "\n";
-    ctx.getResolvableSymsFile()->add(file.get());
-    files.push_back(std::move(file));
-  }
-}
-
 //
 // Main driver
 //
@@ -856,12 +847,6 @@ bool WinLinkDriver::linkPECOFF(int argc,
     return true;
 
   PECOFFLinkingContext ctx;
-  ctx.registry().addSupportCOFFObjects(ctx);
-  ctx.registry().addSupportCOFFImportLibraries(ctx);
-  ctx.registry().addSupportArchives(ctx.logInputFiles());
-  ctx.registry().addSupportNativeObjects();
-  ctx.registry().addSupportYamlFiles();
-
   std::vector<const char *> newargv = processLinkEnv(ctx, argc, argv);
   processLibEnv(ctx);
   if (!parse(newargv.size() - 1, &newargv[0], ctx, diag))
@@ -872,6 +857,13 @@ bool WinLinkDriver::linkPECOFF(int argc,
     if (!createSideBySideManifestFile(ctx, diag))
       return false;
 
+  // Register possible input file parsers.
+  ctx.registry().addSupportCOFFObjects(ctx);
+  ctx.registry().addSupportCOFFImportLibraries(ctx);
+  ctx.registry().addSupportArchives(ctx.logInputFiles());
+  ctx.registry().addSupportNativeObjects();
+  ctx.registry().addSupportYamlFiles();
+
   return link(ctx, diag);
 }
 
@@ -892,8 +884,8 @@ bool WinLinkDriver::parse(int argc, cons
     return false;
 
   // The list of input files.
-  std::vector<std::unique_ptr<File>> files;
-  std::vector<std::unique_ptr<File>> libraries;
+  std::vector<std::unique_ptr<FileNode> > files;
+  std::vector<std::unique_ptr<FileNode> > libraries;
 
   // Handle /help
   if (parsedArgs->getLastArg(OPT_help)) {
@@ -1371,9 +1363,11 @@ bool WinLinkDriver::parse(int argc, cons
   for (StringRef path : inputFiles) {
     path = ctx.allocate(path);
     if (isLibraryFile(path)) {
-      addFiles(ctx, getLibraryPath(ctx, path), diag, libraries);
+      libraries.push_back(std::unique_ptr<FileNode>(
+          new PECOFFFileNode(ctx, getLibraryPath(ctx, path))));
     } else {
-      addFiles(ctx, getObjectPath(ctx, path), diag, files);
+      files.push_back(std::unique_ptr<FileNode>(
+          new PECOFFFileNode(ctx, getObjectPath(ctx, path))));
     }
   }
 
@@ -1395,7 +1389,8 @@ bool WinLinkDriver::parse(int argc, cons
   if (!ctx.getNoDefaultLibAll())
     for (const StringRef path : defaultLibs)
       if (!ctx.hasNoDefaultLib(path))
-	addFiles(ctx, getLibraryPath(ctx, path.lower()), diag, libraries);
+        libraries.push_back(std::unique_ptr<FileNode>(
+            new PECOFFFileNode(ctx, getLibraryPath(ctx, path.lower()))));
 
   if (files.empty() && !isReadingDirectiveSection) {
     diag << "No input files\n";
@@ -1406,19 +1401,18 @@ bool WinLinkDriver::parse(int argc, cons
   // constructed by replacing an extension of the first input file
   // with ".exe".
   if (ctx.outputPath().empty()) {
-    StringRef path = files[0]->path();
+    StringRef path = *cast<FileNode>(&*files[0])->getPath(ctx);
     ctx.setOutputPath(replaceExtension(ctx, path, ".exe"));
   }
 
   // Add the input files to the input graph.
   if (!ctx.hasInputGraph())
     ctx.setInputGraph(std::unique_ptr<InputGraph>(new InputGraph()));
-  for (std::unique_ptr<File> &file : files) {
+  for (std::unique_ptr<FileNode> &file : files) {
     if (isReadingDirectiveSection)
-      if (file->parse())
+      if (file->parse(ctx, diag))
         return false;
-    ctx.getInputGraph().addInputElement(
-	std::unique_ptr<InputElement>(new WrapperNode(std::move(file))));
+    ctx.getInputGraph().addInputElement(std::move(file));
   }
 
   // Add the library group to the input graph.
@@ -1433,13 +1427,12 @@ bool WinLinkDriver::parse(int argc, cons
   }
 
   // Add the library files to the library group.
-  for (std::unique_ptr<File> &file : libraries) {
-    if (!hasLibrary(ctx, file.get())) {
+  for (std::unique_ptr<FileNode> &lib : libraries) {
+    if (!hasLibrary(ctx, lib.get())) {
       if (isReadingDirectiveSection)
-        if (file->parse())
+        if (lib->parse(ctx, diag))
           return false;
-      ctx.addLibraryFile(
-	std::unique_ptr<FileNode>(new WrapperNode(std::move(file))));
+      ctx.addLibraryFile(std::move(lib));
     }
   }
 

Added: lld/trunk/lib/Driver/WinLinkInputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkInputGraph.cpp?rev=225859&view=auto
==============================================================================
--- lld/trunk/lib/Driver/WinLinkInputGraph.cpp (added)
+++ lld/trunk/lib/Driver/WinLinkInputGraph.cpp Tue Jan 13 18:21:34 2015
@@ -0,0 +1,39 @@
+//===- lib/Driver/WinLinkInputGraph.cpp -----------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Driver/WinLinkInputGraph.h"
+
+namespace lld {
+
+/// \brief Parse the input file to lld::File.
+std::error_code PECOFFFileNode::parse(const LinkingContext &ctx,
+                                      raw_ostream &diagnostics) {
+  if (_parsed)
+    return std::error_code();
+  _parsed = true;
+  ErrorOr<StringRef> filePath = getPath(ctx);
+  if (std::error_code ec = filePath.getError()) {
+    diagnostics << "File not found: " << _path << "\n";
+    return ec;
+  }
+
+  ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
+      MemoryBuffer::getFileOrSTDIN(*filePath);
+  if (std::error_code ec = mb.getError()) {
+    diagnostics << "Cannot open file: " << *filePath << "\n";
+    return ec;
+  }
+
+  if (ctx.logInputFiles())
+    diagnostics << *filePath << "\n";
+
+  return ctx.registry().parseFile(std::move(mb.get()), _files);
+}
+
+} // end anonymous namespace

Modified: lld/trunk/lib/Passes/RoundTripNativePass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Passes/RoundTripNativePass.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/Passes/RoundTripNativePass.cpp (original)
+++ lld/trunk/lib/Passes/RoundTripNativePass.cpp Tue Jan 13 18:21:34 2015
@@ -40,15 +40,13 @@ void RoundTripNativePass::perform(std::u
   if (!mb)
     return;
 
-  std::error_code ec = _context.registry().loadFile(
+  std::error_code ec = _context.registry().parseFile(
       std::move(mb.get()), _nativeFile);
   if (ec) {
     // Note: we need a way for Passes to report errors.
     llvm_unreachable("native reader not registered or read error");
   }
   File *objFile = _nativeFile[0].get();
-  if (objFile->parse())
-    llvm_unreachable("native reader parse error");
   mergedFile.reset(new SimpleFileWrapper(_context, *objFile));
 
   llvm::sys::fs::remove(tmpNativeFile.str());

Modified: lld/trunk/lib/Passes/RoundTripYAMLPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Passes/RoundTripYAMLPass.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/Passes/RoundTripYAMLPass.cpp (original)
+++ lld/trunk/lib/Passes/RoundTripYAMLPass.cpp Tue Jan 13 18:21:34 2015
@@ -40,15 +40,13 @@ void RoundTripYAMLPass::perform(std::uni
   if (!mb)
     return;
 
-  std::error_code ec = _context.registry().loadFile(
+  std::error_code ec = _context.registry().parseFile(
       std::move(mb.get()), _yamlFile);
   if (ec) {
     // Note: we need a way for Passes to report errors.
     llvm_unreachable("yaml reader not registered or read error");
   }
   File *objFile = _yamlFile[0].get();
-  if (objFile->parse())
-    llvm_unreachable("native reader parse error");
   mergedFile.reset(new SimpleFileWrapper(_context, *objFile));
   llvm::sys::fs::remove(tmpYAMLFile.str());
 }

Modified: lld/trunk/lib/ReaderWriter/ELF/ELFReader.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFReader.h?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFReader.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFReader.h Tue Jan 13 18:21:34 2015
@@ -33,8 +33,8 @@ public:
   }
 
   std::error_code
-  loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
-           std::vector<std::unique_ptr<File>> &result) const override {
+  parseFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
+            std::vector<std::unique_ptr<File>> &result) const override {
     std::size_t maxAlignment =
         1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart()));
     auto f =
@@ -72,8 +72,8 @@ public:
   }
 
   std::error_code
-  loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
-           std::vector<std::unique_ptr<File>> &result) const override {
+  parseFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
+            std::vector<std::unique_ptr<File>> &result) const override {
     std::size_t maxAlignment =
         1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart()));
     auto f =

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFReader.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFReader.h?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFReader.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFReader.h Tue Jan 13 18:21:34 2015
@@ -49,12 +49,12 @@ public:
         _flagMerger(flagMerger) {}
 
   std::error_code
-  loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry &registry,
-           std::vector<std::unique_ptr<File>> &result) const override {
+  parseFile(std::unique_ptr<MemoryBuffer> mb, const Registry &registry,
+            std::vector<std::unique_ptr<File>> &result) const override {
     auto &hdr = *elfHeader(*mb);
     if (std::error_code ec = _flagMerger.merge(hdr.getFileClass(), hdr.e_flags))
       return ec;
-    return BaseReaderType::loadFile(std::move(mb), registry, result);
+    return BaseReaderType::parseFile(std::move(mb), registry, result);
   }
 
 private:
@@ -72,12 +72,12 @@ public:
         _flagMerger(flagMerger) {}
 
   std::error_code
-  loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry &registry,
-           std::vector<std::unique_ptr<File>> &result) const override {
+  parseFile(std::unique_ptr<MemoryBuffer> mb, const Registry &registry,
+            std::vector<std::unique_ptr<File>> &result) const override {
     auto &hdr = *elfHeader(*mb);
     if (std::error_code ec = _flagMerger.merge(hdr.getFileClass(), hdr.e_flags))
       return ec;
-    return BaseReaderType::loadFile(std::move(mb), registry, result);
+    return BaseReaderType::parseFile(std::move(mb), registry, result);
   }
 
 private:

Modified: lld/trunk/lib/ReaderWriter/FileArchive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/FileArchive.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/FileArchive.cpp (original)
+++ lld/trunk/lib/ReaderWriter/FileArchive.cpp Tue Jan 13 18:21:34 2015
@@ -67,9 +67,7 @@ public:
 
   /// \brief parse each member
   std::error_code
-  parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
-    if (std::error_code ec = parse())
-      return ec;
+  parseAllMembers(std::vector<std::unique_ptr<File>> &result) const override {
     for (auto mf = _archive->child_begin(), me = _archive->child_end();
          mf != me; ++mf) {
       std::unique_ptr<File> file;
@@ -154,12 +152,9 @@ private:
         mb.getBuffer(), memberPath, false));
 
     std::vector<std::unique_ptr<File>> files;
-    if (std::error_code ec = _registry.loadFile(std::move(memberMB), files))
-      return ec;
+    _registry.parseFile(std::move(memberMB), files);
     assert(files.size() == 1);
     result = std::move(files[0]);
-    if (std::error_code ec = result->parse())
-      return ec;
 
     // The memory buffer is co-owned by the archive file and the children,
     // so that the bufffer is deallocated when all the members are destructed.
@@ -237,8 +232,8 @@ public:
   }
 
   std::error_code
-  loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry &reg,
-           std::vector<std::unique_ptr<File>> &result) const override {
+  parseFile(std::unique_ptr<MemoryBuffer> mb, const Registry &reg,
+            std::vector<std::unique_ptr<File>> &result) const override {
     StringRef path = mb->getBufferIdentifier();
     std::unique_ptr<FileArchive> file(
         new FileArchive(std::move(mb), reg, path, _logLoading));

Modified: lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp Tue Jan 13 18:21:34 2015
@@ -91,7 +91,7 @@ public:
   }
 
   std::error_code
-  parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
+  parseAllMembers(std::vector<std::unique_ptr<File>> &result) const override {
     return std::error_code();
   }
 

Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Tue Jan 13 18:21:34 2015
@@ -12,8 +12,8 @@
 #include "File.h"
 #include "MachONormalizedFile.h"
 #include "MachOPasses.h"
-#include "lld/Core/ArchiveLibraryFile.h"
 #include "lld/Core/PassManager.h"
+#include "lld/Driver/DarwinInputGraph.h"
 #include "lld/Passes/LayoutPass.h"
 #include "lld/Passes/RoundTripYAMLPass.h"
 #include "lld/ReaderWriter/Reader.h"
@@ -605,18 +605,20 @@ Writer &MachOLinkingContext::writer() co
 }
 
 MachODylibFile* MachOLinkingContext::loadIndirectDylib(StringRef path) {
-  ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr
-      = MemoryBuffer::getFileOrSTDIN(path);
-  if (mbOrErr.getError())
+  std::unique_ptr<MachOFileNode> node(new MachOFileNode(path, *this));
+  std::error_code ec = node->parse(*this, llvm::errs());
+  if (ec)
     return nullptr;
 
-  std::vector<std::unique_ptr<File>> files;
-  if (registry().loadFile(std::move(mbOrErr.get()), files))
-    return nullptr;
-  assert(files.size() == 1 && "expected one file in dylib");
-  MachODylibFile* result = reinterpret_cast<MachODylibFile*>(files[0].get());
+  assert(node->files().size() == 1 && "expected one file in dylib");
+  // lld::File object is owned by MachOFileNode object. This method returns
+  // an unowned pointer to the lld::File object.
+  MachODylibFile* result = reinterpret_cast<MachODylibFile*>(
+                                                   node->files().front().get());
+
   // Node object now owned by _indirectDylibs vector.
-  _indirectDylibs.push_back(std::move(files[0]));
+  _indirectDylibs.push_back(std::move(node));
+
   return result;
 }
 
@@ -928,7 +930,9 @@ bool MachOLinkingContext::customAtomOrde
 
 static File *getFirstFile(const std::unique_ptr<InputElement> &elem) {
   FileNode *e = dyn_cast<FileNode>(const_cast<InputElement *>(elem.get()));
-  return e ? e->getFile() : nullptr;
+  if (!e || e->files().empty())
+    return nullptr;
+  return e->files()[0].get();
 }
 
 static bool isLibrary(const std::unique_ptr<InputElement> &elem) {

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp Tue Jan 13 18:21:34 2015
@@ -527,8 +527,8 @@ public:
   }
 
   std::error_code
-  loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry &registry,
-           std::vector<std::unique_ptr<File>> &result) const override {
+  parseFile(std::unique_ptr<MemoryBuffer> mb, const Registry &registry,
+            std::vector<std::unique_ptr<File>> &result) const override {
     auto *file = new MachOFile(std::move(mb), &_ctx);
     result.push_back(std::unique_ptr<MachOFile>(file));
     return std::error_code();
@@ -554,8 +554,8 @@ public:
   }
 
   std::error_code
-  loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry &registry,
-           std::vector<std::unique_ptr<File>> &result) const override {
+  parseFile(std::unique_ptr<MemoryBuffer> mb, const Registry &registry,
+            std::vector<std::unique_ptr<File>> &result) const override {
     auto *file = new MachODylibFile(std::move(mb), &_ctx);
     result.push_back(std::unique_ptr<MachODylibFile>(file));
     return std::error_code();
@@ -580,3 +580,4 @@ void Registry::addSupportMachOObjects(Ma
 
 
 } // namespace lld
+

Modified: lld/trunk/lib/ReaderWriter/Native/ReaderNative.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/Native/ReaderNative.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/Native/ReaderNative.cpp (original)
+++ lld/trunk/lib/ReaderWriter/Native/ReaderNative.cpp Tue Jan 13 18:21:34 2015
@@ -999,8 +999,8 @@ public:
   }
 
   virtual std::error_code
-  loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
-           std::vector<std::unique_ptr<File>> &result) const override {
+  parseFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
+            std::vector<std::unique_ptr<File>> &result) const override {
     auto *file = new lld::native::File(std::move(mb));
     result.push_back(std::unique_ptr<File>(file));
     return std::error_code();

Modified: lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h Tue Jan 13 18:21:34 2015
@@ -88,7 +88,7 @@ public:
   }
 
   std::error_code
-  parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
+  parseAllMembers(std::vector<std::unique_ptr<File>> &result) const override {
     return std::error_code();
   }
 
@@ -174,6 +174,45 @@ private:
   mutable llvm::BumpPtrAllocator _alloc;
 };
 
+class ResolvableSymbols {
+public:
+  void add(File *file) {
+    std::lock_guard<std::mutex> lock(_mutex);
+    if (_seen.count(file) > 0)
+      return;
+    _seen.insert(file);
+    _queue.insert(file);
+  }
+
+  const std::set<std::string> &defined() {
+    readAllSymbols();
+    return _defined;
+  }
+
+private:
+  // Files are read lazily, so that it has no runtime overhead if
+  // no one accesses this class.
+  void readAllSymbols() {
+    std::lock_guard<std::mutex> lock(_mutex);
+    for (File *file : _queue) {
+      if (auto *archive = dyn_cast<ArchiveLibraryFile>(file)) {
+        for (const std::string &sym : archive->getDefinedSymbols())
+          _defined.insert(sym);
+        continue;
+      }
+      for (const DefinedAtom *atom : file->defined())
+        if (!atom->name().empty())
+          _defined.insert(atom->name());
+    }
+    _queue.clear();
+  }
+
+  std::set<std::string> _defined;
+  std::set<File *> _seen;
+  std::set<File *> _queue;
+  std::mutex _mutex;
+};
+
 // A ExportedSymbolRenameFile is a virtual archive file for dllexported symbols.
 //
 // One usually has to specify the exact symbol name to resolve it. That's true
@@ -207,7 +246,7 @@ private:
 class ExportedSymbolRenameFile : public impl::VirtualArchiveLibraryFile {
 public:
   ExportedSymbolRenameFile(const PECOFFLinkingContext &ctx,
-                           ResolvableSymbols *syms)
+                           std::shared_ptr<ResolvableSymbols> syms)
       : VirtualArchiveLibraryFile("<export>"), _syms(syms),
         _ctx(const_cast<PECOFFLinkingContext *>(&ctx)) {
     for (PECOFFLinkingContext::ExportDesc &desc : _ctx->getDllExports())
@@ -219,7 +258,7 @@ public:
     if (_exportedSyms.count(sym) == 0)
       return nullptr;
     std::string replace;
-    if (!findDecoratedSymbol(_ctx, _syms, sym.str(), replace))
+    if (!findDecoratedSymbol(_ctx, _syms.get(), sym.str(), replace))
       return nullptr;
 
     for (ExportDesc &exp : _ctx->getDllExports())
@@ -232,7 +271,7 @@ public:
 
 private:
   std::set<std::string> _exportedSyms;
-  ResolvableSymbols *_syms;
+  std::shared_ptr<ResolvableSymbols> _syms;
   mutable llvm::BumpPtrAllocator _alloc;
   mutable PECOFFLinkingContext *_ctx;
 };
@@ -245,7 +284,7 @@ private:
 class EntryPointFile : public SimpleFile {
 public:
   EntryPointFile(const PECOFFLinkingContext &ctx,
-                 ResolvableSymbols *syms)
+                 std::shared_ptr<ResolvableSymbols> syms)
       : SimpleFile("<entry>"), _ctx(const_cast<PECOFFLinkingContext *>(&ctx)),
         _syms(syms), _firstTime(true) {}
 
@@ -277,7 +316,7 @@ private:
     StringRef opt = _ctx->getEntrySymbolName();
     if (!opt.empty()) {
       std::string mangled;
-      if (findDecoratedSymbol(_ctx, _syms, opt, mangled))
+      if (findDecoratedSymbol(_ctx, _syms.get(), opt, mangled))
         return mangled;
       return _ctx->decorateSymbol(opt);
     }
@@ -302,7 +341,7 @@ private:
       if (_syms->defined().count(sym))
         return true;
       std::string ignore;
-      return findDecoratedSymbol(_ctx, _syms, sym, ignore);
+      return findDecoratedSymbol(_ctx, _syms.get(), sym, ignore);
     };
 
     switch (_ctx->getSubsystem()) {
@@ -333,7 +372,7 @@ private:
   PECOFFLinkingContext *_ctx;
   atom_collection_vector<UndefinedAtom> _undefinedAtoms;
   std::mutex _mutex;
-  ResolvableSymbols *_syms;
+  std::shared_ptr<ResolvableSymbols> _syms;
   llvm::BumpPtrAllocator _alloc;
   bool _firstTime;
 };

Modified: lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp Tue Jan 13 18:21:34 2015
@@ -118,7 +118,9 @@ bool PECOFFLinkingContext::createImplici
       llvm::make_unique<pecoff::LocallyImportedSymbolFile>(*this));
   getInputGraph().addInputElement(std::move(impFileNode));
 
-  pecoff::ResolvableSymbols* syms = getResolvableSymsFile();
+  std::shared_ptr<pecoff::ResolvableSymbols> syms(
+      new pecoff::ResolvableSymbols());
+  getInputGraph().registerObserver([=](File *file) { syms->add(file); });
 
   // Create a file for dllexported symbols.
   auto exportNode = llvm::make_unique<SimpleFileNode>("<export>");
@@ -329,27 +331,4 @@ void PECOFFLinkingContext::addPasses(Pas
   pm.add(std::unique_ptr<Pass>(new pecoff::InferSubsystemPass(*this)));
 }
 
-void pecoff::ResolvableSymbols::add(File *file) {
-  std::lock_guard<std::mutex> lock(_mutex);
-  if (_seen.count(file) > 0)
-    return;
-  _seen.insert(file);
-  _queue.insert(file);
-}
-
-void pecoff::ResolvableSymbols::readAllSymbols() {
-  std::lock_guard<std::mutex> lock(_mutex);
-  for (File *file : _queue) {
-    if (auto *archive = dyn_cast<ArchiveLibraryFile>(file)) {
-      for (const std::string &sym : archive->getDefinedSymbols())
-	_defined.insert(sym);
-      continue;
-    }
-    for (const DefinedAtom *atom : file->defined())
-      if (!atom->name().empty())
-	_defined.insert(atom->name());
-  }
-  _queue.clear();
-}
-
 } // end namespace lld

Modified: lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp Tue Jan 13 18:21:34 2015
@@ -1077,8 +1077,8 @@ public:
   }
 
   std::error_code
-  loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry &,
-           std::vector<std::unique_ptr<File>> &result) const override {
+  parseFile(std::unique_ptr<MemoryBuffer> mb, const Registry &,
+            std::vector<std::unique_ptr<File>> &result) const override {
     // Parse the memory buffer as PECOFF file.
     auto *file = new FileCOFF(std::move(mb), _ctx);
     result.push_back(std::unique_ptr<File>(file));

Modified: lld/trunk/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp Tue Jan 13 18:21:34 2015
@@ -364,8 +364,8 @@ public:
   }
 
   std::error_code
-  loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
-           std::vector<std::unique_ptr<File> > &result) const override {
+  parseFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
+            std::vector<std::unique_ptr<File> > &result) const override {
     auto *file = new FileImportLibrary(std::move(mb), _machine);
     result.push_back(std::unique_ptr<File>(file));
     return std::error_code();

Modified: lld/trunk/lib/ReaderWriter/Reader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/Reader.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/Reader.cpp (original)
+++ lld/trunk/lib/ReaderWriter/Reader.cpp Tue Jan 13 18:21:34 2015
@@ -30,8 +30,8 @@ void Registry::add(std::unique_ptr<YamlI
 }
 
 std::error_code
-Registry::loadFile(std::unique_ptr<MemoryBuffer> mb,
-                   std::vector<std::unique_ptr<File>> &result) const {
+Registry::parseFile(std::unique_ptr<MemoryBuffer> mb,
+                    std::vector<std::unique_ptr<File>> &result) const {
   // Get file type.
   StringRef content(mb->getBufferStart(), mb->getBufferSize());
   llvm::sys::fs::file_magic fileType = llvm::sys::fs::identify_magic(content);
@@ -42,8 +42,11 @@ Registry::loadFile(std::unique_ptr<Memor
   for (const std::unique_ptr<Reader> &reader : _readers) {
     if (!reader->canParse(fileType, extension, *mb))
       continue;
-    if (std::error_code ec = reader->loadFile(std::move(mb), *this, result))
+    if (std::error_code ec = reader->parseFile(std::move(mb), *this, result))
       return ec;
+    for (std::unique_ptr<File> &file : result)
+      if (std::error_code ec = file->parse())
+        return ec;
     return std::error_code();
   }
 

Modified: lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp (original)
+++ lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp Tue Jan 13 18:21:34 2015
@@ -648,7 +648,7 @@ template <> struct MappingTraits<const l
     }
 
     virtual std::error_code
-    parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
+    parseAllMembers(std::vector<std::unique_ptr<File>> &result) const override {
       return std::error_code();
     }
 
@@ -1325,8 +1325,8 @@ public:
   }
 
   std::error_code
-  loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
-           std::vector<std::unique_ptr<File>> &result) const override {
+  parseFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
+            std::vector<std::unique_ptr<File>> &result) const override {
     // Create YAML Input Reader.
     YamlContext yamlContext;
     yamlContext._registry = &_registry;
@@ -1343,7 +1343,7 @@ public:
 
     std::shared_ptr<MemoryBuffer> smb(mb.release());
     for (const File *file : createdFiles) {
-      // Note: loadFile() should return vector of *const* File
+      // Note: parseFile() should return vector of *const* File
       File *f = const_cast<File *>(file);
       f->setLastError(std::error_code());
       f->setSharedMemoryBuffer(smb);

Added: lld/trunk/test/Driver/libsearch-inputGraph.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/Driver/libsearch-inputGraph.test?rev=225859&view=auto
==============================================================================
--- lld/trunk/test/Driver/libsearch-inputGraph.test (added)
+++ lld/trunk/test/Driver/libsearch-inputGraph.test Tue Jan 13 18:21:34 2015
@@ -0,0 +1,39 @@
+RUN: lld -flavor gnu -target x86_64-linux -L%p/../elf/Inputs -lfnarchive \
+RUN:   --output-filetype=yaml --noinhibit-exec 2> %t.err
+RUN: FileCheck %s < %t.err
+
+RUN: lld -flavor gnu -target x86_64-linux  -L%p/../elf/Inputs --whole-archive \
+RUN:   -lfnarchive --output-filetype=yaml --noinhibit-exec 2> %t1.err
+RUN: FileCheck %s -check-prefix="WHOLEARCHIVE" < %t1.err
+
+RUN: lld -flavor gnu -target x86_64-linux  -L%p/../elf/Inputs --whole-archive \
+RUN:   --as-needed -lfnarchive --output-filetype=yaml --noinhibit-exec 2> %t2.err
+RUN: FileCheck %s -check-prefix="ASNEEDED" < %t2.err
+
+RUN: lld -flavor gnu -target x86_64-linux  --sysroot=%p/../elf -L=/Inputs \
+RUN:   -lfnarchive --output-filetype=yaml --noinhibit-exec 2> %t3.err
+RUN: FileCheck -check-prefix="SYSROOT" %s < %t3.err
+
+CHECK: Name    : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
+CHECK: Type    : ELF File
+CHECK: Attributes :
+CHECK:   - wholeArchive : false
+CHECK:   - asNeeded : false
+
+WHOLEARCHIVE: Name    : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
+WHOLEARCHIVE: Type    : ELF File
+WHOLEARCHIVE: Attributes :
+WHOLEARCHIVE:   - wholeArchive : true
+WHOLEARCHIVE:   - asNeeded : false
+
+ASNEEDED: Name    : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
+ASNEEDED: Type    : ELF File
+ASNEEDED: Attributes :
+ASNEEDED:   - wholeArchive : true
+ASNEEDED:   - asNeeded : true
+
+SYSROOT: Name    : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
+SYSROOT: Type    : ELF File
+SYSROOT: Attributes :
+SYSROOT:   - wholeArchive : false
+SYSROOT:   - asNeeded : false

Modified: lld/trunk/test/pecoff/hello64.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/hello64.test?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/test/pecoff/hello64.test (original)
+++ lld/trunk/test/pecoff/hello64.test Tue Jan 13 18:21:34 2015
@@ -12,9 +12,9 @@ CHECK: 6019: 41 b9 00 00 00 00       mov
 CHECK: 601f: e8 0a 00 00 00          callq   10
 CHECK: 6024: b9 00 00 00 00          movl    $0, %ecx
 CHECK: 6029: e8 08 00 00 00          callq   8
-CHECK: 602e: ff 25 d2 cf ff ff       jmpq    *-12334(%rip)
+CHECK: 602e: ff 25 d4 cf ff ff       jmpq    *-12332(%rip)
 CHECK: 6034: cc                      int3
 CHECK: 6035: cc                      int3
-CHECK: 6036: ff 25 c2 cf ff ff       jmpq    *-12350(%rip)
+CHECK: 6036: ff 25 c4 cf ff ff       jmpq    *-12348(%rip)
 CHECK: 603c: cc                      int3
 CHECK: 603d: cc                      int3

Modified: lld/trunk/unittests/DriverTests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/CMakeLists.txt?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/CMakeLists.txt (original)
+++ lld/trunk/unittests/DriverTests/CMakeLists.txt Tue Jan 13 18:21:34 2015
@@ -4,6 +4,7 @@ add_lld_unittest(DriverTests
   DarwinLdDriverTest.cpp
   WinLinkDriverTest.cpp
   WinLinkModuleDefTest.cpp
+  InputGraphTest.cpp
   )
 
 target_link_libraries(DriverTests

Added: lld/trunk/unittests/DriverTests/InputGraphTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/InputGraphTest.cpp?rev=225859&view=auto
==============================================================================
--- lld/trunk/unittests/DriverTests/InputGraphTest.cpp (added)
+++ lld/trunk/unittests/DriverTests/InputGraphTest.cpp Tue Jan 13 18:21:34 2015
@@ -0,0 +1,122 @@
+//===- lld/unittest/InputGraphTest.cpp -----------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief InputGraph Tests
+///
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "lld/Core/InputGraph.h"
+#include "lld/Core/Resolver.h"
+#include "lld/Core/Simple.h"
+
+using namespace lld;
+
+namespace {
+
+class TestLinkingContext : public LinkingContext {
+public:
+  Writer &writer() const override { llvm_unreachable("no writer!"); }
+  bool validateImpl(raw_ostream &) override { return true; }
+};
+
+class TestExpandFileNode : public SimpleFileNode {
+public:
+  TestExpandFileNode(StringRef path) : SimpleFileNode(path) {}
+
+  /// Returns the elements replacing this node
+  bool getReplacements(InputGraph::InputElementVectorT &result) override {
+    for (std::unique_ptr<InputElement> &elt : _expandElements)
+      result.push_back(std::move(elt));
+    return true;
+  }
+
+  void addElement(std::unique_ptr<InputElement> element) {
+    _expandElements.push_back(std::move(element));
+  }
+
+private:
+  InputGraph::InputElementVectorT _expandElements;
+};
+
+class InputGraphTest : public testing::Test {
+public:
+  InputGraphTest() {
+    _ctx.setInputGraph(std::unique_ptr<InputGraph>(new InputGraph()));
+    _graph = &_ctx.getInputGraph();
+  }
+
+  StringRef getNext() {
+    File *file = _graph->getNextFile();
+    EXPECT_TRUE(file);
+    return file->path();
+  }
+
+  void expectEnd() {
+    File *file = _graph->getNextFile();
+    EXPECT_TRUE(file == nullptr);
+  }
+
+protected:
+  TestLinkingContext _ctx;
+  InputGraph *_graph;
+};
+
+} // end anonymous namespace
+
+static std::unique_ptr<SimpleFileNode> createFile(StringRef name) {
+  std::vector<std::unique_ptr<File>> files;
+  files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name)));
+  std::unique_ptr<SimpleFileNode> file(new SimpleFileNode("filenode"));
+  file->addFiles(std::move(files));
+  return file;
+}
+
+TEST_F(InputGraphTest, Empty) {
+  expectEnd();
+}
+
+TEST_F(InputGraphTest, File) {
+  _graph->addInputElement(createFile("file1"));
+  EXPECT_EQ("file1", getNext());
+  expectEnd();
+}
+
+// Node expansion tests
+TEST_F(InputGraphTest, Normalize) {
+  _graph->addInputElement(createFile("file1"));
+
+  std::unique_ptr<TestExpandFileNode> expandFile(
+      new TestExpandFileNode("node"));
+  expandFile->addElement(createFile("file2"));
+  expandFile->addElement(createFile("file3"));
+  _graph->addInputElement(std::move(expandFile));
+  _graph->normalize();
+
+  EXPECT_EQ("file1", getNext());
+  EXPECT_EQ("file2", getNext());
+  EXPECT_EQ("file3", getNext());
+  expectEnd();
+}
+
+TEST_F(InputGraphTest, Observer) {
+  std::vector<std::string> files;
+  _graph->registerObserver([&](File *file) { files.push_back(file->path()); });
+
+  _graph->addInputElement(createFile("file1"));
+  _graph->addInputElement(createFile("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]);
+}

Modified: lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=225859&r1=225858&r2=225859&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp Tue Jan 13 18:21:34 2015
@@ -698,9 +698,10 @@ TEST_F(WinLinkParserTest, Ignore) {
   // compatibility with link.exe.
   EXPECT_TRUE(parse("link.exe", "/nologo", "/errorreport:prompt",
                     "/incremental", "/incremental:no", "/delay:unload",
-                    "/disallowlib:foo", "/pdbaltpath:bar",
-                    "/wx", "/wx:no", "/tlbid:1", "/tlbout:foo", "/idlout:foo",
-                    "/ignore:4000", "/ignoreidl", "/implib:foo", "/safeseh",
+                    "/disallowlib:foo", "/pdbaltpath:bar", "/verbose",
+                    "/verbose:icf", "/wx", "/wx:no", "/tlbid:1",
+                    "/tlbout:foo", "/idlout:foo", "/ignore:4000",
+                    "/ignoreidl", "/implib:foo", "/safeseh",
                     "/safeseh:no", "/functionpadmin", "/maxilksize:1024",
                     "a.obj", nullptr));
   EXPECT_EQ("", errorMessage());





More information about the llvm-commits mailing list