[lld] r188958 - add InputGraph functionality

Shankar Easwaran shankare at codeaurora.org
Wed Aug 21 15:57:10 PDT 2013


Author: shankare
Date: Wed Aug 21 17:57:10 2013
New Revision: 188958

URL: http://llvm.org/viewvc/llvm-project?rev=188958&view=rev
Log:
add InputGraph functionality

Added:
    lld/trunk/include/lld/Driver/CoreInputGraph.h
    lld/trunk/include/lld/Driver/DarwinInputGraph.h
    lld/trunk/include/lld/Driver/GnuLDInputGraph.h
    lld/trunk/include/lld/Driver/InputGraph.h
    lld/trunk/include/lld/Driver/WinLinkInputGraph.h
    lld/trunk/include/lld/ReaderWriter/MachOFormat.hpp
      - copied, changed from r188318, lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp
    lld/trunk/lib/Driver/InputGraph.cpp
    lld/trunk/test/Driver/libsearch-inputGraph.test
Removed:
    lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp
Modified:
    lld/trunk/include/lld/Core/File.h
    lld/trunk/include/lld/Core/LinkingContext.h
    lld/trunk/include/lld/Driver/Driver.h
    lld/trunk/include/lld/Driver/LinkerInput.h
    lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
    lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
    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/LDOptions.td
    lld/trunk/lib/Driver/WinLinkDriver.cpp
    lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/ReaderLinkerScript.cpp
    lld/trunk/test/elf/X86_64/nmagic.test
    lld/trunk/test/elf/X86_64/omagic.test
    lld/trunk/test/elf/archive-elf-forceload.objtxt
    lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp
    lld/trunk/unittests/DriverTests/DriverTest.h

Modified: lld/trunk/include/lld/Core/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/File.h?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/File.h (original)
+++ lld/trunk/include/lld/Core/File.h Wed Aug 21 17:57:10 2013
@@ -23,6 +23,9 @@
 #include <vector>
 
 namespace lld {
+
+class LinkingContext;
+
 /// Every Atom is owned by some File. A common scenario is for a single
 /// object file (.o) to be parsed by some reader and produce a single
 /// File object that represents the content of that object file.

Modified: lld/trunk/include/lld/Core/LinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/LinkingContext.h?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/LinkingContext.h (original)
+++ lld/trunk/include/lld/Core/LinkingContext.h Wed Aug 21 17:57:10 2013
@@ -15,6 +15,7 @@
 #include "lld/Core/range.h"
 #include "lld/Core/Reference.h"
 
+#include "lld/Driver/InputGraph.h"
 #include "lld/Driver/LinkerInput.h"
 #include "lld/ReaderWriter/Reader.h"
 
@@ -33,6 +34,7 @@ class PassManager;
 class File;
 class Writer;
 class InputFiles;
+class InputGraph;
 
 /// \brief The LinkingContext class encapsulates "what and how" to link.
 ///
@@ -173,7 +175,7 @@ public:
   const std::vector<LinkerInput> &inputFiles() const { return _inputFiles; }
   /// @}
 
-  /// \name Methods used by Drivers to configure LinkingContext
+  /// \name Methods used by Drivers to configure TargetInfo
   /// @{
   void setOutputPath(StringRef str) { _outputPath = str; }
   void setEntrySymbolName(StringRef name) { _entrySymbolName = name; }
@@ -207,6 +209,10 @@ public:
     _inputFiles.emplace_back(LinkerInput(std::move(buffer)));
   }
   void appendLLVMOption(const char *opt) { _llvmOptions.push_back(opt); }
+  virtual void setInputGraph(std::unique_ptr<InputGraph> inputGraph) {
+    _inputGraph = std::move(inputGraph);
+  }
+  virtual InputGraph &inputGraph() const { return *_inputGraph; }
 
   /// This method adds undefined symbols specified by the -u option to the
   /// to the list of undefined symbols known to the linker. This option
@@ -324,6 +330,7 @@ protected:
   std::vector<const char *> _llvmOptions;
   std::unique_ptr<Reader> _yamlReader;
   StringRefVector _initialUndefinedSymbols;
+  std::unique_ptr<InputGraph> _inputGraph;
 
 private:
   /// Validate the subclass bits. Only called by validate.

Added: lld/trunk/include/lld/Driver/CoreInputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/CoreInputGraph.h?rev=188958&view=auto
==============================================================================
--- lld/trunk/include/lld/Driver/CoreInputGraph.h (added)
+++ lld/trunk/include/lld/Driver/CoreInputGraph.h Wed Aug 21 17:57:10 2013
@@ -0,0 +1,52 @@
+//===- lld/Driver/CoreInputGraph.h - Files to be linked for CORE linking---==//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// Handles Options for CORE linking and provides InputElements
+/// for the CORE linker
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_CORE_INPUT_GRAPH_H
+#define LLD_CORE_INPUT_GRAPH_H
+
+#include "lld/Driver/InputGraph.h"
+#include "lld/ReaderWriter/CoreLinkingContext.h"
+
+#include <map>
+
+namespace lld {
+
+/// \brief Represents a CORE File
+class COREFileNode : public FileNode {
+public:
+  COREFileNode(CoreLinkingContext &ctx, StringRef path)
+      : FileNode(path), _ctx(ctx) {}
+
+  static inline bool classof(const InputElement *a) {
+    return a->kind() == InputElement::Kind::File;
+  }
+
+  virtual std::unique_ptr<lld::LinkerInput>
+  createLinkerInput(const lld::LinkingContext &);
+
+  /// \brief validates the Input Element
+  virtual bool validate() { return true; }
+
+  /// \brief Dump the Input Element
+  virtual bool dump(raw_ostream &) { return true; }
+
+private:
+  const CoreLinkingContext &_ctx;
+};
+
+} // namespace lld
+
+#endif

Added: lld/trunk/include/lld/Driver/DarwinInputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/DarwinInputGraph.h?rev=188958&view=auto
==============================================================================
--- lld/trunk/include/lld/Driver/DarwinInputGraph.h (added)
+++ lld/trunk/include/lld/Driver/DarwinInputGraph.h Wed Aug 21 17:57:10 2013
@@ -0,0 +1,53 @@
+//===- lld/Driver/DarwinInputGraph.h - Files to be linked for MachO
+// linking---===//
+//
+//                             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_MachO_INPUT_GRAPH_H
+#define LLD_MachO_INPUT_GRAPH_H
+
+#include "lld/Driver/InputGraph.h"
+#include "lld/ReaderWriter/MachOLinkingContext.h"
+
+#include <map>
+
+namespace lld {
+
+/// \brief Represents a MachO File
+class MachOFileNode : public FileNode {
+public:
+  MachOFileNode(MachOLinkingContext &ctx, StringRef path)
+      : FileNode(path), _ctx(ctx) {}
+
+  static inline bool classof(const InputElement *a) {
+    return a->kind() == InputElement::Kind::File;
+  }
+
+  virtual std::unique_ptr<lld::LinkerInput>
+  createLinkerInput(const lld::LinkingContext &);
+
+  /// \brief validates the Input Element
+  virtual bool validate() { return true; }
+
+  /// \brief Dump the Input Element
+  virtual bool dump(raw_ostream &) { return true; }
+
+private:
+  const MachOLinkingContext &_ctx;
+};
+
+} // 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=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/Driver.h (original)
+++ lld/trunk/include/lld/Driver/Driver.h Wed Aug 21 17:57:10 2013
@@ -18,6 +18,7 @@
 #define LLD_DRIVER_DRIVER_H
 
 #include "lld/Core/LLVM.h"
+#include "lld/Driver/InputGraph.h"
 
 #include "llvm/ADT/Triple.h"
 #include "llvm/Support/raw_ostream.h"
@@ -36,7 +37,7 @@ class ELFLinkingContext;
 class Driver {
 protected:
 
-  /// Performs link using specified options.
+  /// Performs link using specified options
   static bool link(const LinkingContext &context,
                    raw_ostream &diagnostics = llvm::errs());
 
@@ -44,7 +45,6 @@ private:
   Driver() LLVM_DELETED_FUNCTION;
 };
 
-
 /// Driver for "universal" lld tool which can mimic any linker command line
 /// parsing once it figures out which command line flavor to use.
 class UniversalDriver : public Driver {
@@ -133,9 +133,6 @@ private:
   CoreDriver() LLVM_DELETED_FUNCTION;
 };
 
-
-
-
 } // end namespace lld
 
 #endif

Added: lld/trunk/include/lld/Driver/GnuLDInputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/GnuLDInputGraph.h?rev=188958&view=auto
==============================================================================
--- lld/trunk/include/lld/Driver/GnuLDInputGraph.h (added)
+++ lld/trunk/include/lld/Driver/GnuLDInputGraph.h Wed Aug 21 17:57:10 2013
@@ -0,0 +1,103 @@
+//===- lld/Driver/GnuLDInputGraph.h - Files to be linked for ELF linking---===//
+//
+//                             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_ELF_INPUT_GRAPH_H
+#define LLD_ELF_INPUT_GRAPH_H
+
+#include "lld/Driver/InputGraph.h"
+#include "lld/ReaderWriter/ELFLinkingContext.h"
+
+namespace lld {
+
+/// \brief Represents a ELF File
+class ELFFileNode : public FileNode {
+public:
+  ELFFileNode(ELFLinkingContext &ctx, StringRef path,
+              bool isWholeArchive = false, bool asNeeded = false,
+              std::vector<StringRef> searchPath = { "" })
+      : FileNode(path), _elfLinkingContext(ctx),
+        _isWholeArchive(isWholeArchive), _asNeeded(asNeeded) {
+    std::copy(searchPath.begin(), searchPath.end(),
+              std::back_inserter(_libraryPaths));
+  }
+
+  static inline bool classof(const InputElement *a) {
+    return a->kind() == InputElement::Kind::File;
+  }
+
+  virtual StringRef path(const LinkingContext &ctx) const;
+
+  virtual std::unique_ptr<lld::LinkerInput>
+  createLinkerInput(const lld::LinkingContext &);
+
+  /// \brief validates the Input Element
+  virtual bool validate() { return true; }
+
+  /// \brief Dump the Input Element
+  virtual bool dump(raw_ostream &diagnostics) {
+    diagnostics << "Name    : " << path(_elfLinkingContext) << "\n";
+    diagnostics << "Type    : "
+                << "ELF File"
+                << "\n";
+    diagnostics << "Ordinal : " << getOrdinal() << "\n";
+    diagnostics << "Attributes : "
+                << "\n";
+    diagnostics << "  - wholeArchive : "
+                << ((_isWholeArchive) ? "true" : "false") << "\n";
+    diagnostics << "  - asNeeded : " << ((_asNeeded) ? "true" : "false")
+                << "\n";
+    diagnostics << "  contextPath : " << ((_libraryPaths.size()) ? "" : "None")
+                << "\n";
+    for (auto path : _libraryPaths)
+      diagnostics << "    - " << path << "\n";
+    return true;
+  }
+
+private:
+  ELFLinkingContext &_elfLinkingContext;
+  bool _isWholeArchive : 1;
+  bool _asNeeded : 1;
+  std::vector<StringRef> _libraryPaths;
+};
+
+/// \brief Represents a ELF control node
+class ELFGroup : public Group {
+public:
+  ELFGroup(ELFLinkingContext &ctx) : Group(), _elfLinkingContext(ctx) {}
+
+  static inline bool classof(const InputElement *a) {
+    return a->kind() == InputElement::Kind::Control;
+  }
+
+  virtual std::unique_ptr<lld::LinkerInput>
+  createLinkerInput(const lld::LinkingContext &) {
+    // FIXME : create a linker input to handle groups
+    return nullptr;
+  }
+
+  /// \brief Validate the options
+  virtual bool validate() { return true; }
+
+  /// \brief Dump the ELFGroup
+  virtual bool dump(llvm::raw_ostream &) { return true; }
+
+private:
+  ELFLinkingContext &_elfLinkingContext;
+};
+
+} // namespace lld
+
+#endif

Added: lld/trunk/include/lld/Driver/InputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/InputGraph.h?rev=188958&view=auto
==============================================================================
--- lld/trunk/include/lld/Driver/InputGraph.h (added)
+++ lld/trunk/include/lld/Driver/InputGraph.h Wed Aug 21 17:57:10 2013
@@ -0,0 +1,245 @@
+//===- lld/Core/InputGraph.h - Files to be linked -------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// Inputs to the linker in the form of a Graph.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_INPUTGRAPH_H
+#define LLD_INPUTGRAPH_H
+
+#include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
+#include "lld/Driver/LinkerInput.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <memory>
+#include <stack>
+#include <vector>
+
+namespace lld {
+
+class InputElement;
+class LinkingContext;
+
+/// \brief The inputs to the linker are represented by an InputGraph. The
+/// nodes in the input graph contains Input elements. The InputElements are
+/// either Input Files or Control Options. The Input Files represent each Input
+/// File to the linker and the control option specify what the linker needs
+/// to do when it processes the option. Each InputElement that is part of the
+/// Graph has also an Ordinal value associated with it. The ordinal value is
+/// needed for components to figure out the relative position of the arguments
+/// that appeared in the Command Line. One such example is adding the list of
+/// dynamic dynamic libraries to the DT_NEEDED list with the ELF Flavor. The
+/// InputElements also have a weight function that can be used to determine the
+/// weight of the file, for statistical purposes. The InputGraph also would
+/// contain a set of General options that are processed by the linker, which
+/// control the output
+class InputGraph {
+public:
+  typedef std::vector<std::unique_ptr<InputElement> > InputElementVectorT;
+  typedef InputElementVectorT::iterator InputElementIterT;
+
+  /// \brief Initialize the inputgraph
+  InputGraph() : _ordinal(0), _numElements(0), _numFiles(0) {}
+
+  /// \brief Adds a node into the InputGraph
+  virtual bool addInputElement(std::unique_ptr<InputElement>);
+
+  /// \brief Set Ordinals for all the InputElements that form the InputGraph
+  virtual bool assignOrdinals();
+
+  /// Destructor
+  virtual ~InputGraph() {}
+
+  /// Total number of InputFiles
+  virtual int64_t numFiles() const { return _numFiles; }
+
+  /// Total number of InputElements
+  virtual int64_t numElements() const { return _numElements; }
+
+  /// \brief Do postprocessing of the InputGraph if there is a need for the
+  /// to provide additional information to the user, also rearranges
+  /// InputElements by their ordinals. If an user wants to place an input file
+  /// at the desired position, the user can do that
+  virtual void doPostProcess();
+
+  /// \brief Iterators
+  InputElementIterT begin() { return _inputArgs.begin(); }
+
+  InputElementIterT end() { return _inputArgs.end(); }
+
+  /// \brief Validate the input graph
+  virtual bool validate();
+
+  /// \brief Dump the input Graph
+  virtual bool dump(raw_ostream &diagnostics = llvm::errs());
+
+  InputElement &operator[](uint32_t index) const {
+    return (*_inputArgs[index]);
+  }
+
+private:
+  // Input arguments
+  InputElementVectorT _inputArgs;
+  // Ordinals
+  int64_t _ordinal;
+  // Total number of InputElements
+  int64_t _numElements;
+  // Total number of FileNodes
+  int64_t _numFiles;
+};
+
+/// \brief This describes each element in the InputGraph. The Kind
+/// determines what the current node contains.
+class InputElement {
+public:
+  /// Each input element in the graph can be a File or a control
+  enum class Kind : uint8_t {
+    Control,  // Represents a type associated with ControlNodes
+        File, // Represents a type associated with File Nodes
+  };
+
+  /// \brief Initialize the Input Element, The ordinal value of an input Element
+  /// is initially set to -1, if the user wants to override its ordinal,
+  /// let the user do it
+  InputElement(Kind type, int64_t ordinal = -1)
+      : _kind(type), _ordinal(-1), _weight(0) {}
+
+  virtual ~InputElement() {}
+
+  /// Return the Element Type for an Input Element
+  virtual Kind kind() const { return _kind; }
+
+  virtual void setOrdinal(int64_t ordinal) {
+    if (_ordinal != -1)
+      _ordinal = ordinal;
+  }
+
+  virtual int64_t getOrdinal() const { return _ordinal; }
+
+  virtual int64_t weight() const { return 0; }
+
+  virtual void setWeight() { return; }
+
+  /// \brief validates the Input Element
+  virtual bool validate() = 0;
+
+  /// \brief Dump the Input Element
+  virtual bool dump(raw_ostream &diagnostics) = 0;
+
+private:
+  Kind _kind;
+  int64_t _ordinal;
+  int64_t _weight;
+};
+
+/// \brief The Control class represents a control node in the InputGraph
+class ControlNode : public InputElement {
+public:
+  /// A control node could be of several types supported by InputGraph
+  /// Future kinds of Control node could be added
+  enum class ControlKind : uint8_t {
+    Simple,   // Represents a simple control node
+        Group // Represents a type associated with ControlNodes
+  };
+
+  ControlNode(ControlNode::ControlKind controlKind =
+                  ControlNode::ControlKind::Simple,
+              int64_t _ordinal = -1)
+      : InputElement(InputElement::Kind::Control, _ordinal),
+        _controlKind(controlKind) {}
+
+  virtual ~ControlNode() {}
+
+  /// \brief Return the kind of control node
+  virtual ControlNode::ControlKind controlKind() { return _controlKind; }
+
+  /// \brief Process control start/exit
+  virtual bool processControlEnter() { return true; }
+
+  /// \brief Process control start/exit
+  virtual bool processControlExit() { return true; }
+
+  /// Process the input Elemenet
+  virtual bool processInputElement(std::unique_ptr<InputElement> element) = 0;
+
+  /// \brief Casting support
+  static inline bool classof(const InputElement *a) {
+    return a->kind() == InputElement::Kind::Control;
+  }
+
+  /// Does the control node have any more elements
+  bool hasMoreElements() const { return (_elements.size() != 0); }
+
+  /// \brief Iterators to iterate the
+  InputGraph::InputElementIterT begin() { return _elements.begin(); }
+
+  InputGraph::InputElementIterT end() { return _elements.end(); }
+
+  /// \brief Create a lld::File node from the FileNode
+  virtual std::unique_ptr<LinkerInput>
+  createLinkerInput(const LinkingContext &targetInfo) = 0;
+
+private:
+  ControlKind _controlKind;
+
+protected:
+  InputGraph::InputElementVectorT _elements;
+};
+
+/// \brief Represents an Input file in the graph
+class FileNode : public InputElement {
+public:
+  FileNode(StringRef path, int64_t ordinal = -1)
+      : InputElement(InputElement::Kind::File, ordinal), _path(path) {}
+
+  virtual StringRef path(const LinkingContext &) const { return _path; }
+
+  virtual ~FileNode() {}
+
+  /// \brief Casting support
+  static inline bool classof(const InputElement *a) {
+    return a->kind() == InputElement::Kind::File;
+  }
+
+  /// \brief Create a lld::File node from the FileNode
+  virtual std::unique_ptr<LinkerInput>
+  createLinkerInput(const LinkingContext &targetInfo) = 0;
+
+protected:
+  StringRef _path;
+};
+
+/// \brief A Control node which contains a group of InputElements
+/// This affects the resolver so that it resolves undefined symbols
+/// in the group completely before looking at other input files that
+/// follow the group
+class Group : public ControlNode {
+public:
+  Group() : ControlNode(ControlNode::ControlKind::Group) {}
+
+  static inline bool classof(const InputElement *a) {
+    return a->kind() == InputElement::Kind::Control;
+  }
+
+  virtual bool processInputElement(std::unique_ptr<InputElement> element) {
+    _elements.push_back(std::move(element));
+    return true;
+  }
+
+  virtual std::unique_ptr<lld::LinkerInput>
+  createLinkerInput(const lld::LinkingContext &) = 0;
+};
+
+} // namespace lld
+
+#endif // LLD_INPUTGRAPH_H

Modified: lld/trunk/include/lld/Driver/LinkerInput.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/LinkerInput.h?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/LinkerInput.h (original)
+++ lld/trunk/include/lld/Driver/LinkerInput.h Wed Aug 21 17:57:10 2013
@@ -45,15 +45,16 @@ class LinkerInput {
   LinkerInput(const LinkerInput &) LLVM_DELETED_FUNCTION;
 
 public:
-  explicit LinkerInput(StringRef file) : _file(file) {}
+  explicit LinkerInput(StringRef file)
+      : _file(file), _isForceLoad(false), _asNeeded(false) {}
 
   explicit LinkerInput(std::unique_ptr<llvm::MemoryBuffer> buffer)
-      : _buffer(std::move(buffer)), _file(_buffer->getBufferIdentifier()) {
-  }
+      : _buffer(std::move(buffer)), _file(_buffer->getBufferIdentifier()),
+        _isForceLoad(false), _asNeeded(false) {}
 
   LinkerInput(LinkerInput &&other)
-      : _buffer(std::move(other._buffer)), _file(std::move(other._file)) {
-  }
+      : _buffer(std::move(other._buffer)), _file(std::move(other._file)),
+        _isForceLoad(other.isForceLoad()), _asNeeded(other.asNeeded()) {}
 
   LinkerInput &operator=(LinkerInput &&rhs) {
     _buffer = std::move(rhs._buffer);
@@ -81,13 +82,26 @@ public:
     return std::move(_buffer);
   }
 
+  /// \brief forceLoad is a positional option which when set, requires all
+  /// members in an archive to be force loaded
+  void setForceLoad(bool forceLoad) { _isForceLoad = forceLoad; }
+
+  bool isForceLoad() const { return _isForceLoad; }
+
+  /// \brief asneeded is a positional option which when set for a file
+  /// makes the file to be needed at runtime only if its resolving
+  /// undefined symbols
+  void setAsNeeded(bool asNeeded) { _asNeeded = asNeeded; }
+
+  bool asNeeded() const { return _asNeeded; }
+
 private:
   mutable std::unique_ptr<llvm::MemoryBuffer> _buffer;
   std::string _file;
+  bool _isForceLoad : 1;
+  bool _asNeeded : 1;
 };
 
-
-
 } // 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=188958&view=auto
==============================================================================
--- lld/trunk/include/lld/Driver/WinLinkInputGraph.h (added)
+++ lld/trunk/include/lld/Driver/WinLinkInputGraph.h Wed Aug 21 17:57:10 2013
@@ -0,0 +1,80 @@
+//===- lld/Driver/WinLinkInputGraph.h - Files to be linked for PECOFF
+// linking---===//
+//
+//                             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_PECOFF_INPUT_GRAPH_H
+#define LLD_PECOFF_INPUT_GRAPH_H
+
+#include "lld/Driver/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) {}
+
+  static inline bool classof(const InputElement *a) {
+    return a->kind() == InputElement::Kind::File;
+  }
+
+  virtual StringRef path(const LinkingContext &ctx) const;
+
+  virtual std::unique_ptr<lld::LinkerInput>
+  createLinkerInput(const lld::LinkingContext &);
+
+  /// \brief validates the Input Element
+  virtual bool validate() { return true; }
+
+  /// \brief Dump the Input Element
+  virtual bool dump(raw_ostream &) { return true; }
+
+private:
+  const PECOFFLinkingContext &_ctx;
+};
+
+/// \brief Represents a PECOFF Library File
+class PECOFFLibraryNode : public FileNode {
+public:
+  PECOFFLibraryNode(PECOFFLinkingContext &ctx, StringRef path)
+      : FileNode(path), _ctx(ctx) {}
+
+  static inline bool classof(const InputElement *a) {
+    return a->kind() == InputElement::Kind::File;
+  }
+
+  virtual StringRef path(const LinkingContext &ctx) const;
+
+  virtual std::unique_ptr<lld::LinkerInput>
+  createLinkerInput(const lld::LinkingContext &);
+
+  /// \brief validates the Input Element
+  virtual bool validate() { return true; }
+
+  /// \brief Dump the Input Element
+  virtual bool dump(raw_ostream &) { return true; }
+
+private:
+  const PECOFFLinkingContext &_ctx;
+};
+
+} // namespace lld
+
+#endif

Modified: lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h Wed Aug 21 17:57:10 2013
@@ -150,11 +150,9 @@ public:
   /// \brief Disallow dynamic libraries during linking
   virtual void setNoAllowDynamicLibraries() { _noAllowDynamicLibraries = true; }
 
-  void appendSearchPath(StringRef dirPath) {
-    _inputSearchPaths.push_back(dirPath);
-  }
-  /// Searches directories then calls appendInputFile()
-  bool appendLibrary(StringRef libName);
+  /// Searches directories for a match on the input File
+  StringRef searchLibrary(StringRef libName,
+                          const std::vector<StringRef> &searchPath) const;
 
 private:
   ELFLinkingContext() LLVM_DELETED_FUNCTION;
@@ -178,7 +176,7 @@ protected:
   bool _noAllowDynamicLibraries;
   OutputMagic _outputMagic;
   StringRefVector _inputSearchPaths;
-  llvm::BumpPtrAllocator _extraStrings;
+  mutable llvm::BumpPtrAllocator _alloc;
   std::unique_ptr<Reader> _elfReader;
   std::unique_ptr<Writer> _writer;
   std::unique_ptr<Reader> _linkerScriptReader;

Copied: lld/trunk/include/lld/ReaderWriter/MachOFormat.hpp (from r188318, lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp)
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOFormat.hpp?p2=lld/trunk/include/lld/ReaderWriter/MachOFormat.hpp&p1=lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp&r1=188318&r2=188958&rev=188958&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp (original)
+++ lld/trunk/include/lld/ReaderWriter/MachOFormat.hpp Wed Aug 21 17:57:10 2013
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 //
-// This file contains all the structs and constants needed to write a 
+// This file contains all the structs and constants needed to write a
 // mach-o final linked image.  The names of the structs and constants
 // are the same as in the darwin native header <mach-o/loader.h> so
 // they will be familiar to anyone who has used that header.
@@ -25,9 +25,9 @@ namespace lld {
 namespace mach_o {
 
 
-enum { 
+enum {
   MH_MAGIC    = 0xfeedface,
-  MH_MAGIC_64 = 0xfeedfacf 
+  MH_MAGIC_64 = 0xfeedfacf
 };
 
 enum {
@@ -62,24 +62,24 @@ enum {
 //
 class mach_header {
 public:
-  uint32_t    magic;  
+  uint32_t    magic;
   uint32_t    cputype;
-  uint32_t    cpusubtype;  
-  uint32_t    filetype;  
-  uint32_t    ncmds;    
-  uint32_t    sizeofcmds;  
-  uint32_t    flags;  
-  uint32_t    reserved;  
- 
+  uint32_t    cpusubtype;
+  uint32_t    filetype;
+  uint32_t    ncmds;
+  uint32_t    sizeofcmds;
+  uint32_t    flags;
+  uint32_t    reserved;
+
   uint64_t size() {
     return (magic == 0xfeedfacf) ? 32 : 28;
   }
-  
+
   void copyTo(uint8_t *to, bool swap=false) {
     ::memcpy(to, (char*)&magic, this->size());
   }
- 
-  void recordLoadCommand(const class load_command *lc);    
+
+  void recordLoadCommand(const class load_command *lc);
 };
 
 
@@ -101,14 +101,14 @@ class load_command {
 public:
   const uint32_t  cmd;        // type of load command
   const uint32_t  cmdsize;    // length of load command including this header
-  
+
   load_command(uint32_t cmdNumber, uint32_t sz, bool is64, bool align=false)
     : cmd(cmdNumber), cmdsize(pointerAlign(sz, is64, align)) {
   }
-  
+
   virtual ~load_command() {
   }
-  
+
   virtual void copyTo(uint8_t *to, bool swap=false) = 0;
 private:
   // Load commands must be pointer-size aligned. Most load commands are
@@ -168,7 +168,7 @@ enum {
   S_NON_LAZY_SYMBOL_POINTERS= 0x00000006,
   S_LAZY_SYMBOL_POINTERS    = 0x00000007,
   S_SYMBOL_STUBS            = 0x00000008,
-  
+
   // Other bits in section.flags
   S_ATTR_PURE_INSTRUCTIONS  = 0x80000000,
   S_ATTR_SOME_INSTRUCTIONS  = 0x00000400
@@ -177,32 +177,32 @@ enum {
 
 // section record for 32-bit architectures
 struct section {
-  char      sectname[16];  
-  char      segname[16];  
-  uint32_t  addr;  
-  uint32_t  size;    
-  uint32_t  offset;  
-  uint32_t  align;    
-  uint32_t  reloff;  
-  uint32_t  nreloc;    
-  uint32_t  flags;    
+  char      sectname[16];
+  char      segname[16];
+  uint32_t  addr;
+  uint32_t  size;
+  uint32_t  offset;
+  uint32_t  align;
+  uint32_t  reloff;
+  uint32_t  nreloc;
+  uint32_t  flags;
   uint32_t  reserved1;
-  uint32_t  reserved2;  
+  uint32_t  reserved2;
 };
 
 // section record for 64-bit architectures
 struct section_64 {
-  char      sectname[16];  
-  char      segname[16];  
-  uint64_t  addr;  
-  uint64_t  size;    
-  uint32_t  offset;  
-  uint32_t  align;    
-  uint32_t  reloff;  
-  uint32_t  nreloc;    
-  uint32_t  flags;    
+  char      sectname[16];
+  char      segname[16];
+  uint64_t  addr;
+  uint64_t  size;
+  uint32_t  offset;
+  uint32_t  align;
+  uint32_t  reloff;
+  uint32_t  nreloc;
+  uint32_t  flags;
   uint32_t  reserved1;
-  uint32_t  reserved2;  
+  uint32_t  reserved2;
   uint32_t  reserved3;
 };
 
@@ -210,35 +210,35 @@ struct section_64 {
 //
 // A segment load command has a fixed set of fields followed by an 'nsect'
 // array of section records.  The in-memory object uses a pointer to
-// a dynamically allocated array of sections.  
+// a dynamically allocated array of sections.
 //
 class segment_command : public load_command {
 public:
-  char      segname[16];  
-  uint64_t  vmaddr;    
-  uint64_t  vmsize;    
-  uint64_t  fileoff;  
-  uint64_t  filesize;  
-  uint32_t  maxprot;  
-  uint32_t  initprot;  
-  uint32_t  nsects;    
-  uint32_t  flags;  
+  char      segname[16];
+  uint64_t  vmaddr;
+  uint64_t  vmsize;
+  uint64_t  fileoff;
+  uint64_t  filesize;
+  uint32_t  maxprot;
+  uint32_t  initprot;
+  uint32_t  nsects;
+  uint32_t  flags;
   section_64 *sections;
-  
+
   segment_command(unsigned sectCount, bool is64)
-    : load_command((is64 ? LC_SEGMENT_64 : LC_SEGMENT), 
+    : load_command((is64 ? LC_SEGMENT_64 : LC_SEGMENT),
                    (is64 ? (72 + sectCount*80) : (56 + sectCount*68)),
                    is64),
-     vmaddr(0), vmsize(0), fileoff(0), filesize(0), 
+     vmaddr(0), vmsize(0), fileoff(0), filesize(0),
       maxprot(0), initprot(0), nsects(sectCount), flags(0) {
     sections = new section_64[sectCount];
     this->nsects = sectCount;
   }
-  
+
   ~segment_command() {
     delete sections;
   }
-  
+
   void copyTo(uint8_t *to, bool swap) {
     if ( swap ) {
       assert(0 && "non-native endianness not supported yet");
@@ -284,8 +284,8 @@ private:
     ::memcpy(&to[offset], &value32, sizeof(uint32_t));
   }
 
-  bool is64() { 
-    return (cmd == LC_SEGMENT_64); 
+  bool is64() {
+    return (cmd == LC_SEGMENT_64);
   }
 };
 
@@ -303,8 +303,8 @@ public:
 private:
   StringRef _name;
 public:
-  dylinker_command(StringRef path, bool is64) 
-    : load_command(LC_LOAD_DYLINKER,12 + path.size(), is64, true), 
+  dylinker_command(StringRef path, bool is64)
+    : load_command(LC_LOAD_DYLINKER,12 + path.size(), is64, true),
        name_offset(12), _name(path) {
   }
 
@@ -330,48 +330,48 @@ public:
 //
 class symtab_command : public load_command {
 public:
-  uint32_t  symoff;  
-  uint32_t  nsyms;  
-  uint32_t  stroff;  
-  uint32_t  strsize;  
+  uint32_t  symoff;
+  uint32_t  nsyms;
+  uint32_t  stroff;
+  uint32_t  strsize;
 
-  symtab_command(bool is64) 
-    : load_command(LC_SYMTAB, 24, is64), 
+  symtab_command(bool is64)
+    : load_command(LC_SYMTAB, 24, is64),
       symoff(0), nsyms(0), stroff(0), strsize(0) {
   }
-  
+
   virtual void copyTo(uint8_t *to, bool swap=false) {
     if ( swap ) {
       assert(0 && "non-native endianness not supported yet");
     }
     else {
-      // in-memory matches on-disk, so copy fields 
+      // in-memory matches on-disk, so copy fields
       ::memcpy(to, (uint8_t*)&cmd, 24);
     }
   }
-  
+
 };
 
 
 //
 // The entry_point_command load command holds the offset to the function
-// _main in a dynamic executable.  
+// _main in a dynamic executable.
 //
 class entry_point_command : public load_command {
 public:
-  uint64_t  entryoff;  
-  uint64_t  stacksize; 
+  uint64_t  entryoff;
+  uint64_t  stacksize;
 
-  entry_point_command(bool is64) 
+  entry_point_command(bool is64)
     : load_command(LC_MAIN, 24, is64), entryoff(0), stacksize(0) {
   }
-  
+
   virtual void copyTo(uint8_t *to, bool swap=false) {
     if ( swap ) {
       assert(0 && "non-native endianness not supported yet");
     }
     else {
-      // in-memory matches on-disk, so copy fields 
+      // in-memory matches on-disk, so copy fields
       ::memcpy(to, (uint8_t*)&cmd, 24);
     }
   }
@@ -391,7 +391,7 @@ private:
   uint8_t   *_registerArray;
 
 public:
-  thread_command(uint32_t cpuType, bool is64) 
+  thread_command(uint32_t cpuType, bool is64)
     : load_command(LC_UNIXTHREAD, 16+registersBufferSize(cpuType), is64),
       fields_count(registersBufferSize(cpuType)/4), _cpuType(cpuType) {
     switch ( cpuType ) {
@@ -411,19 +411,19 @@ public:
                                     ::calloc(registersBufferSize(cpuType), 1));
     assert(_registerArray);
   }
-  
+
   virtual void copyTo(uint8_t *to, bool swap=false) {
     if ( swap ) {
       assert(0 && "non-native endianness not supported yet");
     }
     else {
-      // in-memory matches on-disk, so copy fixed fields 
+      // in-memory matches on-disk, so copy fixed fields
       ::memcpy(to, (uint8_t*)&cmd, 16);
       // that register array
       ::memcpy(&to[16], _registerArray, registersBufferSize(_cpuType));
     }
   }
-  
+
   void setPC(uint64_t pc) {
     uint32_t *regs32 = reinterpret_cast<uint32_t*>(_registerArray);
     uint64_t *regs64 = reinterpret_cast<uint64_t*>(_registerArray);
@@ -441,9 +441,9 @@ public:
         assert(0 && "unsupported cpu type");
     }
   }
-  
+
   virtual ~thread_command() {
-    ::free(_registerArray); 
+    ::free(_registerArray);
   }
 
 private:
@@ -459,9 +459,9 @@ private:
     assert(0 && "unsupported cpu type");
     return 0;
   }
-    
-    
-  
+
+
+
 };
 
 
@@ -475,19 +475,19 @@ private:
 struct dylib_command : public load_command {
   uint32_t  name_offset;
   uint32_t  timestamp;
-  uint32_t  current_version;    
+  uint32_t  current_version;
   uint32_t  compatibility_version;
-private:  
+private:
   StringRef _loadPath;
 public:
-  
-  dylib_command(StringRef path, bool is64) 
-    : load_command(LC_LOAD_DYLIB, 24 + path.size(), is64, true), 
-      name_offset(24), timestamp(0), 
+
+  dylib_command(StringRef path, bool is64)
+    : load_command(LC_LOAD_DYLIB, 24 + path.size(), is64, true),
+      name_offset(24), timestamp(0),
       current_version(0x10000), compatibility_version(0x10000),
       _loadPath(path) {
   }
-  
+
   virtual void copyTo(uint8_t *to, bool swap=false) {
     if ( swap ) {
       assert(0 && "non-native endianness not supported yet");
@@ -508,30 +508,30 @@ public:
 // of information needed by dyld to prepare the image for execution.
 //
 struct dyld_info_command : public load_command {
-  uint32_t   rebase_off;  
-  uint32_t   rebase_size;  
-  uint32_t   bind_off;  
-  uint32_t   bind_size;  
-  uint32_t   weak_bind_off;  
-  uint32_t   weak_bind_size; 
+  uint32_t   rebase_off;
+  uint32_t   rebase_size;
+  uint32_t   bind_off;
+  uint32_t   bind_size;
+  uint32_t   weak_bind_off;
+  uint32_t   weak_bind_size;
   uint32_t   lazy_bind_off;
-  uint32_t   lazy_bind_size; 
-  uint32_t   export_off;  
-  uint32_t   export_size;  
+  uint32_t   lazy_bind_size;
+  uint32_t   export_off;
+  uint32_t   export_size;
 
-  dyld_info_command(bool is64) 
-    : load_command(LC_DYLD_INFO_ONLY, 48, is64), 
+  dyld_info_command(bool is64)
+    : load_command(LC_DYLD_INFO_ONLY, 48, is64),
         rebase_off(0), rebase_size(0),
-        bind_off(0), bind_size(0), weak_bind_off(0), weak_bind_size(0), 
+        bind_off(0), bind_size(0), weak_bind_off(0), weak_bind_size(0),
         lazy_bind_off(0), lazy_bind_size(0), export_off(0), export_size(0) {
    }
-  
+
   virtual void copyTo(uint8_t *to, bool swap=false) {
     if ( swap ) {
       assert(0 && "non-native endianness not supported yet");
     }
     else {
-      // in-memory matches on-disk, so copy fields 
+      // in-memory matches on-disk, so copy fields
       ::memcpy(to, (uint8_t*)&cmd, 48);
     }
   }
@@ -585,23 +585,23 @@ enum {
 
 class nlist {
 public:
-  uint32_t  n_strx; 
-  uint8_t   n_type; 
-  uint8_t   n_sect;   
-  uint16_t  n_desc;   
-  uint64_t  n_value;    
-  
+  uint32_t  n_strx;
+  uint8_t   n_type;
+  uint8_t   n_sect;
+  uint16_t  n_desc;
+  uint64_t  n_value;
+
   static unsigned size(bool is64) {
     return (is64 ? 16 : 12);
   }
-  
+
   void copyTo(uint8_t *to, bool is64, bool swap=false) {
     if ( swap ) {
       assert(0 && "non-native endianness not supported yet");
     }
     else {
       if ( is64 ) {
-        // in-memory matches on-disk, so just copy whole struct 
+        // in-memory matches on-disk, so just copy whole struct
         ::memcpy(to, (uint8_t*)&n_strx, 16);
       }
       else {

Modified: lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Wed Aug 21 17:57:10 2013
@@ -37,6 +37,9 @@ public:
     int minorVersion;
   };
 
+  /// \brief Casting support
+  static inline bool classof(const LinkingContext *info) { return true; }
+
   virtual error_code
   parseFile(std::unique_ptr<MemoryBuffer> &mb,
             std::vector<std::unique_ptr<File> > &result) const;
@@ -56,8 +59,7 @@ public:
     return _inputSearchPaths;
   }
 
-  void appendInputFileOrLibrary(std::string path);
-  void appendLibraryFile(StringRef path);
+  StringRef searchLibraryFile(StringRef path) const;
 
   void setBaseAddress(uint64_t addr) { _baseAddress = addr; }
   uint64_t getBaseAddress() const { return _baseAddress; }
@@ -93,13 +95,19 @@ public:
   virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
   virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
 
-  StringRef allocateString(const StringRef &ref) {
+  StringRef allocateString(StringRef ref) {
     char *x = _alloc.Allocate<char>(ref.size() + 1);
     memcpy(x, ref.data(), ref.size());
     x[ref.size()] = '\0';
     return x;
   }
 
+  virtual bool hasInputGraph() {
+    if (_inputGraph)
+      return true;
+    return false;
+  }
+
 private:
   // The start address for the program. The default value for the executable is
   // 0x400000, but can be altered using -base command line option.

Modified: lld/trunk/lib/Driver/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/CMakeLists.txt?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/lib/Driver/CMakeLists.txt (original)
+++ lld/trunk/lib/Driver/CMakeLists.txt Wed Aug 21 17:57:10 2013
@@ -9,6 +9,7 @@ tablegen(LLVM WinLinkOptions.inc -gen-op
 add_public_tablegen_target(DriverOptionsTableGen)
 
 add_lld_library(lldDriver
+  InputGraph.cpp
   CoreDriver.cpp
   DarwinLdDriver.cpp
   Driver.cpp

Modified: lld/trunk/lib/Driver/CoreDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/CoreDriver.cpp?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/lib/Driver/CoreDriver.cpp (original)
+++ lld/trunk/lib/Driver/CoreDriver.cpp Wed Aug 21 17:57:10 2013
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lld/Driver/Driver.h"
+#include "lld/Driver/CoreInputGraph.h"
 #include "lld/ReaderWriter/CoreLinkingContext.h"
 #include "lld/ReaderWriter/Reader.h"
 
@@ -61,103 +62,105 @@ public:
   CoreOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){}
 };
 
-
-
 } // namespace anonymous
 
 
 namespace lld {
 
+std::unique_ptr<lld::LinkerInput>
+COREFileNode::createLinkerInput(const LinkingContext &info) {
+  return std::unique_ptr<LinkerInput>(new LinkerInput(path(info)));
+}
+
 bool CoreDriver::link(int argc, const char *argv[], raw_ostream &diagnostics) {
   CoreLinkingContext info;
   if (parse(argc, argv, info))
     return true;
-  
+
   return Driver::link(info);
 }
 
-bool CoreDriver::parse(int argc, const char *argv[], CoreLinkingContext &info,
+bool CoreDriver::parse(int argc, const char *argv[], CoreLinkingContext &ctx,
                        raw_ostream &diagnostics) {
   // Parse command line options using CoreOptions.td
   std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
   CoreOptTable table;
   unsigned missingIndex;
   unsigned missingCount;
-  parsedArgs.reset(table.ParseArgs(&argv[1], &argv[argc], 
-                                                missingIndex, missingCount));
+  parsedArgs.reset(
+      table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount));
   if (missingCount) {
-    diagnostics  << "error: missing arg value for '"
-                 << parsedArgs->getArgString(missingIndex)
-                 << "' expected " << missingCount << " argument(s).\n";
+    diagnostics << "error: missing arg value for '"
+                << parsedArgs->getArgString(missingIndex) << "' expected "
+                << missingCount << " argument(s).\n";
     return true;
   }
 
-  for (auto it = parsedArgs->filtered_begin(OPT_UNKNOWN),
-            ie = parsedArgs->filtered_end(); it != ie; ++it) {
-    diagnostics  << "warning: ignoring unknown argument: "
-                 << (*it)->getAsString(*parsedArgs) << "\n";
-  }
-  
-  // Copy mllvm
-  for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_mllvm),
-                               ie = parsedArgs->filtered_end();
-       it != ie; ++it) {
-    info.appendLLVMOption((*it)->getValue());
-  }
-  
-  // Handle -e xxx
-  if (llvm::opt::Arg *entry = parsedArgs->getLastArg(OPT_entry))
-    info.setEntrySymbolName(entry->getValue());
-    
-  // Handle -o xxx
-  if (llvm::opt::Arg *outpath = parsedArgs->getLastArg(OPT_output))
-    info.setOutputPath(outpath->getValue());
-  else
-    info.setOutputPath("-");
-    
-  // Handle --dead_strip
-  if (parsedArgs->getLastArg(OPT_dead_strip))
-    info.setDeadStripping(true);
-  else
-    info.setDeadStripping(false);
- 
-  // Handle --keep-globals
-  if (parsedArgs->getLastArg(OPT_keep_globals))
-    info.setGlobalsAreDeadStripRoots(true);
-  else
-    info.setGlobalsAreDeadStripRoots(false);
-  
-  // Handle --undefines-are-errors
-  if (parsedArgs->getLastArg(OPT_undefines_are_errors)) {
-    info.setPrintRemainingUndefines(true);
-    info.setAllowRemainingUndefines(false);
-  }
-  else {
-    info.setPrintRemainingUndefines(false);
-    info.setAllowRemainingUndefines(true);
-  }
+  std::unique_ptr<InputGraph> inputGraph(new InputGraph());
 
-  // Handle --commons-search-archives
-  if (parsedArgs->getLastArg(OPT_commons_search_archives))
-    info.setSearchArchivesToOverrideTentativeDefinitions(true);
-  else
-    info.setSearchArchivesToOverrideTentativeDefinitions(false);
-  
-  // Handle --add-pass xxx option
-  for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_add_pass),
-                               ie = parsedArgs->filtered_end();
-                              it != ie; ++it) {
-    info.addPassNamed((*it)->getValue());
+  // Set default options
+  ctx.setOutputPath("-");
+  ctx.setDeadStripping(false);
+  ctx.setGlobalsAreDeadStripRoots(false);
+  ctx.setPrintRemainingUndefines(false);
+  ctx.setAllowRemainingUndefines(true);
+  ctx.setSearchArchivesToOverrideTentativeDefinitions(false);
+
+  // Process all the arguments and create Input Elements
+  for (auto inputArg : *parsedArgs) {
+    switch (inputArg->getOption().getID()) {
+    case OPT_mllvm:
+      ctx.appendLLVMOption(inputArg->getValue());
+      break;
+
+    case OPT_entry:
+      ctx.setEntrySymbolName(inputArg->getValue());
+      break;
+
+    case OPT_output:
+      ctx.setOutputPath(inputArg->getValue());
+      break;
+
+    case OPT_dead_strip:
+      ctx.setDeadStripping(true);
+      break;
+
+    case OPT_keep_globals:
+      ctx.setGlobalsAreDeadStripRoots(true);
+      break;
+
+    case OPT_undefines_are_errors:
+      ctx.setPrintRemainingUndefines(true);
+      ctx.setAllowRemainingUndefines(false);
+      break;
+
+    case OPT_commons_search_archives:
+      ctx.setSearchArchivesToOverrideTentativeDefinitions(true);
+      break;
+
+    case OPT_add_pass:
+      ctx.addPassNamed(inputArg->getValue());
+      break;
+
+    case OPT_INPUT: {
+      inputGraph->addInputElement(std::unique_ptr<InputElement>(
+          new COREFileNode(ctx, inputArg->getValue())));
+    } break;
+
+    default:
+      break;
+    }
   }
 
-  // Handle input files
-  for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_INPUT),
-                               ie = parsedArgs->filtered_end();
-                              it != ie; ++it) {
-    info.appendInputFile((*it)->getValue());
+  if (!inputGraph->numFiles()) {
+    diagnostics << "No input files\n";
+    return true;
   }
-  
-  return false;
+
+  ctx.setInputGraph(std::move(inputGraph));
+
+  // Validate the combination of options used.
+  return ctx.validate(diagnostics);
 }
 
 } // namespace lld

Modified: lld/trunk/lib/Driver/DarwinLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/DarwinLdDriver.cpp Wed Aug 21 17:57:10 2013
@@ -14,9 +14,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "lld/Driver/Driver.h"
+#include "lld/Driver/DarwinInputGraph.h"
 #include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "../ReaderWriter/MachO/MachOFormat.hpp"
-
+#include "lld/ReaderWriter/MachOFormat.hpp"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Triple.h"
@@ -71,31 +71,35 @@ public:
 
 namespace lld {
 
-bool DarwinLdDriver::linkMachO(int argc, const char *argv[], 
-                                                    raw_ostream &diagnostics) {
-  MachOLinkingContext info;
-  if (parse(argc, argv, info, diagnostics))
+std::unique_ptr<lld::LinkerInput>
+MachOFileNode::createLinkerInput(const LinkingContext &ctx) {
+  return std::unique_ptr<LinkerInput>(new LinkerInput(path(ctx)));
+}
+
+bool DarwinLdDriver::linkMachO(int argc, const char *argv[],
+                               raw_ostream &diagnostics) {
+  MachOLinkingContext ctx;
+  if (parse(argc, argv, ctx, diagnostics))
     return true;
-  if ( info.doNothing() )
+  if (ctx.doNothing())
     return false;
-    
-  return link(info, diagnostics);
+
+  return link(ctx, diagnostics);
 }
 
 bool DarwinLdDriver::parse(int argc, const char *argv[],
-                           MachOLinkingContext &info,
-                           raw_ostream &diagnostics) {
+                           MachOLinkingContext &ctx, raw_ostream &diagnostics) {
   // Parse command line options using DarwinOptions.td
   std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
   DarwinLdOptTable table;
   unsigned missingIndex;
   unsigned missingCount;
-  parsedArgs.reset(table.ParseArgs(&argv[1], &argv[argc], 
-                                                missingIndex, missingCount));
+  parsedArgs.reset(
+      table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount));
   if (missingCount) {
-    diagnostics  << "error: missing arg value for '"
-                 << parsedArgs->getArgString(missingIndex)
-                 << "' expected " << missingCount << " argument(s).\n";
+    diagnostics << "error: missing arg value for '"
+                << parsedArgs->getArgString(missingIndex) << "' expected "
+                << missingCount << " argument(s).\n";
     return true;
   }
 
@@ -104,52 +108,52 @@ bool DarwinLdDriver::parse(int argc, con
     diagnostics  << "warning: ignoring unknown argument: "
                  << (*it)->getAsString(*parsedArgs) << "\n";
   }
-  
+
   // Figure out output kind ( -dylib, -r, -bundle, -preload, or -static )
   if ( llvm::opt::Arg *kind = parsedArgs->getLastArg(OPT_dylib, OPT_relocatable,
                                       OPT_bundle, OPT_static, OPT_preload)) {
     switch (kind->getOption().getID()) {
     case OPT_dylib:
-      info.setOutputFileType(mach_o::MH_DYLIB);
-      info.setGlobalsAreDeadStripRoots(true);
+      ctx.setOutputFileType(mach_o::MH_DYLIB);
+      ctx.setGlobalsAreDeadStripRoots(true);
       break;
     case OPT_relocatable:
-      info.setPrintRemainingUndefines(false);
-      info.setAllowRemainingUndefines(true);
-      info.setOutputFileType(mach_o::MH_OBJECT);
+      ctx.setPrintRemainingUndefines(false);
+      ctx.setAllowRemainingUndefines(true);
+      ctx.setOutputFileType(mach_o::MH_OBJECT);
       break;
     case OPT_bundle:
-      info.setOutputFileType(mach_o::MH_BUNDLE);
+      ctx.setOutputFileType(mach_o::MH_BUNDLE);
       break;
     case OPT_static:
-      info.setOutputFileType(mach_o::MH_EXECUTE);
+      ctx.setOutputFileType(mach_o::MH_EXECUTE);
       break;
     case OPT_preload:
-       info.setOutputFileType(mach_o::MH_PRELOAD);
+      ctx.setOutputFileType(mach_o::MH_PRELOAD);
       break;
     }
   }
-  
+
   // Handle -e xxx
   if (llvm::opt::Arg *entry = parsedArgs->getLastArg(OPT_entry))
-    info.setEntrySymbolName(entry->getValue());
+    ctx.setEntrySymbolName(entry->getValue());
 
   // Handle -o xxx
   if (llvm::opt::Arg *outpath = parsedArgs->getLastArg(OPT_output))
-    info.setOutputPath(outpath->getValue());
-    
+    ctx.setOutputPath(outpath->getValue());
+
   // Handle -dead_strip
   if (parsedArgs->getLastArg(OPT_dead_strip))
-    info.setDeadStripping(true);
-  
+    ctx.setDeadStripping(true);
+
   // Handle -all_load
   if (parsedArgs->getLastArg(OPT_all_load))
-    info.setForceLoadAllArchives(true);
-  
+    ctx.setForceLoadAllArchives(true);
+
   // Handle -arch xxx
   if (llvm::opt::Arg *archStr = parsedArgs->getLastArg(OPT_arch)) {
-    info.setArch(MachOLinkingContext::archFromName(archStr->getValue()));
-    if (info.arch() == MachOLinkingContext::arch_unknown) {
+    ctx.setArch(MachOLinkingContext::archFromName(archStr->getValue()));
+    if (ctx.arch() == MachOLinkingContext::arch_unknown) {
       diagnostics << "error: unknown arch named '" << archStr->getValue()
                   << "'\n";
       return true;
@@ -163,20 +167,20 @@ bool DarwinLdDriver::parse(int argc, con
                                                OPT_ios_simulator_version_min)) {
     switch (minOS->getOption().getID()) {
     case OPT_macosx_version_min:
-      if (info.setOS(MachOLinkingContext::OS::macOSX, minOS->getValue())) {
+      if (ctx.setOS(MachOLinkingContext::OS::macOSX, minOS->getValue())) {
         diagnostics << "error: malformed macosx_version_min value\n";
         return true;
       }
       break;
     case OPT_ios_version_min:
-      if (info.setOS(MachOLinkingContext::OS::iOS, minOS->getValue())) {
+      if (ctx.setOS(MachOLinkingContext::OS::iOS, minOS->getValue())) {
         diagnostics << "error: malformed ios_version_min value\n";
         return true;
       }
       break;
     case OPT_ios_simulator_version_min:
-      if (info.setOS(MachOLinkingContext::OS::iOS_simulator,
-                     minOS->getValue())) {
+      if (ctx.setOS(MachOLinkingContext::OS::iOS_simulator,
+                    minOS->getValue())) {
         diagnostics << "error: malformed ios_simulator_version_min value\n";
         return true;
       }
@@ -185,34 +189,32 @@ bool DarwinLdDriver::parse(int argc, con
   }
   else {
     // No min-os version on command line, check environment variables
-  
   }
-  
+
+  std::unique_ptr<InputGraph> inputGraph(new InputGraph());
+
   // Handle input files
   for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_INPUT),
                                ie = parsedArgs->filtered_end();
                               it != ie; ++it) {
-    info.appendInputFile((*it)->getValue());
+    inputGraph->addInputElement(std::unique_ptr<InputElement>(
+        new MachOFileNode(ctx, (*it)->getValue())));
   }
-  
-  // Handle -help
-  if (parsedArgs->getLastArg(OPT_help)) {
-    table.PrintHelp(llvm::outs(), argv[0], "LLVM Darwin Linker", false);
-    // If only -help on command line, don't try to do any linking
-    if ( argc == 2 ) {
-      info.setDoNothing(true);
-      return false;
-    }
+
+  if (!inputGraph->numFiles()) {
+    diagnostics << "No input files\n";
+    return true;
   }
 
+  ctx.setInputGraph(std::move(inputGraph));
+
   // Validate the combination of options used.
-  if (info.validate(diagnostics))
+  if (ctx.validate(diagnostics))
     return true;
 
   return false;
 }
 
-
 } // namespace lld
 
 

Modified: lld/trunk/lib/Driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Driver.cpp?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/lib/Driver/Driver.cpp (original)
+++ lld/trunk/lib/Driver/Driver.cpp Wed Aug 21 17:57:10 2013
@@ -40,21 +40,31 @@ bool Driver::link(const LinkingContext &
     args[numArgs + 1] = 0;
     llvm::cl::ParseCommandLineOptions(numArgs + 1, args);
   }
+  InputGraph &inputGraph = context.inputGraph();
+  if (!inputGraph.numFiles())
+    return true;
 
   // Read inputs
   ScopedTask readTask(getDefaultDomain(), "Read Args");
-  std::vector<std::vector<std::unique_ptr<File>> > files(
-      context.inputFiles().size());
+  std::vector<std::vector<std::unique_ptr<File> > > files(
+      inputGraph.numFiles());
   size_t index = 0;
   std::atomic<bool> fail(false);
   TaskGroup tg;
-  for (const auto &input : context.inputFiles()) {
+  std::vector<std::unique_ptr<LinkerInput> > linkerInputs;
+  for (auto &ie : inputGraph) {
+    if (ie->kind() == InputElement::Kind::File) {
+      FileNode *fileNode = (llvm::dyn_cast<FileNode>)(ie.get());
+      linkerInputs.push_back(std::move(fileNode->createLinkerInput(context)));
+    }
+  }
+  for (const auto &input : linkerInputs) {
     if (context.logInputFiles())
-      llvm::outs() << input.getPath() << "\n";
+      llvm::outs() << input->getPath() << "\n";
 
     tg.spawn([ &, index]{
-      if (error_code ec = context.readFile(input.getPath(), files[index])) {
-        diagnostics << "Failed to read file: " << input.getPath() << ": "
+      if (error_code ec = context.readFile(input->getPath(), files[index])) {
+        diagnostics << "Failed to read file: " << input->getPath() << ": "
                     << ec.message() << "\n";
         fail = true;
         return;

Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdDriver.cpp Wed Aug 21 17:57:10 2013
@@ -14,7 +14,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lld/Driver/Driver.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
+#include "lld/Driver/GnuLDInputGraph.h"
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
@@ -71,10 +71,20 @@ public:
 
 } // namespace
 
+std::unique_ptr<lld::LinkerInput>
+ELFFileNode::createLinkerInput(const LinkingContext &ctx) {
+  std::unique_ptr<LinkerInput> inputFile(new LinkerInput(path(ctx)));
+  inputFile->setAsNeeded(_asNeeded);
+  inputFile->setForceLoad(_isWholeArchive);
+  return std::move(inputFile);
+}
 
+StringRef ELFFileNode::path(const LinkingContext &) const {
+  return _elfLinkingContext.searchLibrary(_path, _libraryPaths);
+}
 
 bool GnuLdDriver::linkELF(int argc, const char *argv[],
-                                                  raw_ostream &diagnostics) {
+                          raw_ostream &diagnostics) {
   std::unique_ptr<ELFLinkingContext> options;
   bool error = parse(argc, argv, options, diagnostics);
   if (error)
@@ -93,6 +103,7 @@ bool GnuLdDriver::parse(int argc, const
   GnuLdOptTable table;
   unsigned missingIndex;
   unsigned missingCount;
+
   parsedArgs.reset(
       table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount));
   if (missingCount) {
@@ -102,13 +113,6 @@ bool GnuLdDriver::parse(int argc, const
     return true;
   }
 
-  for (auto it = parsedArgs->filtered_begin(OPT_UNKNOWN),
-            ie = parsedArgs->filtered_end(); it != ie; ++it) {
-    diagnostics << "warning: ignoring unknown argument: " << (*it)->getAsString(
-                                                                 *parsedArgs)
-                << "\n";
-  }
-
   // Handle --help
   if (parsedArgs->getLastArg(OPT_help)) {
     table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
@@ -121,154 +125,181 @@ bool GnuLdDriver::parse(int argc, const
     triple = llvm::Triple(trip->getValue());
   else
     triple = getDefaultTarget(argv[0]);
-  std::unique_ptr<ELFLinkingContext> options(ELFLinkingContext::create(triple));
+  std::unique_ptr<ELFLinkingContext> ctx(ELFLinkingContext::create(triple));
 
-  if (!options) {
+  if (!ctx) {
     diagnostics << "unknown target triple\n";
     return true;
   }
 
-  // Handle -e xxx
-  if (llvm::opt::Arg *entry = parsedArgs->getLastArg(OPT_entry))
-    options->setEntrySymbolName(entry->getValue());
-
-  // Handle -emit-yaml
-  if (parsedArgs->getLastArg(OPT_emit_yaml))
-    options->setOutputYAML(true);
-
-  // Handle -o xxx
-  if (llvm::opt::Arg *output = parsedArgs->getLastArg(OPT_output))
-    options->setOutputPath(output->getValue());
-  else if (options->outputYAML())
-    options->setOutputPath("-"); // yaml writes to stdout by default
-  else
-    options->setOutputPath("a.out");
+  std::unique_ptr<InputGraph> inputGraph(new InputGraph());
+  std::stack<InputElement *> controlNodeStack;
 
-  // Handle -r, -shared, or -static
-  if (llvm::opt::Arg *kind =
-          parsedArgs->getLastArg(OPT_relocatable, OPT_shared, OPT_static)) {
-    switch (kind->getOption().getID()) {
+  // Positional options for an Input File
+  std::vector<StringRef> searchPath;
+  bool isWholeArchive = false;
+  bool asNeeded = false;
+  bool _outputOptionSet = false;
+
+  // Create a dynamic executable by default
+  ctx->setOutputFileType(llvm::ELF::ET_EXEC);
+  ctx->setIsStaticExecutable(false);
+  ctx->setAllowShlibUndefines(false);
+  ctx->setUseShlibUndefines(true);
+
+  // Set the output file to be a.out
+  ctx->setOutputPath("a.out");
+
+  // Process all the arguments and create Input Elements
+  for (auto inputArg : *parsedArgs) {
+    switch (inputArg->getOption().getID()) {
+    case OPT_mllvm:
+      ctx->appendLLVMOption(inputArg->getValue());
+      break;
     case OPT_relocatable:
-      options->setOutputFileType(llvm::ELF::ET_REL);
-      options->setPrintRemainingUndefines(false);
-      options->setAllowRemainingUndefines(true);
+      ctx->setOutputFileType(llvm::ELF::ET_REL);
+      ctx->setPrintRemainingUndefines(false);
+      ctx->setAllowRemainingUndefines(true);
+      break;
+    case OPT_static:
+      ctx->setOutputFileType(llvm::ELF::ET_EXEC);
+      ctx->setIsStaticExecutable(true);
       break;
     case OPT_shared:
-      options->setOutputFileType(llvm::ELF::ET_DYN);
-      options->setAllowShlibUndefines(true);
-      options->setUseShlibUndefines(false);
+      ctx->setOutputFileType(llvm::ELF::ET_DYN);
+      ctx->setAllowShlibUndefines(true);
+      ctx->setUseShlibUndefines(false);
       break;
-    case OPT_static:
-      options->setOutputFileType(llvm::ELF::ET_EXEC);
-      options->setIsStaticExecutable(true);
+    case OPT_entry:
+      ctx->setEntrySymbolName(inputArg->getValue());
       break;
-    }
-  } else {
-    options->setOutputFileType(llvm::ELF::ET_EXEC);
-    options->setIsStaticExecutable(false);
-    options->setAllowShlibUndefines(false);
-    options->setUseShlibUndefines(true);
-  }
 
-  // Handle --noinhibit-exec
-  if (parsedArgs->getLastArg(OPT_noinhibit_exec))
-    options->setAllowRemainingUndefines(true);
-
-  // Handle --force-load
-  if (parsedArgs->getLastArg(OPT_force_load))
-    options->setForceLoadAllArchives(true);
-
-  // Handle --merge-strings
-  if (parsedArgs->getLastArg(OPT_merge_strings))
-    options->setMergeCommonStrings(true);
-
-  // Handle -t
-  if (parsedArgs->getLastArg(OPT_t))
-    options->setLogInputFiles(true);
-
-  // Handle --no-allow-shlib-undefined
-  if (parsedArgs->getLastArg(OPT_no_allow_shlib_undefs))
-    options->setAllowShlibUndefines(false);
-
-  // Handle --allow-shlib-undefined
-  if (parsedArgs->getLastArg(OPT_allow_shlib_undefs))
-    options->setAllowShlibUndefines(true);
-
-  // Handle --use-shlib-undefs
-  if (parsedArgs->getLastArg(OPT_use_shlib_undefs))
-    options->setUseShlibUndefines(true);
-
-  // Handle --dynamic-linker
-  if (llvm::opt::Arg *dynamicLinker =
-          parsedArgs->getLastArg(OPT_dynamic_linker))
-    options->setInterpreter(dynamicLinker->getValue());
-
-  // Handle NMAGIC
-  if (parsedArgs->getLastArg(OPT_nmagic))
-    options->setOutputMagic(ELFLinkingContext::OutputMagic::NMAGIC);
-
-  // Handle OMAGIC
-  if (parsedArgs->getLastArg(OPT_omagic))
-    options->setOutputMagic(ELFLinkingContext::OutputMagic::OMAGIC);
-
-  // Handle --no-omagic
-  if (parsedArgs->getLastArg(OPT_no_omagic)) {
-    options->setOutputMagic(ELFLinkingContext::OutputMagic::DEFAULT);
-    options->setNoAllowDynamicLibraries();
-  }
+    case OPT_output:
+      _outputOptionSet = true;
+      ctx->setOutputPath(inputArg->getValue());
+      break;
 
-  // If either of the options NMAGIC/OMAGIC have been set, make the executable
-  // static
-  if (!options->allowLinkWithDynamicLibraries())
-    options->setIsStaticExecutable(true);
-
-  // Handle -u, --undefined option
-  for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_u),
-                               ie = parsedArgs->filtered_end();
-       it != ie; ++it) {
-    options->addInitialUndefinedSymbol((*it)->getValue());
-  }
+    case OPT_noinhibit_exec:
+      ctx->setAllowRemainingUndefines(true);
+      break;
 
-  // Handle -Lxxx
-  for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_L),
-                               ie = parsedArgs->filtered_end();
-       it != ie; ++it) {
-    options->appendSearchPath((*it)->getValue());
-  }
+    case OPT_merge_strings:
+      ctx->setMergeCommonStrings(true);
+      break;
 
-  // Copy mllvm
-  for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_mllvm),
-                               ie = parsedArgs->filtered_end();
-       it != ie; ++it) {
-    options->appendLLVMOption((*it)->getValue());
-  }
+    case OPT_all_load:
+      ctx->setForceLoadAllArchives(true);
+      break;
 
-  // Handle input files (full paths and -lxxx)
-  for (llvm::opt::arg_iterator
-           it = parsedArgs->filtered_begin(OPT_INPUT, OPT_l),
-           ie = parsedArgs->filtered_end();
-       it != ie; ++it) {
-    switch ((*it)->getOption().getID()) {
-    case OPT_INPUT:
-      options->appendInputFile((*it)->getValue());
+    case OPT_t:
+      ctx->setLogInputFiles(true);
       break;
-    case OPT_l:
-      if (options->appendLibrary((*it)->getValue())) {
-        diagnostics << "Failed to find library for " << (*it)->getValue()
-                    << "\n";
-        return true;
-      }
+
+    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_dynamic_linker:
+      ctx->setInterpreter(inputArg->getValue());
       break;
+
+    case OPT_nmagic:
+      ctx->setOutputMagic(ELFLinkingContext::OutputMagic::NMAGIC);
+      ctx->setIsStaticExecutable(true);
+      break;
+
+    case OPT_omagic:
+      ctx->setOutputMagic(ELFLinkingContext::OutputMagic::OMAGIC);
+      ctx->setIsStaticExecutable(true);
+      break;
+
+    case OPT_no_omagic:
+      ctx->setOutputMagic(ELFLinkingContext::OutputMagic::DEFAULT);
+      ctx->setNoAllowDynamicLibraries();
+      break;
+
+    case OPT_u:
+      ctx->addInitialUndefinedSymbol(inputArg->getValue());
+      break;
+
+    case OPT_emit_yaml:
+      if (!_outputOptionSet)
+        ctx->setOutputPath("-");
+      ctx->setOutputYAML(true);
+      break;
+
+    case OPT_no_whole_archive:
+      isWholeArchive = false;
+      break;
+    case OPT_whole_archive:
+      isWholeArchive = true;
+      break;
+    case OPT_as_needed:
+      asNeeded = true;
+      break;
+    case OPT_no_as_needed:
+      asNeeded = false;
+      break;
+    case OPT_L:
+      searchPath.push_back(inputArg->getValue());
+      break;
+
+    case OPT_start_group: {
+      std::unique_ptr<InputElement> controlStart(new ELFGroup(*ctx));
+      controlNodeStack.push(controlStart.get());
+      (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
+          ->processControlEnter();
+      inputGraph->addInputElement(std::move(controlStart));
+    } break;
+
+    case OPT_end_group:
+      (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
+          ->processControlExit();
+      controlNodeStack.pop();
+      return false;
+
+    case OPT_INPUT:
+    case OPT_l: {
+      std::unique_ptr<InputElement> inputFile =
+          std::move(std::unique_ptr<InputElement>(
+              new ELFFileNode(*ctx, inputArg->getValue(), isWholeArchive,
+                              asNeeded, searchPath)));
+      if (controlNodeStack.empty())
+        inputGraph->addInputElement(std::move(inputFile));
+      else
+        (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
+            ->processInputElement(std::move(inputFile));
+    } break;
+
     default:
-      llvm_unreachable("input option type not handled");
-    }
+      break;
+    } // end switch on option ID
+  }   // end for
+
+  if (!inputGraph->numFiles()) {
+    diagnostics << "No input files\n";
+    return true;
   }
 
+  if (ctx->outputYAML())
+    inputGraph->dump(diagnostics);
+
   // Validate the combination of options used.
-  if (options->validate(diagnostics))
+  if (ctx->validate(diagnostics))
     return true;
 
-  context.swap(options);
+  ctx->setInputGraph(std::move(inputGraph));
+
+  context.swap(ctx);
+
   return false;
 }
 

Added: lld/trunk/lib/Driver/InputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/InputGraph.cpp?rev=188958&view=auto
==============================================================================
--- lld/trunk/lib/Driver/InputGraph.cpp (added)
+++ lld/trunk/lib/Driver/InputGraph.cpp Wed Aug 21 17:57:10 2013
@@ -0,0 +1,56 @@
+//===- lib/Driver/InputGraph.cpp ------------------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "lld/Driver/InputGraph.h"
+
+using namespace lld;
+
+namespace {
+bool sortInputElements(const std::unique_ptr<InputElement> &a,
+                       const std::unique_ptr<InputElement> &b) {
+  return a->getOrdinal() < b->getOrdinal();
+}
+}
+
+bool InputGraph::addInputElement(std::unique_ptr<InputElement> ie) {
+  switch (ie->kind()) {
+  case InputElement::Kind::Control:
+    ++_numElements;
+    break;
+  case InputElement::Kind::File:
+    ++_numElements;
+    ++_numFiles;
+    break;
+  }
+  _inputArgs.push_back(std::move(ie));
+  return true;
+}
+
+bool InputGraph::assignOrdinals() {
+  for (auto &ie : _inputArgs)
+    ie->setOrdinal(++_ordinal);
+  return true;
+}
+
+void InputGraph::doPostProcess() {
+  std::stable_sort(_inputArgs.begin(), _inputArgs.end(), sortInputElements);
+}
+
+bool InputGraph::validate() {
+  for (auto &ie : _inputArgs)
+    if (!ie->validate())
+      return false;
+  return true;
+}
+
+bool InputGraph::dump(raw_ostream &diagnostics) {
+  for (auto &ie : _inputArgs)
+    if (!ie->dump(diagnostics))
+      return false;
+  return true;
+}

Modified: lld/trunk/lib/Driver/LDOptions.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/LDOptions.td?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/lib/Driver/LDOptions.td (original)
+++ lld/trunk/lib/Driver/LDOptions.td Wed Aug 21 17:57:10 2013
@@ -80,8 +80,18 @@ def undefined : Separate<["--"], "undefi
 def u_equal : Joined<["-"], "u=">, Alias<u>;
 def undefined_equal : Joined<["--"], "undefined=">, Alias<u>;
 
+def as_needed : Flag<["--"], "as-needed">,
+    HelpText<"This option affects ELF DT_NEEDED tags for dynamic libraries mentioned on the command line">;
+def no_as_needed : Flag<["--"], "no-as-needed">,
+    HelpText<"This option restores the default behavior of adding DT_NEEDED entries">;
+
 // extensions
 def emit_yaml : Flag<["-"], "emit-yaml">, 
     HelpText<"Write YAML instead of ELF">;
-def force_load : Flag<["--"], "force-load">,
-    HelpText<"Force load of all members in all static libraries">;
+def whole_archive: Flag<["--"], "whole-archive">,
+    HelpText<"Force load of all members in a static library">;
+def no_whole_archive: Flag<["--"], "no-whole-archive">,
+    HelpText<"Restores the default behavior of loading archive members">;
+
+def all_load : Flag<["-"], "all_load">,
+        HelpText<"Forces all members of all static libraries to be loaded">;

Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
+++ lld/trunk/lib/Driver/WinLinkDriver.cpp Wed Aug 21 17:57:10 2013
@@ -17,15 +17,16 @@
 #include <sstream>
 #include <map>
 
+#include "lld/Driver/Driver.h"
+#include "lld/Driver/WinLinkInputGraph.h"
+#include "lld/ReaderWriter/PECOFFLinkingContext.h"
+
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/Path.h"
 
-#include "lld/Driver/Driver.h"
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-
 namespace lld {
 
 namespace {
@@ -62,135 +63,6 @@ public:
   WinLinkOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){}
 };
 
-// Displays error message if the given version does not match with
-// /^\d+$/.
-bool checkNumber(StringRef version, const char *errorMessage,
-                 raw_ostream &diagnostics) {
-  if (version.str().find_first_not_of("0123456789") != std::string::npos
-      || version.empty()) {
-    diagnostics << "error: " << errorMessage << version << "\n";
-    return false;
-  }
-  return true;
-}
-
-// Parse an argument for /base, /stack or /heap. The expected string
-// is "<integer>[,<integer>]".
-bool parseMemoryOption(const StringRef &arg, raw_ostream &diagnostics,
-                       uint64_t &reserve, uint64_t &commit) {
-  StringRef reserveStr, commitStr;
-  llvm::tie(reserveStr, commitStr) = arg.split(',');
-  if (!checkNumber(reserveStr, "invalid size: ", diagnostics))
-    return false;
-  reserve = atoi(reserveStr.str().c_str());
-  if (!commitStr.empty()) {
-    if (!checkNumber(commitStr, "invalid size: ", diagnostics))
-      return false;
-    commit = atoi(commitStr.str().c_str());
-  }
-  return true;
-}
-
-// Parse /base command line option. The argument for the parameter is in the
-// form of "<address>[:<size>]".
-bool parseBaseOption(PECOFFLinkingContext &context, const StringRef &arg,
-                     raw_ostream &diagnostics) {
-  // Size should be set to SizeOfImage field in the COFF header, and if it's
-  // smaller than the actual size, the linker should warn about that. Currently
-  // we just ignore the value of size parameter.
-  uint64_t addr, size;
-  if (!parseMemoryOption(arg, diagnostics, addr, size))
-    return false;
-  // It's an error if the base address is not multiple of 64K.
-  if (addr & 0xffff) {
-    diagnostics << "Base address have to be multiple of 64K, but got "
-                << addr << "\n";
-    return false;
-  }
-  context.setBaseAddress(addr);
-  return true;
-}
-
-// Parse /stack command line option
-bool parseStackOption(PECOFFLinkingContext &context, const StringRef &arg,
-                      raw_ostream &diagnostics) {
-  uint64_t reserve;
-  uint64_t commit = context.getStackCommit();
-  if (!parseMemoryOption(arg, diagnostics, reserve, commit))
-    return false;
-  context.setStackReserve(reserve);
-  context.setStackCommit(commit);
-  return true;
-}
-
-// Parse /heap command line option.
-bool parseHeapOption(PECOFFLinkingContext &context, const StringRef &arg,
-                     raw_ostream &diagnostics) {
-  uint64_t reserve;
-  uint64_t commit = context.getHeapCommit();
-  if (!parseMemoryOption(arg, diagnostics, reserve, commit))
-    return false;
-  context.setHeapReserve(reserve);
-  context.setHeapCommit(commit);
-  return true;
-}
-
-// Returns subsystem type for the given string.
-llvm::COFF::WindowsSubsystem stringToWinSubsystem(StringRef str) {
-  std::string arg(str.lower());
-  return llvm::StringSwitch<llvm::COFF::WindowsSubsystem>(arg)
-      .Case("windows", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI)
-      .Case("console", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI)
-      .Default(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN);
-}
-
-bool parseMinOSVersion(PECOFFLinkingContext &context,
-                       const StringRef &osVersion, raw_ostream &diagnostics) {
-  StringRef majorVersion, minorVersion;
-  llvm::tie(majorVersion, minorVersion) = osVersion.split('.');
-  if (minorVersion.empty())
-    minorVersion = "0";
-  if (!checkNumber(majorVersion, "invalid OS major version: ", diagnostics))
-    return false;
-  if (!checkNumber(minorVersion, "invalid OS minor version: ", diagnostics))
-    return false;
-  PECOFFLinkingContext::OSVersion minOSVersion(
-      atoi(majorVersion.str().c_str()), atoi(minorVersion.str().c_str()));
-  context.setMinOSVersion(minOSVersion);
-  return true;
-}
-
-// Parse /subsystem command line option. The form of /subsystem is
-// "subsystem_name[,majorOSVersion[.minorOSVersion]]".
-bool parseSubsystemOption(PECOFFLinkingContext &context, std::string arg,
-                          raw_ostream &diagnostics) {
-  StringRef subsystemStr, osVersionStr;
-  llvm::tie(subsystemStr, osVersionStr) = StringRef(arg).split(',');
-
-  // Parse optional OS version if exists.
-  if (!osVersionStr.empty())
-    if (!parseMinOSVersion(context, osVersionStr, diagnostics))
-      return false;
-
-  // Parse subsystem name.
-  llvm::COFF::WindowsSubsystem subsystem = stringToWinSubsystem(subsystemStr);
-  if (subsystem == llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN) {
-    diagnostics << "error: unknown subsystem name: " << subsystemStr << "\n";
-    return false;
-  }
-  context.setSubsystem(subsystem);
-  return true;
-}
-
-// Replace a file extension with ".exe". If the given file has no
-// extension, just add ".exe".
-StringRef getDefaultOutputFileName(PECOFFLinkingContext &context,
-                                   StringRef path) {
-  SmallString<128> smallStr = path;
-  llvm::sys::path::replace_extension(smallStr, ".exe");
-  return context.allocateString(smallStr.str());
-}
-
 // Split the given string with spaces.
 std::vector<std::string> splitArgList(std::string str) {
   std::stringstream stream(str);
@@ -210,6 +82,26 @@ std::vector<StringRef> splitPathList(Str
   return std::move(ret);
 }
 
+// Parse an argument for /base, /stack or /heap. The expected string
+// is "<integer>[,<integer>]".
+bool parseMemoryOption(StringRef arg, uint64_t &reserve, uint64_t &commit) {
+  StringRef reserveStr, commitStr;
+  llvm::tie(reserveStr, commitStr) = arg.split(',');
+  if (reserveStr.getAsInteger(0, reserve))
+    return true;
+  if (!commitStr.empty() && (commitStr.getAsInteger(0, commit)))
+    return true;
+  return false;
+}
+
+// Returns subsystem type for the given string.
+llvm::COFF::WindowsSubsystem stringToWinSubsystem(StringRef str) {
+  return llvm::StringSwitch<llvm::COFF::WindowsSubsystem>(str.lower())
+      .Case("windows", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI)
+      .Case("console", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI)
+      .Default(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN);
+}
+
 // Handle /failifmatch option.
 bool handleFailIfMismatchOption(StringRef option,
                                 std::map<StringRef, StringRef> &mustMatch,
@@ -218,26 +110,16 @@ bool handleFailIfMismatchOption(StringRe
   llvm::tie(key, value) = option.split('=');
   if (key.empty() || value.empty()) {
     diagnostics << "error: malformed /failifmatch option: " << option << "\n";
-    return false;
+    return true;
   }
   auto it = mustMatch.find(key);
   if (it != mustMatch.end() && it->second != value) {
     diagnostics << "error: mismatch detected: '" << it->second << "' and '"
                 << value << "' for key '" << key << "'\n";
-    return false;
+    return true;
   }
   mustMatch[key] = value;
-  return true;
-}
-
-// Add ".lib" extension if the path does not already have the extension to mimic
-// link.exe behavior.
-StringRef canonicalizeImportLibraryPath(PECOFFLinkingContext &context,
-                                        StringRef path) {
-  std::string s(path.lower());
-  if (StringRef(s).endswith(".lib"))
-    return path;
-  return context.allocateString(std::string(path).append(".lib"));
+  return false;
 }
 
 // Process "LINK" environment variable. If defined, the value of the variable
@@ -299,6 +181,29 @@ std::unique_ptr<llvm::opt::InputArgList>
 
 } // namespace
 
+std::unique_ptr<lld::LinkerInput>
+PECOFFFileNode::createLinkerInput(const LinkingContext &ctx) {
+  return std::unique_ptr<LinkerInput>(new LinkerInput(path(ctx)));
+}
+
+std::unique_ptr<lld::LinkerInput>
+PECOFFLibraryNode::createLinkerInput(const LinkingContext &ctx) {
+  return std::unique_ptr<LinkerInput>(new LinkerInput(path(ctx)));
+}
+
+StringRef PECOFFFileNode::path(const LinkingContext &) const {
+  if (_path.endswith(".lib"))
+    return _ctx.searchLibraryFile(_path);
+  if (llvm::sys::path::extension(_path).empty())
+    return (_path.str() + ".obj");
+  return _path;
+}
+
+StringRef PECOFFLibraryNode::path(const LinkingContext &) const {
+  if (!_path.endswith(".lib"))
+    return _ctx.searchLibraryFile(_path.str() + ".lib");
+  return _ctx.searchLibraryFile(_path);
+}
 
 bool WinLinkDriver::linkPECOFF(int argc, const char *argv[],
                                raw_ostream &diagnostics) {
@@ -311,14 +216,19 @@ bool WinLinkDriver::linkPECOFF(int argc,
 }
 
 bool WinLinkDriver::parse(int argc, const char *argv[],
-                          PECOFFLinkingContext &context,
-                          raw_ostream &diagnostics) {
+                          PECOFFLinkingContext &ctx, raw_ostream &diagnostics) {
+  std::map<StringRef, StringRef> failIfMismatchMap;
   // Parse the options.
   std::unique_ptr<llvm::opt::InputArgList> parsedArgs = parseArgs(
       argc, argv, diagnostics);
   if (!parsedArgs)
     return true;
 
+  if (!ctx.hasInputGraph())
+    ctx.setInputGraph(std::unique_ptr<InputGraph>(new InputGraph()));
+
+  InputGraph &inputGraph = ctx.inputGraph();
+
   // handle /help
   if (parsedArgs->getLastArg(OPT_help)) {
     WinLinkOptTable table;
@@ -326,75 +236,6 @@ bool WinLinkDriver::parse(int argc, cons
     return true;
   }
 
-  // Copy -mllvm
-  for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_mllvm),
-                               ie = parsedArgs->filtered_end();
-       it != ie; ++it) {
-    context.appendLLVMOption((*it)->getValue());
-  }
-
-  // handle /base
-  if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_base))
-    if (!parseBaseOption(context, arg->getValue(), diagnostics))
-      return true;
-
-  // handle /stack
-  if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_stack))
-    if (!parseStackOption(context, arg->getValue(), diagnostics))
-      return true;
-
-  // handle /heap
-  if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_heap))
-    if (!parseHeapOption(context, arg->getValue(), diagnostics))
-      return true;
-
-  // handle /subsystem
-  if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_subsystem))
-    if (!parseSubsystemOption(context, arg->getValue(), diagnostics))
-      return true;
-
-  // handle /entry
-  if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_entry))
-    context.setEntrySymbolName(arg->getValue());
-
-  // handle /libpath
-  for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_libpath),
-                               ie = parsedArgs->filtered_end();
-       it != ie; ++it) {
-    context.appendInputSearchPath((*it)->getValue());
-  }
-
-  // handle /force
-  if (parsedArgs->getLastArg(OPT_force))
-    context.setAllowRemainingUndefines(true);
-
-  // handle /nxcompat:no
-  if (parsedArgs->getLastArg(OPT_no_nxcompat))
-    context.setNxCompat(false);
-
-  // handle /largeaddressaware
-  if (parsedArgs->getLastArg(OPT_largeaddressaware))
-    context.setLargeAddressAware(true);
-
-  // handle /fixed
-  if (parsedArgs->getLastArg(OPT_fixed))
-    context.setBaseRelocationEnabled(false);
-
-  // handle /tsaware:no
-  if (parsedArgs->getLastArg(OPT_no_tsaware))
-    context.setTerminalServerAware(false);
-
-  // handle /include
-  for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_incl),
-                               ie = parsedArgs->filtered_end();
-       it != ie; ++it) {
-    context.addInitialUndefinedSymbol((*it)->getValue());
-  }
-
-  // handle /out
-  if (llvm::opt::Arg *outpath = parsedArgs->getLastArg(OPT_out))
-    context.setOutputPath(outpath->getValue());
-
   // handle /defaultlib
   std::vector<StringRef> defaultLibs;
   for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_defaultlib),
@@ -403,29 +244,143 @@ bool WinLinkDriver::parse(int argc, cons
     defaultLibs.push_back((*it)->getValue());
   }
 
-  // Handle /failifmismatch. /failifmismatch is the hidden linker option behind
-  // the scenes of "detect_mismatch" pragma. If the compiler finds "#pragma
-  // detect_mismatch(name, value)", it outputs "/failifmismatch:name=value" to
-  // the .drectve section of the resultant object file. The linker raises an
-  // error if conflicting /failmismatch options are given. Conflicting options
-  // are the options with the same key but with different values.
-  //
-  // This feature is used to prevent inconsistent object files from linking.
-  std::map<StringRef, StringRef> mustMatch;
-  for (llvm::opt::arg_iterator
-           it = parsedArgs->filtered_begin(OPT_failifmismatch),
-           ie = parsedArgs->filtered_end();
-       it != ie; ++it) {
-    if (!handleFailIfMismatchOption((*it)->getValue(), mustMatch, diagnostics))
-      return true;
-  }
-
-  // Add input files
-  std::vector<StringRef> inputPaths;
-  for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_INPUT),
-                               ie = parsedArgs->filtered_end();
-       it != ie; ++it) {
-    inputPaths.push_back((*it)->getValue());
+  // Process all the arguments and create Input Elements
+  for (auto inputArg : *parsedArgs) {
+    switch (inputArg->getOption().getID()) {
+    case OPT_mllvm:
+      ctx.appendLLVMOption(inputArg->getValue());
+      break;
+
+    case OPT_base:
+      // Parse /base command line option. The argument for the parameter is in
+      // the
+      // form of "<address>[:<size>]".
+      uint64_t addr, size;
+      // Size should be set to SizeOfImage field in the COFF header, and if
+      // it's smaller than the actual size, the linker should warn about that.
+      // Currently we just ignore the value of size parameter.
+      if (parseMemoryOption(inputArg->getValue(), addr, size))
+        return true;
+      // It's an error if the base address is not multiple of 64K.
+      // TODO: move this to validation of LinkingContext
+      if (addr & 0xffff) {
+        diagnostics << "Base address have to be multiple of 64K, but got "
+                    << addr << "\n";
+        return true;
+      }
+      ctx.setBaseAddress(addr);
+      break;
+    case OPT_stack: {
+      // Parse /stack command line option
+      uint64_t reserve;
+      uint64_t commit = ctx.getStackCommit();
+      if (parseMemoryOption(inputArg->getValue(), reserve, commit))
+        return true;
+      ctx.setStackReserve(reserve);
+      ctx.setStackCommit(commit);
+    } break;
+    case OPT_heap: {
+      // Parse /heap command line option
+      uint64_t reserve;
+      uint64_t commit = ctx.getHeapCommit();
+      if (parseMemoryOption(inputArg->getValue(), reserve, commit))
+        return true;
+      ctx.setHeapReserve(reserve);
+      ctx.setHeapCommit(commit);
+    } break;
+    case OPT_subsystem: {
+      // Parse /subsystem command line option. The form of /subsystem is
+      // "subsystem_name[,majorOSVersion[.minorOSVersion]]".
+      StringRef subsystemStr, osVersion;
+      llvm::tie(subsystemStr, osVersion) =
+          StringRef(inputArg->getValue()).split(',');
+      if (!osVersion.empty()) {
+        StringRef majorVersion, minorVersion;
+        llvm::tie(majorVersion, minorVersion) = osVersion.split('.');
+        if (minorVersion.empty())
+          minorVersion = "0";
+        int32_t major, minor;
+        if (majorVersion.getAsInteger(0, major))
+          return true;
+        if (minorVersion.getAsInteger(0, minor))
+          return true;
+        ctx.setMinOSVersion(PECOFFLinkingContext::OSVersion(major, minor));
+      }
+      // Parse subsystem name.
+      llvm::COFF::WindowsSubsystem subsystem =
+          stringToWinSubsystem(subsystemStr);
+      if (subsystem == llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN) {
+        diagnostics << "error: unknown subsystem name: " << subsystemStr
+                    << "\n";
+        return true;
+      }
+      ctx.setSubsystem(subsystem);
+    } break;
+
+    case OPT_failifmismatch:
+      if (handleFailIfMismatchOption(inputArg->getValue(), failIfMismatchMap,
+                                     diagnostics))
+        return true;
+      break;
+
+    case OPT_entry:
+      // handle /entry
+      ctx.setEntrySymbolName(inputArg->getValue());
+      break;
+
+    case OPT_libpath:
+      // handle /libpath
+      ctx.appendInputSearchPath(inputArg->getValue());
+      break;
+
+    case OPT_force:
+      // handle /force
+      ctx.setAllowRemainingUndefines(true);
+      break;
+
+    case OPT_no_nxcompat:
+      // handle /nxcompat:no
+      ctx.setNxCompat(false);
+      break;
+
+    case OPT_largeaddressaware:
+      // handle /largeaddressaware
+      ctx.setLargeAddressAware(true);
+      break;
+
+    case OPT_fixed:
+      // handle /fixed
+      ctx.setBaseRelocationEnabled(false);
+      break;
+
+    case OPT_tsaware:
+      // handle /tsaware
+      ctx.setTerminalServerAware(true);
+      break;
+
+    case OPT_no_tsaware:
+      // handle /tsaware:no
+      ctx.setTerminalServerAware(false);
+      break;
+
+    case OPT_incl:
+      // handle /incl
+      ctx.addInitialUndefinedSymbol(inputArg->getValue());
+      break;
+
+    case OPT_out:
+      // handle /out
+      ctx.setOutputPath(inputArg->getValue());
+      break;
+
+    case OPT_INPUT: {
+      inputGraph.addInputElement(std::unique_ptr<InputElement>(
+          new PECOFFFileNode(ctx, inputArg->getValue())));
+    } break;
+
+    default:
+      break;
+    }
   }
 
   // Arguments after "--" are interpreted as filenames even if they
@@ -433,27 +388,33 @@ bool WinLinkDriver::parse(int argc, cons
   // but useful for us to test lld on Unix.
   if (llvm::opt::Arg *dashdash = parsedArgs->getLastArg(OPT_DASH_DASH)) {
     for (const StringRef value : dashdash->getValues())
-      inputPaths.push_back(value);
+      inputGraph.addInputElement(
+          std::unique_ptr<InputElement>(new PECOFFFileNode(ctx, value)));
   }
 
-  // Add input files specified via the command line.
-  for (const StringRef path : inputPaths)
-    context.appendInputFileOrLibrary(path);
-
-  // Add the library files specified by /defaultlib option. The files
-  // specified by the option should have lower precedence than the other files
-  // added above, which is important for link.exe compatibility.
-  for (const StringRef path : defaultLibs)
-    context.appendLibraryFile(canonicalizeImportLibraryPath(context, path));
+  // Add ".lib" extension if the path does not already have the extension to
+  // mimic link.exe behavior.
+  for (auto defaultLibPath : defaultLibs)
+    inputGraph.addInputElement(std::unique_ptr<InputElement>(
+        new PECOFFLibraryNode(ctx, defaultLibPath)));
+
+  if (!inputGraph.numFiles()) {
+    diagnostics << "No input files\n";
+    return true;
+  }
 
   // If /out option was not specified, the default output file name is
   // constructed by replacing an extension of the first input file
   // with ".exe".
-  if (context.outputPath().empty() && !inputPaths.empty())
-    context.setOutputPath(getDefaultOutputFileName(context, inputPaths[0]));
+  if (ctx.outputPath().empty()) {
+    SmallString<128> firstInputFilePath =
+        (llvm::dyn_cast<FileNode>(&((inputGraph)[0])))->path(ctx);
+    (llvm::sys::path::replace_extension(firstInputFilePath, ".exe"));
+    ctx.setOutputPath(firstInputFilePath.str());
+  }
 
   // Validate the combination of options used.
-  return context.validate(diagnostics);
+  return ctx.validate(diagnostics);
 }
 
 } // namespace lld

Modified: lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp Wed Aug 21 17:57:10 2013
@@ -64,11 +64,6 @@ bool ELFLinkingContext::validateImpl(raw
     _entrySymbolName = "_start";
   }
 
-  if (_inputFiles.empty()) {
-    diagnostics << "No input files\n";
-    return true;
-  }
-
   _elfReader = createReaderELF(*this);
   _linkerScriptReader.reset(new ReaderLinkerScript(*this));
   _writer = _outputYAML ? createWriterYAML(*this) : createWriterELF(*this);
@@ -131,10 +126,11 @@ ELFLinkingContext::create(llvm::Triple t
   }
 }
 
-bool ELFLinkingContext::appendLibrary(StringRef libName) {
+StringRef ELFLinkingContext::searchLibrary(
+    StringRef libName, const std::vector<StringRef> &searchPath) const {
   bool foundFile = false;
   StringRef pathref;
-  for (StringRef dir : _inputSearchPaths) {
+  for (StringRef dir : searchPath) {
     // Search for dynamic library
     if (!_isStaticExecutable) {
       SmallString<128> dynlibPath;
@@ -155,15 +151,10 @@ bool ELFLinkingContext::appendLibrary(St
         foundFile = true;
       }
     }
-    if (foundFile) {
-      unsigned pathlen = pathref.size();
-      char *x = _extraStrings.Allocate<char>(pathlen);
-      memcpy(x, pathref.data(), pathlen);
-      appendInputFile(StringRef(x, pathlen));
-      return false;
-    }
+    if (foundFile)
+      return (*(new (_alloc) std::string(pathref.str())));
   }
-  return true;
+  return libName;
 }
 
 } // end namespace lld

Removed: lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp?rev=188957&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp (removed)
@@ -1,627 +0,0 @@
-//===- lib/ReaderWriter/MachO/MachOFormat.hpp -----------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-//
-// This file contains all the structs and constants needed to write a 
-// mach-o final linked image.  The names of the structs and constants
-// are the same as in the darwin native header <mach-o/loader.h> so
-// they will be familiar to anyone who has used that header.
-//
-
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Memory.h"
-
-#ifndef LLD_READER_WRITER_MACHO_FORMAT_H_
-#define LLD_READER_WRITER_MACHO_FORMAT_H_
-
-namespace lld {
-namespace mach_o {
-
-
-enum { 
-  MH_MAGIC    = 0xfeedface,
-  MH_MAGIC_64 = 0xfeedfacf 
-};
-
-enum {
-  CPU_TYPE_ARM  =   0x0000000C,
-  CPU_TYPE_I386 =   0x00000007,
-  CPU_TYPE_X86_64 = 0x01000007
-};
-
-enum {
-  CPU_SUBTYPE_X86_ALL    = 0x00000003,
-  CPU_SUBTYPE_X86_64_ALL = 0x00000003,
-  CPU_SUBTYPE_ARM_V6     = 0x00000006,
-  CPU_SUBTYPE_ARM_V7     = 0x00000009,
-  CPU_SUBTYPE_ARM_V7S    = 0x0000000B
-};
-
-enum {
-  MH_OBJECT     = 0x1,
-  MH_EXECUTE    = 0x2,
-  MH_PRELOAD    = 0x5,
-  MH_DYLIB      = 0x6,
-  MH_DYLINKER   = 0x7,
-  MH_BUNDLE     = 0x8,
-  MH_DYLIB_STUB = 0x9,
-  MH_KEXT_BUNDLE= 0xB
-};
-
-
-//
-// Every mach-o file starts with this header.  The header size is
-// 28 bytes for 32-bit architecures and 32-bytes for 64-bit architectures.
-//
-class mach_header {
-public:
-  uint32_t    magic;  
-  uint32_t    cputype;
-  uint32_t    cpusubtype;  
-  uint32_t    filetype;  
-  uint32_t    ncmds;    
-  uint32_t    sizeofcmds;  
-  uint32_t    flags;  
-  uint32_t    reserved;  
- 
-  uint64_t size() {
-    return (magic == 0xfeedfacf) ? 32 : 28;
-  }
-  
-  void copyTo(uint8_t *to, bool swap=false) {
-    ::memcpy(to, (char*)&magic, this->size());
-  }
- 
-  void recordLoadCommand(const class load_command *lc);    
-};
-
-
-//
-// Every mach-o file has a list of load commands after the mach_header.
-// Each load command starts with a type and length, so you can iterate
-// through the load commands even if you don't understand the content
-// of a particular type.
-//
-// The model for handling endianness and 32 vs 64 bitness is that the in-memory
-// object is always 64-bit and the native endianess.  The endianess swapping
-// and pointer sizing is done when writing (copyTo method) or when reading
-// (constructor that takes a buffer).
-//
-// The load_command subclasses are designed so to mirror the traditional "C"
-// structs, so you can get and set the same field names (e.g. seg->vmaddr = 0).
-//
-class load_command {
-public:
-  const uint32_t  cmd;        // type of load command
-  const uint32_t  cmdsize;    // length of load command including this header
-  
-  load_command(uint32_t cmdNumber, uint32_t sz, bool is64, bool align=false)
-    : cmd(cmdNumber), cmdsize(pointerAlign(sz, is64, align)) {
-  }
-  
-  virtual ~load_command() {
-  }
-  
-  virtual void copyTo(uint8_t *to, bool swap=false) = 0;
-private:
-  // Load commands must be pointer-size aligned. Most load commands are
-  // a fixed size, so there is a runtime assert to check those.  For variable
-  // length load commands, setting the align option to true will add padding
-  // at the end of the load command to round up its size for proper alignment.
-  uint32_t pointerAlign(uint32_t size, bool is64, bool align) {
-    if ( align ) {
-       if ( is64 )
-        return (size + 7) & (-8);
-      else
-        return (size + 3) & (-4);
-    }
-    else {
-      if ( is64 )
-        assert((size % 8) == 0);
-      else
-        assert((size % 4) == 0);
-      return size;
-    }
-  }
-
-};
-
-inline void mach_header::recordLoadCommand(const load_command *lc) {
-  ++ncmds;
-  sizeofcmds += lc->cmdsize;
-}
-
-// Supported load command types
-enum {
-  LC_SEGMENT        = 0x00000001,
-  LC_SYMTAB         = 0x00000002,
-  LC_UNIXTHREAD     = 0x00000005,
-  LC_LOAD_DYLIB     = 0x0000000C,
-  LC_LOAD_DYLINKER  = 0x0000000E,
-  LC_SEGMENT_64     = 0x00000019,
-  LC_MAIN           = 0x80000028,
-  LC_DYLD_INFO_ONLY = 0x80000022
-};
-
-// Memory protection bit used in segment_command.initprot
-enum {
-  VM_PROT_NONE    = 0x0,
-  VM_PROT_READ    = 0x1,
-  VM_PROT_WRITE   = 0x2,
-  VM_PROT_EXECUTE = 0x4,
-};
-
-// Bits for the section.flags field
-enum {
-  // Section "type" is the low byte
-  SECTION_TYPE              = 0x000000FF,
-  S_REGULAR                 = 0x00000000,
-  S_ZEROFILL                = 0x00000001,
-  S_CSTRING_LITERALS        = 0x00000002,
-  S_NON_LAZY_SYMBOL_POINTERS= 0x00000006,
-  S_LAZY_SYMBOL_POINTERS    = 0x00000007,
-  S_SYMBOL_STUBS            = 0x00000008,
-  
-  // Other bits in section.flags
-  S_ATTR_PURE_INSTRUCTIONS  = 0x80000000,
-  S_ATTR_SOME_INSTRUCTIONS  = 0x00000400
-};
-
-
-// section record for 32-bit architectures
-struct section {
-  char      sectname[16];  
-  char      segname[16];  
-  uint32_t  addr;  
-  uint32_t  size;    
-  uint32_t  offset;  
-  uint32_t  align;    
-  uint32_t  reloff;  
-  uint32_t  nreloc;    
-  uint32_t  flags;    
-  uint32_t  reserved1;
-  uint32_t  reserved2;  
-};
-
-// section record for 64-bit architectures
-struct section_64 {
-  char      sectname[16];  
-  char      segname[16];  
-  uint64_t  addr;  
-  uint64_t  size;    
-  uint32_t  offset;  
-  uint32_t  align;    
-  uint32_t  reloff;  
-  uint32_t  nreloc;    
-  uint32_t  flags;    
-  uint32_t  reserved1;
-  uint32_t  reserved2;  
-  uint32_t  reserved3;
-};
-
-
-//
-// A segment load command has a fixed set of fields followed by an 'nsect'
-// array of section records.  The in-memory object uses a pointer to
-// a dynamically allocated array of sections.  
-//
-class segment_command : public load_command {
-public:
-  char      segname[16];  
-  uint64_t  vmaddr;    
-  uint64_t  vmsize;    
-  uint64_t  fileoff;  
-  uint64_t  filesize;  
-  uint32_t  maxprot;  
-  uint32_t  initprot;  
-  uint32_t  nsects;    
-  uint32_t  flags;  
-  section_64 *sections;
-  
-  segment_command(unsigned sectCount, bool is64)
-    : load_command((is64 ? LC_SEGMENT_64 : LC_SEGMENT), 
-                   (is64 ? (72 + sectCount*80) : (56 + sectCount*68)),
-                   is64),
-     vmaddr(0), vmsize(0), fileoff(0), filesize(0), 
-      maxprot(0), initprot(0), nsects(sectCount), flags(0) {
-    sections = new section_64[sectCount];
-    this->nsects = sectCount;
-  }
-  
-  ~segment_command() {
-    delete sections;
-  }
-  
-  void copyTo(uint8_t *to, bool swap) {
-    if ( swap ) {
-      assert(0 && "non-native endianness not supported yet");
-    }
-    else {
-      if( is64() ) {
-        // in-memory matches on-disk, so copy segment fields followed by sections
-        ::memcpy(to, (uint8_t*)&cmd, 72);
-        if ( nsects != 0 )
-          ::memcpy(&to[72], sections, sizeof(section_64)*nsects);
-      }
-      else {
-        // on-disk is 32-bit struct, so copy each field
-        ::memcpy(to, (uint8_t*)&cmd, 24);
-        copy32(to, 24, vmaddr);
-        copy32(to, 28, vmsize);
-        copy32(to, 32, fileoff);
-        copy32(to, 36, filesize);
-        copy32(to, 40, maxprot);
-        copy32(to, 44, initprot);
-        copy32(to, 48, nsects);
-        copy32(to, 52, flags);
-        for(uint32_t i=0; i < nsects; ++i) {
-          unsigned off = 56+i*68;
-          ::memcpy(&to[off], sections[i].sectname, 32);
-          copy32(to, off+32, sections[i].addr);
-          copy32(to, off+36, sections[i].size);
-          copy32(to, off+40, sections[i].offset);
-          copy32(to, off+44, sections[i].align);
-          copy32(to, off+48, sections[i].reloff);
-          copy32(to, off+52, sections[i].nreloc);
-          copy32(to, off+56, sections[i].flags);
-          copy32(to, off+60, sections[i].reserved1);
-          copy32(to, off+64, sections[i].reserved2);
-        }
-      }
-    }
-  }
-
-private:
-  void copy32(uint8_t *to, unsigned offset, uint64_t value) {
-    uint32_t value32 = value; // FIXME: range check
-    ::memcpy(&to[offset], &value32, sizeof(uint32_t));
-  }
-
-  bool is64() { 
-    return (cmd == LC_SEGMENT_64); 
-  }
-};
-
-
-
-//
-// The dylinker_command contains the path to the dynamic loader to use
-// with the program (e.g. "/usr/lib/dyld"). So, it is variable length.
-// But load commands must be pointer size aligned.
-//
-//
-class dylinker_command : public load_command {
-public:
-  uint32_t  name_offset;
-private:
-  StringRef _name;
-public:
-  dylinker_command(StringRef path, bool is64) 
-    : load_command(LC_LOAD_DYLINKER,12 + path.size(), is64, true), 
-       name_offset(12), _name(path) {
-  }
-
-  virtual void copyTo(uint8_t *to, bool swap=false) {
-    if ( swap ) {
-      assert(0 && "non-native endianness not supported yet");
-    }
-    else {
-      // in-memory matches on-disk, so copy first fields followed by path
-      ::memcpy(to, (uint8_t*)&cmd, 12);
-      ::memcpy(&to[12], _name.data(), _name.size());
-      ::memset(&to[12+_name.size()], 0, cmdsize-(12+_name.size()));
-    }
-  }
-
-};
-
-
-
-//
-// The symtab_command just holds the offset to the array of nlist structs
-// and the offsets to the string pool for all symbol names.
-//
-class symtab_command : public load_command {
-public:
-  uint32_t  symoff;  
-  uint32_t  nsyms;  
-  uint32_t  stroff;  
-  uint32_t  strsize;  
-
-  symtab_command(bool is64) 
-    : load_command(LC_SYMTAB, 24, is64), 
-      symoff(0), nsyms(0), stroff(0), strsize(0) {
-  }
-  
-  virtual void copyTo(uint8_t *to, bool swap=false) {
-    if ( swap ) {
-      assert(0 && "non-native endianness not supported yet");
-    }
-    else {
-      // in-memory matches on-disk, so copy fields 
-      ::memcpy(to, (uint8_t*)&cmd, 24);
-    }
-  }
-  
-};
-
-
-//
-// The entry_point_command load command holds the offset to the function
-// _main in a dynamic executable.  
-//
-class entry_point_command : public load_command {
-public:
-  uint64_t  entryoff;  
-  uint64_t  stacksize; 
-
-  entry_point_command(bool is64) 
-    : load_command(LC_MAIN, 24, is64), entryoff(0), stacksize(0) {
-  }
-  
-  virtual void copyTo(uint8_t *to, bool swap=false) {
-    if ( swap ) {
-      assert(0 && "non-native endianness not supported yet");
-    }
-    else {
-      // in-memory matches on-disk, so copy fields 
-      ::memcpy(to, (uint8_t*)&cmd, 24);
-    }
-  }
-};
-
-
-//
-// The thread_command load command holds the set of initial register values
-// for a dynamic executable.  In reality, only the PC and SP are used.
-//
-class thread_command : public load_command {
-public:
-	uint32_t	fields_flavor;
-	uint32_t	fields_count;
-private:
-  uint32_t   _cpuType;
-  uint8_t   *_registerArray;
-
-public:
-  thread_command(uint32_t cpuType, bool is64) 
-    : load_command(LC_UNIXTHREAD, 16+registersBufferSize(cpuType), is64),
-      fields_count(registersBufferSize(cpuType)/4), _cpuType(cpuType) {
-    switch ( cpuType ) {
-      case CPU_TYPE_I386:
-        fields_flavor = 1;  // i386_THREAD_STATE
-        break;
-      case CPU_TYPE_X86_64:
-        fields_flavor = 4;  // x86_THREAD_STATE64;
-        break;
-      case CPU_TYPE_ARM:
-        fields_flavor = 1;  // ARM_THREAD_STATE
-        break;
-      default:
-        assert(0 && "unsupported cpu type");
-    }
-    _registerArray = reinterpret_cast<uint8_t*>(
-                                    ::calloc(registersBufferSize(cpuType), 1));
-    assert(_registerArray);
-  }
-  
-  virtual void copyTo(uint8_t *to, bool swap=false) {
-    if ( swap ) {
-      assert(0 && "non-native endianness not supported yet");
-    }
-    else {
-      // in-memory matches on-disk, so copy fixed fields 
-      ::memcpy(to, (uint8_t*)&cmd, 16);
-      // that register array
-      ::memcpy(&to[16], _registerArray, registersBufferSize(_cpuType));
-    }
-  }
-  
-  void setPC(uint64_t pc) {
-    uint32_t *regs32 = reinterpret_cast<uint32_t*>(_registerArray);
-    uint64_t *regs64 = reinterpret_cast<uint64_t*>(_registerArray);
-    switch ( _cpuType ) {
-      case CPU_TYPE_I386:
-        regs32[10] = pc;
-        break;
-      case CPU_TYPE_X86_64:
-        regs64[16] = pc;
-        break;
-      case CPU_TYPE_ARM:
-        regs32[15] = pc;
-        break;
-      default:
-        assert(0 && "unsupported cpu type");
-    }
-  }
-  
-  virtual ~thread_command() {
-    ::free(_registerArray); 
-  }
-
-private:
-  uint32_t registersBufferSize(uint32_t cpuType) {
-    switch ( cpuType ) {
-      case CPU_TYPE_I386:
-        return 64;        // i386_THREAD_STATE_COUNT * 4
-      case CPU_TYPE_X86_64:
-        return 168;       // x86_THREAD_STATE64_COUNT * 4
-      case CPU_TYPE_ARM:
-        return 68;        // ARM_THREAD_STATE_COUNT * 4
-    }
-    assert(0 && "unsupported cpu type");
-    return 0;
-  }
-    
-    
-  
-};
-
-
-
-
-
-//
-// The dylib_command load command holds the name/path of a dynamic shared
-// library which this mach-o image depends on.
-//
-struct dylib_command : public load_command {
-  uint32_t  name_offset;
-  uint32_t  timestamp;
-  uint32_t  current_version;    
-  uint32_t  compatibility_version;
-private:  
-  StringRef _loadPath;
-public:
-  
-  dylib_command(StringRef path, bool is64) 
-    : load_command(LC_LOAD_DYLIB, 24 + path.size(), is64, true), 
-      name_offset(24), timestamp(0), 
-      current_version(0x10000), compatibility_version(0x10000),
-      _loadPath(path) {
-  }
-  
-  virtual void copyTo(uint8_t *to, bool swap=false) {
-    if ( swap ) {
-      assert(0 && "non-native endianness not supported yet");
-    }
-    else {
-      // in-memory matches on-disk, so copy first fields followed by path
-      ::memcpy(to, (uint8_t*)&cmd, 24);
-      ::memcpy(&to[24], _loadPath.data(), _loadPath.size());
-      ::memset(&to[24+_loadPath.size()], 0, cmdsize-(24+_loadPath.size()));
-    }
-  }
-
-};
-
-
-//
-// The dyld_info_command load command holds the offsets to various tables
-// of information needed by dyld to prepare the image for execution.
-//
-struct dyld_info_command : public load_command {
-  uint32_t   rebase_off;  
-  uint32_t   rebase_size;  
-  uint32_t   bind_off;  
-  uint32_t   bind_size;  
-  uint32_t   weak_bind_off;  
-  uint32_t   weak_bind_size; 
-  uint32_t   lazy_bind_off;
-  uint32_t   lazy_bind_size; 
-  uint32_t   export_off;  
-  uint32_t   export_size;  
-
-  dyld_info_command(bool is64) 
-    : load_command(LC_DYLD_INFO_ONLY, 48, is64), 
-        rebase_off(0), rebase_size(0),
-        bind_off(0), bind_size(0), weak_bind_off(0), weak_bind_size(0), 
-        lazy_bind_off(0), lazy_bind_size(0), export_off(0), export_size(0) {
-   }
-  
-  virtual void copyTo(uint8_t *to, bool swap=false) {
-    if ( swap ) {
-      assert(0 && "non-native endianness not supported yet");
-    }
-    else {
-      // in-memory matches on-disk, so copy fields 
-      ::memcpy(to, (uint8_t*)&cmd, 48);
-    }
-  }
-};
-
-
-enum {
-  BIND_TYPE_POINTER               = 1,
-  BIND_TYPE_TEXT_ABSOLUTE32        = 2,
-  BIND_TYPE_TEXT_PCREL32          = 3
-};
-
-enum {
-  BIND_SPECIAL_DYLIB_SELF             = 0,
-  BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE  = -1,
-  BIND_SPECIAL_DYLIB_FLAT_LOOKUP      =  -2
-};
-
-enum {
-  BIND_SYMBOL_FLAGS_WEAK_IMPORT           = 0x1,
-  BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION    =  0x8
-};
-
-enum {
-  BIND_OPCODE_MASK                              = 0xF0,
-  BIND_IMMEDIATE_MASK                           = 0x0F,
-  BIND_OPCODE_DONE                              = 0x00,
-  BIND_OPCODE_SET_DYLIB_ORDINAL_IMM             = 0x10,
-  BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB            = 0x20,
-  BIND_OPCODE_SET_DYLIB_SPECIAL_IMM             = 0x30,
-  BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM     = 0x40,
-  BIND_OPCODE_SET_TYPE_IMM                      = 0x50,
-  BIND_OPCODE_SET_ADDEND_SLEB                   = 0x60,
-  BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB       = 0x70,
-  BIND_OPCODE_ADD_ADDR_ULEB                     = 0x80,
-  BIND_OPCODE_DO_BIND                           = 0x90,
-  BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB             = 0xA0,
-  BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED       = 0xB0,
-  BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB  = 0xC0
-};
-
-
-
-
-enum {
-  N_UNDF = 0x00,
-  N_EXT  = 0x01,
-  N_PEXT = 0x10,
-  N_SECT = 0x0e
-};
-
-class nlist {
-public:
-  uint32_t  n_strx; 
-  uint8_t   n_type; 
-  uint8_t   n_sect;   
-  uint16_t  n_desc;   
-  uint64_t  n_value;    
-  
-  static unsigned size(bool is64) {
-    return (is64 ? 16 : 12);
-  }
-  
-  void copyTo(uint8_t *to, bool is64, bool swap=false) {
-    if ( swap ) {
-      assert(0 && "non-native endianness not supported yet");
-    }
-    else {
-      if ( is64 ) {
-        // in-memory matches on-disk, so just copy whole struct 
-        ::memcpy(to, (uint8_t*)&n_strx, 16);
-      }
-      else {
-        // on-disk uses 32-bit n_value, so special case n_value
-        ::memcpy(to, (uint8_t*)&n_strx, 8);
-        uint32_t value32 = n_value; // FIXME: range check
-        ::memcpy(&to[8], &value32, sizeof(uint32_t));
-      }
-    }
-  }
-};
-
-
-
-
-
-} // namespace mach_o
-} // namespace lld
-
-
-
-#endif // LLD_READER_WRITER_MACHO_FORMAT_H_
-

Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Wed Aug 21 17:57:10 2013
@@ -8,10 +8,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "lld/ReaderWriter/MachOLinkingContext.h"
+#include "lld/ReaderWriter/MachOFormat.hpp"
 #include "GOTPass.hpp"
 #include "StubsPass.hpp"
 #include "ReferenceKinds.h"
-#include "MachOFormat.hpp"
 
 #include "lld/Core/PassManager.h"
 #include "lld/ReaderWriter/Reader.h"
@@ -205,11 +205,6 @@ bool MachOLinkingContext::addUnixThreadL
 }
 
 bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
-  if (_inputFiles.empty()) {
-    diagnostics << "no object files specified\n";
-    return true;
-  }
-
   if ((_outputFileType == mach_o::MH_EXECUTE) && _entrySymbolName.empty()) {
     if (_outputFileTypeStatic) {
       _entrySymbolName = "start";

Modified: lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp Wed Aug 21 17:57:10 2013
@@ -31,12 +31,12 @@
 #include "lld/Core/Reference.h"
 #include "lld/Core/SharedLibraryAtom.h"
 #include "lld/ReaderWriter/MachOLinkingContext.h"
+#include "lld/ReaderWriter/MachOFormat.hpp"
 
 #include <vector>
 #include <map>
 #include <string.h>
 
-#include "MachOFormat.hpp"
 #include "ReferenceKinds.h"
 #include "ExecutableAtoms.hpp"
 
@@ -568,8 +568,9 @@ void SectionChunk::write(uint8_t *chunkB
       if ( ref->target() != nullptr )
         targetAddress = _writer.addressOfAtom(ref->target());
       uint64_t fixupAddress = _writer.addressOfAtom(atomInfo.atom) + offset;
-      _writer.kindHandler().applyFixup(ref->kind(), ref->addend(), 
-                            &atomContent[offset], fixupAddress, targetAddress);
+      _writer.kindHandler().applyFixup(ref->kind(), ref->addend(),
+                                       &atomContent[offset], fixupAddress,
+                                       targetAddress);
     }
   }
 }

Modified: lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp Wed Aug 21 17:57:10 2013
@@ -25,13 +25,7 @@
 
 namespace lld {
 
-namespace {
-bool containDirectoryName(StringRef path) {
-  SmallString<128> smallStr = StringRef(path);
-  llvm::sys::path::remove_filename(smallStr);
-  return !smallStr.str().empty();
-}
-} // anonymous namespace
+namespace {} // anonymous namespace
 
 error_code PECOFFLinkingContext::parseFile(
     std::unique_ptr<MemoryBuffer> &mb,
@@ -40,11 +34,6 @@ error_code PECOFFLinkingContext::parseFi
 }
 
 bool PECOFFLinkingContext::validateImpl(raw_ostream &diagnostics) {
-  if (_inputFiles.empty()) {
-    diagnostics << "No input files\n";
-    return true;
-  }
-
   if (_stackReserve < _stackCommit) {
     diagnostics << "Invalid stack size: reserve size must be equal to or "
                 << "greater than commit size, but got " << _stackCommit
@@ -73,45 +62,20 @@ void PECOFFLinkingContext::addImplicitFi
   files.appendFile(*linkerFile);
 }
 
-/// Append the given file to the input file list. The file must be an object
-/// file or an import library file.
-void PECOFFLinkingContext::appendInputFileOrLibrary(std::string path) {
-  StringRef ext = llvm::sys::path::extension(path);
-  // This is an import library file. Look for the library file in the search
-  // paths, unless the path contains a directory name.
-  if (ext.equals_lower(".lib")) {
-    if (containDirectoryName(path)) {
-      appendInputFile(path);
-      return;
-    }
-    appendLibraryFile(path);
-    return;
-  }
-  // This is an object file otherwise. Add ".obj" extension if the given path
-  // name has no file extension.
-  if (ext.empty())
-    path.append(".obj");
-  appendInputFile(allocateString(path));
-}
-
 /// Try to find the input library file from the search paths and append it to
 /// the input file list. Returns true if the library file is found.
-void PECOFFLinkingContext::appendLibraryFile(StringRef filename) {
+StringRef PECOFFLinkingContext::searchLibraryFile(StringRef filename) const {
   // Current directory always takes precedence over the search paths.
-  if (llvm::sys::fs::exists(filename)) {
-    appendInputFile(filename);
-    return;
-  }
+  if (llvm::sys::path::is_absolute(filename) || llvm::sys::fs::exists(filename))
+    return filename;
   // Iterate over the search paths.
   for (StringRef dir : _inputSearchPaths) {
     SmallString<128> path = dir;
     llvm::sys::path::append(path, filename);
-    if (llvm::sys::fs::exists(path.str())) {
-      appendInputFile(allocateString(path.str()));
-      return;
-    }
+    if (llvm::sys::fs::exists(path.str()))
+      return (*(new (_alloc) std::string(path.str())));
   }
-  appendInputFile(filename);
+  return filename;
 }
 
 Writer &PECOFFLinkingContext::writer() const { return *_writer; }

Modified: lld/trunk/lib/ReaderWriter/ReaderLinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ReaderLinkerScript.cpp?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ReaderLinkerScript.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ReaderLinkerScript.cpp Wed Aug 21 17:57:10 2013
@@ -87,7 +87,7 @@ error_code ReaderLinkerScript::parseFile
   const LinkerScript *ls = (*lsf)->getScript();
   result.push_back(std::move(*lsf));
   for (const auto &c : ls->_commands) {
-    if (auto group = dyn_cast<Group>(c))
+    if (auto group = dyn_cast<lld::script::Group>(c))
       for (const auto &path : group->getPaths()) {
         if (error_code ec = _context.readFile(path._path, result))
           return ec;

Added: lld/trunk/test/Driver/libsearch-inputGraph.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/Driver/libsearch-inputGraph.test?rev=188958&view=auto
==============================================================================
--- lld/trunk/test/Driver/libsearch-inputGraph.test (added)
+++ lld/trunk/test/Driver/libsearch-inputGraph.test Wed Aug 21 17:57:10 2013
@@ -0,0 +1,34 @@
+RUN: lld -flavor gnu -L%p/../elf/Inputs -lfnarchive -emit-yaml 2> %t.err
+RUN: FileCheck %s < %t.err
+RUN: lld -flavor gnu -L%p/../elf/Inputs --whole-archive -lfnarchive -emit-yaml 2> %t1.err
+RUN: FileCheck %s -check-prefix="WHOLEARCHIVE" < %t1.err
+RUN: lld -flavor gnu -L%p/../elf/Inputs --whole-archive --as-needed -lfnarchive -emit-yaml 2> %t2.err
+RUN: FileCheck %s -check-prefix="ASNEEDED" < %t2.err
+
+CHECK: Name    : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
+CHECK: Type    : ELF File
+CHECK: Ordinal : -1
+CHECK: Attributes :
+CHECK:   - wholeArchive : false
+CHECK:   - asNeeded : false
+CHECK:   contextPath :
+CHECK:     - {{[^ ]+}}elf/Inputs
+
+WHOLEARCHIVE: Name    : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
+WHOLEARCHIVE: Type    : ELF File
+WHOLEARCHIVE: Ordinal : -1
+WHOLEARCHIVE: Attributes :
+WHOLEARCHIVE:   - wholeArchive : true
+WHOLEARCHIVE:   - asNeeded : false
+WHOLEARCHIVE:   contextPath :
+WHOLEARCHIVE:     - {{[^ ]+}}elf/Inputs
+
+ASNEEDED: Name    : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
+ASNEEDED: Type    : ELF File
+ASNEEDED: Ordinal : -1
+ASNEEDED: Attributes :
+ASNEEDED:   - wholeArchive : true
+ASNEEDED:   - asNeeded : true
+ASNEEDED:   contextPath :
+ASNEEDED:     - {{[^ ]+}}elf/Inputs
+

Modified: lld/trunk/test/elf/X86_64/nmagic.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/nmagic.test?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/test/elf/X86_64/nmagic.test (original)
+++ lld/trunk/test/elf/X86_64/nmagic.test Wed Aug 21 17:57:10 2013
@@ -2,7 +2,7 @@
 # PT_LOAD, PT_TLS
 # The data segment should be aligned to a page boundary
 RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/nmagic.o  \
-RUN: --noinhibit-exec -o %t --nmagic
+RUN: --noinhibit-exec -o %t --nmagic -static
 RUN: llvm-readobj -sections %t | FileCheck -check-prefix=NMAGICSECTIONS %s
 RUN: llvm-readobj -program-headers %t | FileCheck -check-prefix=NMAGICPROGRAMHEADERS %s
 

Modified: lld/trunk/test/elf/X86_64/omagic.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/omagic.test?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/test/elf/X86_64/omagic.test (original)
+++ lld/trunk/test/elf/X86_64/omagic.test Wed Aug 21 17:57:10 2013
@@ -2,7 +2,7 @@
 # PT_LOAD, PT_TLS
 # The data segment should not be aligned to a page boundary
 RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/nmagic.o  \
-RUN: --noinhibit-exec -o %t --omagic
+RUN: --noinhibit-exec -o %t --omagic -static
 RUN: llvm-readobj -sections %t | FileCheck -check-prefix=OMAGICSECTIONS %s
 RUN: llvm-readobj -program-headers %t | FileCheck -check-prefix=OMAGICPROGRAMHEADERS %s
 

Modified: lld/trunk/test/elf/archive-elf-forceload.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/archive-elf-forceload.objtxt?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/test/elf/archive-elf-forceload.objtxt (original)
+++ lld/trunk/test/elf/archive-elf-forceload.objtxt Wed Aug 21 17:57:10 2013
@@ -24,7 +24,7 @@
 # gcc -c main.c fn.c fn1.c
 
 RUN: lld -flavor gnu -target x86_64-linux -e main %p/Inputs/mainobj.x86_64 \
-RUN:  %p/Inputs/libfnarchive.a --force-load -emit-yaml \
+RUN:  %p/Inputs/libfnarchive.a -all_load -emit-yaml \
 RUN:  | FileCheck -check-prefix FORCELOAD %s
 
 FORCELOAD:  defined-atoms:   

Modified: lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp Wed Aug 21 17:57:10 2013
@@ -15,7 +15,7 @@
 #include "DriverTest.h"
 
 #include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "../../lib/ReaderWriter/MachO/MachOFormat.hpp"
+#include "lld/ReaderWriter/MachOFormat.hpp"
 
 using namespace llvm;
 using namespace lld;

Modified: lld/trunk/unittests/DriverTests/DriverTest.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/DriverTest.h?rev=188958&r1=188957&r2=188958&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/DriverTest.h (original)
+++ lld/trunk/unittests/DriverTests/DriverTest.h Wed Aug 21 17:57:10 2013
@@ -30,11 +30,14 @@ protected:
   std::string &errorMessage() { return  _errorMessage; }
 
   // Convenience method for getting number of input files.
-  int inputFileCount() { return linkingContext()->inputFiles().size(); }
+  int inputFileCount() { return linkingContext()->inputGraph().numFiles(); }
 
   // Convenience method for getting i'th input files name.
   std::string inputFile(unsigned index) {
-    return linkingContext()->inputFiles()[index].getPath().str();
+    const InputElement &inputElement = linkingContext()->inputGraph()[index];
+    if (inputElement.kind() == InputElement::Kind::File)
+      return (llvm::dyn_cast<FileNode>(&inputElement))->path(*linkingContext());
+    assert(0 && "not handling other types of input files");
   }
 
   // For unit tests to call driver with various command lines.





More information about the llvm-commits mailing list