<div dir="ltr"><div>The change was one line.</div><div><br></div>  undefAdded = undefAdded || handleFile(*member);<br><div><br></div><div>was wrong because if undefAdded is true, handleFile() is not called. It should've been this.</div><div><br></div><div>  undefAdded = handleFile(*member) || undefAdded;</div><div><br></div><div>A test that could have caught was not added yet. I'm writing one.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Dec 12, 2014 at 2:28 PM, Shankar Easwaran <span dir="ltr"><<a href="mailto:shankare@codeaurora.org" target="_blank">shankare@codeaurora.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Curious to figure out where the error was in the code that caused undefined symbols ?<br>
<br>
Was there a test added to check the failure which was not caught by any of the tests ?<br>
<br>
Shankar Easwaran<div class="HOEnZb"><div class="h5"><br>
<br>
On 12/9/2014 6:33 PM, Rui Ueyama wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: ruiu<br>
Date: Tue Dec  9 18:33:00 2014<br>
New Revision: 223867<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=223867&view=rev" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project?rev=223867&view=rev</a><br>
Log:<br>
Re-commit r223330: Rewrite InputGraph's Group<br>
<br>
Modified:<br>
     lld/trunk/include/lld/Core/<u></u>InputGraph.h<br>
     lld/trunk/include/lld/Core/<u></u>LinkingContext.h<br>
     lld/trunk/include/lld/Core/<u></u>Resolver.h<br>
     lld/trunk/include/lld/Driver/<u></u>DarwinInputGraph.h<br>
     lld/trunk/include/lld/Driver/<u></u>WinLinkInputGraph.h<br>
     lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>MachOLinkingContext.h<br>
     lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>PECOFFLinkingContext.h<br>
     lld/trunk/lib/Core/InputGraph.<u></u>cpp<br>
     lld/trunk/lib/Core/Resolver.<u></u>cpp<br>
     lld/trunk/lib/Driver/<u></u>DarwinInputGraph.cpp<br>
     lld/trunk/lib/Driver/<u></u>DarwinLdDriver.cpp<br>
     lld/trunk/lib/Driver/Driver.<u></u>cpp<br>
     lld/trunk/lib/Driver/<u></u>GnuLdDriver.cpp<br>
     lld/trunk/lib/Driver/<u></u>GnuLdInputGraph.cpp<br>
     lld/trunk/lib/Driver/<u></u>WinLinkDriver.cpp<br>
     lld/trunk/lib/ReaderWriter/<u></u>MachO/MachOLinkingContext.cpp<br>
     lld/trunk/lib/ReaderWriter/<u></u>PECOFF/PECOFFLinkingContext.<u></u>cpp<br>
     lld/trunk/unittests/<u></u>DriverTests/DriverTest.h<br>
     lld/trunk/unittests/<u></u>DriverTests/InputGraphTest.cpp<br>
     lld/trunk/unittests/<u></u>DriverTests/WinLinkDriverTest.<u></u>cpp<br>
<br>
Modified: lld/trunk/include/lld/Core/<u></u>InputGraph.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputGraph.h?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>Core/InputGraph.h?rev=223867&<u></u>r1=223866&r2=223867&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/Core/<u></u>InputGraph.h (original)<br>
+++ lld/trunk/include/lld/Core/<u></u>InputGraph.h Tue Dec  9 18:33:00 2014<br>
@@ -59,12 +59,6 @@ public:<br>
    /// assigned in the way files are resolved.<br>
    virtual ErrorOr<File &> getNextFile();<br>
  -  /// Notifies the current input element of Resolver made some progress on<br>
-  /// resolving undefined symbols using the current file. Group (representing<br>
-  /// --start-group and --end-group) uses that notification to make a decision<br>
-  /// whether it should iterate over again or terminate or not.<br>
-  virtual void notifyProgress();<br>
-<br>
    /// Adds an observer of getNextFile(). Each time a new file is about to be<br>
    /// returned from getNextFile(), registered observers are called with the file<br>
    /// being returned.<br>
@@ -76,14 +70,18 @@ public:<br>
    /// \brief Adds a node at the beginning of the InputGraph<br>
    void addInputElementFront(std::<u></u>unique_ptr<InputElement>);<br>
  -  /// Normalize the InputGraph. It calls expand() on each node and then replace<br>
-  /// it with getReplacements() results.<br>
+  /// Normalize the InputGraph. It calls getReplacements() on each element.<br>
    void normalize();<br>
  -  range<InputElementIterT> inputElements() {<br>
-    return make_range(_inputArgs.begin(), _inputArgs.end());<br>
+  InputElementVectorT &inputElements() {<br>
+    return _inputArgs;<br>
    }<br>
  +  // Returns the current group size if we are at an --end-group.<br>
+  // Otherwise returns 0.<br>
+  int getGroupSize();<br>
+  void skipGroup();<br>
+<br>
    // \brief Returns the number of input files.<br>
    size_t size() const { return _inputArgs.size(); }<br>
  @@ -108,8 +106,8 @@ class InputElement {<br>
  public:<br>
    /// Each input element in the graph can be a File or a control<br>
    enum class Kind : uint8_t {<br>
-    Group,      // Represents a type associated with Group<br>
-    File        // Represents a type associated with File Nodes<br>
+    File,       // Represents a type associated with File Nodes<br>
+    GroupEnd,<br>
    };<br>
      InputElement(Kind type) : _kind(type) {}<br>
@@ -129,16 +127,9 @@ public:<br>
    /// Get the next file to be processed by the resolver<br>
    virtual ErrorOr<File &> getNextFile() = 0;<br>
  -  /// Refer InputGraph::notifyProgress(). By default, it does nothing. Only<br>
-  /// Group is interested in this message.<br>
-  virtual void notifyProgress() {};<br>
-<br>
    /// \brief Reset the next index<br>
    virtual void resetNextIndex() = 0;<br>
  -  /// Returns true if we want to replace this node with children.<br>
-  virtual void expand() {}<br>
-<br>
    /// Get the elements that we want to expand with.<br>
    virtual bool getReplacements(InputGraph::<u></u>InputElementVectorT &) {<br>
      return false;<br>
@@ -148,73 +139,31 @@ protected:<br>
    Kind _kind; // The type of the Element<br>
  };<br>
  -/// \brief A Control node which contains a group of InputElements<br>
-/// This affects the resolver so that it resolves undefined symbols<br>
-/// in the group completely before looking at other input files that<br>
-/// follow the group<br>
-class Group : public InputElement {<br>
+// This is a marker for --end-group. getSize() returns the number of<br>
+// files between the corresponding --start-group and this marker.<br>
+class GroupEnd : public InputElement {<br>
  public:<br>
-  Group()<br>
-      : InputElement(InputElement::<u></u>Kind::Group), _currentElementIndex(0),<br>
-        _nextElementIndex(0), _madeProgress(false) {}<br>
+  GroupEnd(int size) : InputElement(Kind::GroupEnd), _size(size) {}<br>
  -  static inline bool classof(const InputElement *a) {<br>
-    return a->kind() == InputElement::Kind::Group;<br>
-  }<br>
-<br>
-  /// \brief Process input element and add it to the group<br>
-  bool addFile(std::unique_ptr<<u></u>InputElement> element) {<br>
-    _elements.push_back(std::move(<u></u>element));<br>
-    return true;<br>
-  }<br>
+  int getSize() const { return _size; }<br>
  -  range<InputGraph::<u></u>InputElementIterT> elements() {<br>
-    return make_range(_elements.begin(), _elements.end());<br>
-  }<br>
-<br>
-  void resetNextIndex() override {<br>
-    _madeProgress = false;<br>
-    _currentElementIndex = 0;<br>
-    _nextElementIndex = 0;<br>
-    for (std::unique_ptr<InputElement> &elem : _elements)<br>
-      elem->resetNextIndex();<br>
+  static inline bool classof(const InputElement *a) {<br>
+    return a->kind() == Kind::GroupEnd;<br>
    }<br>
      /// \brief Parse the group members.<br>
    std::error_code parse(const LinkingContext &ctx, raw_ostream &diag) override {<br>
-    for (std::unique_ptr<InputElement> &ei : _elements)<br>
-      if (std::error_code ec = ei->parse(ctx, diag))<br>
-        return ec;<br>
      return std::error_code();<br>
    }<br>
  -  /// If Resolver made a progress using the current file, it's ok to revisit<br>
-  /// files in this group in future.<br>
-  void notifyProgress() override {<br>
-    for (std::unique_ptr<InputElement> &elem : _elements)<br>
-      elem->notifyProgress();<br>
-    _madeProgress = true;<br>
-  }<br>
-<br>
-  ErrorOr<File &> getNextFile() override;<br>
-<br>
-  void expand() override {<br>
-    for (std::unique_ptr<InputElement> &elt : _elements)<br>
-      elt->expand();<br>
-    std::vector<std::unique_ptr<<u></u>InputElement>> result;<br>
-    for (std::unique_ptr<InputElement> &elt : _elements) {<br>
-      if (elt->getReplacements(result))<br>
-        continue;<br>
-      result.push_back(std::move(<u></u>elt));<br>
-    }<br>
-    _elements.swap(result);<br>
+  ErrorOr<File &> getNextFile() override {<br>
+    llvm_unreachable("shouldn't be here.");<br>
    }<br>
  -protected:<br>
-  InputGraph::<u></u>InputElementVectorT _elements;<br>
-  uint32_t _currentElementIndex;<br>
-  uint32_t _nextElementIndex;<br>
-  bool _madeProgress;<br>
+  void resetNextIndex() override {}<br>
+<br>
+private:<br>
+  int _size;<br>
  };<br>
    /// \brief Represents an Input file in the graph<br>
@@ -252,6 +201,8 @@ public:<br>
      /// \brief add a file to the list of files<br>
    virtual void addFiles(InputGraph::<u></u>FileVectorT files) {<br>
+    assert(files.size() == 1);<br>
+    assert(_files.empty());<br>
      for (std::unique_ptr<File> &ai : files)<br>
        _files.push_back(std::move(ai)<u></u>);<br>
    }<br>
@@ -260,6 +211,8 @@ public:<br>
    /// the node again.<br>
    void resetNextIndex() override { _nextFileIndex = 0; }<br>
  +  bool getReplacements(InputGraph::<u></u>InputElementVectorT &result) override;<br>
+<br>
  protected:<br>
    /// \brief Read the file into _buffer.<br>
    std::error_code getBuffer(StringRef filePath);<br>
@@ -276,6 +229,10 @@ protected:<br>
  class SimpleFileNode : public FileNode {<br>
  public:<br>
    SimpleFileNode(StringRef path) : FileNode(path) {}<br>
+  SimpleFileNode(StringRef path, std::unique_ptr<File> f)<br>
+      : FileNode(path) {<br>
+    _files.push_back(std::move(f))<u></u>;<br>
+  }<br>
      virtual ~SimpleFileNode() {}<br>
  <br>
Modified: lld/trunk/include/lld/Core/<u></u>LinkingContext.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/LinkingContext.h?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>Core/LinkingContext.h?rev=<u></u>223867&r1=223866&r2=223867&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/Core/<u></u>LinkingContext.h (original)<br>
+++ lld/trunk/include/lld/Core/<u></u>LinkingContext.h Tue Dec  9 18:33:00 2014<br>
@@ -322,6 +322,10 @@ public:<br>
    bool runRoundTripPass() const { return _runRoundTripPasses; }<br>
  #endif<br>
  +  // This function is called just before the Resolver kicks in.<br>
+  // Derived classes may use that chance to rearrange the input files.<br>
+  virtual void maybeSortInputFiles() {}<br>
+<br>
    /// @}<br>
  protected:<br>
    LinkingContext(); // Must be subclassed<br>
<br>
Modified: lld/trunk/include/lld/Core/<u></u>Resolver.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>Core/Resolver.h?rev=223867&r1=<u></u>223866&r2=223867&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/Core/<u></u>Resolver.h (original)<br>
+++ lld/trunk/include/lld/Core/<u></u>Resolver.h Tue Dec  9 18:33:00 2014<br>
@@ -28,7 +28,8 @@ class LinkingContext;<br>
  class Resolver {<br>
  public:<br>
    Resolver(LinkingContext &context)<br>
-      : _context(context), _symbolTable(context), _result(new MergedFile()) {}<br>
+      : _context(context), _symbolTable(context), _result(new MergedFile()),<br>
+        _fileIndex(0) {}<br>
      // InputFiles::Handler methods<br>
    void doDefinedAtom(const DefinedAtom&);<br>
@@ -38,10 +39,10 @@ public:<br>
      // Handle files, this adds atoms from the current file thats<br>
    // being processed by the resolver<br>
-  void handleFile(const File &);<br>
+  bool handleFile(const File &);<br>
      // Handle an archive library file.<br>
-  void handleArchiveFile(const File &);<br>
+  bool handleArchiveFile(const File &);<br>
      // Handle a shared library file.<br>
    void handleSharedLibrary(const File &);<br>
@@ -54,6 +55,9 @@ public:<br>
  private:<br>
    typedef std::function<void(StringRef, bool)> UndefCallback;<br>
  +  bool undefinesAdded(int count);<br>
+  ErrorOr<File &> nextFile(bool &inGroup);<br>
+<br>
    /// \brief Add section group/.gnu.linkonce if it does not exist previously.<br>
    void maybeAddSectionGroupOrGnuLinkO<u></u>nce(const DefinedAtom &atom);<br>
  @@ -110,6 +114,11 @@ private:<br>
    llvm::DenseSet<const Atom *>  _deadAtoms;<br>
    std::unique_ptr<MergedFile>   _result;<br>
    llvm::DenseMap<const Atom *, llvm::DenseSet<const Atom *>> _reverseRef;<br>
+<br>
+  // --start-group and --end-group<br>
+  std::vector<File *> _files;<br>
+  std::map<File *, bool> _newUndefinesAdded;<br>
+  size_t _fileIndex;<br>
  };<br>
    } // namespace lld<br>
<br>
Modified: lld/trunk/include/lld/Driver/<u></u>DarwinInputGraph.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/DarwinInputGraph.h?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>Driver/DarwinInputGraph.h?rev=<u></u>223867&r1=223866&r2=223867&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/Driver/<u></u>DarwinInputGraph.h (original)<br>
+++ lld/trunk/include/lld/Driver/<u></u>DarwinInputGraph.h Tue Dec  9 18:33:00 2014<br>
@@ -23,18 +23,6 @@<br>
    namespace lld {<br>
  -<br>
-class DarwinInputGraph : public InputGraph {<br>
-public:<br>
-  DarwinInputGraph() : _librariesPhase(false), _repeatLibraries(false) { }<br>
-  ErrorOr<File &> getNextFile() override;<br>
-  void notifyProgress() override;<br>
-private:<br>
-  bool _librariesPhase;<br>
-  bool _repeatLibraries;<br>
-};<br>
-<br>
-<br>
  /// \brief Represents a MachO File<br>
  class MachOFileNode : public FileNode {<br>
  public:<br>
<br>
Modified: lld/trunk/include/lld/Driver/<u></u>WinLinkInputGraph.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/WinLinkInputGraph.h?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>Driver/WinLinkInputGraph.h?<u></u>rev=223867&r1=223866&r2=<u></u>223867&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/Driver/<u></u>WinLinkInputGraph.h (original)<br>
+++ lld/trunk/include/lld/Driver/<u></u>WinLinkInputGraph.h Tue Dec  9 18:33:00 2014<br>
@@ -55,21 +55,6 @@ public:<br>
    ErrorOr<StringRef> getPath(const LinkingContext &ctx) const override;<br>
  };<br>
  -/// \brief Represents a ELF control node<br>
-class PECOFFGroup : public Group {<br>
-public:<br>
-  PECOFFGroup(<u></u>PECOFFLinkingContext &ctx) : Group(), _ctx(ctx) {}<br>
-<br>
-  /// \brief Parse the group members.<br>
-  std::error_code parse(const LinkingContext &ctx, raw_ostream &diag) override {<br>
-    std::lock_guard<std::<u></u>recursive_mutex> lock(_ctx.getMutex());<br>
-    return Group::parse(ctx, diag);<br>
-  }<br>
-<br>
-private:<br>
-  PECOFFLinkingContext &_ctx;<br>
-};<br>
-<br>
  } // namespace lld<br>
    #endif<br>
<br>
Modified: lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>MachOLinkingContext.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>MachOLinkingContext.h?rev=<u></u>223867&r1=223866&r2=223867&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>MachOLinkingContext.h (original)<br>
+++ lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>MachOLinkingContext.h Tue Dec  9 18:33:00 2014<br>
@@ -283,6 +283,8 @@ public:<br>
    /// bits are xxxx.yy.zz.  Largest number is 65535.255.255<br>
    static bool parsePackedVersion(StringRef str, uint32_t &result);<br>
  +  void maybeSortInputFiles() override;<br>
+<br>
  private:<br>
    Writer &writer() const override;<br>
    mach_o::MachODylibFile* loadIndirectDylib(StringRef path);<br>
<br>
Modified: lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>PECOFFLinkingContext.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>PECOFFLinkingContext.h?rev=<u></u>223867&r1=223866&r2=223867&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>PECOFFLinkingContext.h (original)<br>
+++ lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>PECOFFLinkingContext.h Tue Dec  9 18:33:00 2014<br>
@@ -29,7 +29,6 @@ using llvm::COFF::WindowsSubsystem;<br>
  static const uint8_t DEFAULT_DOS_STUB[128] = {'M', 'Z'};<br>
    namespace lld {<br>
-class Group;<br>
    class PECOFFLinkingContext : public LinkingContext {<br>
  public:<br>
@@ -318,8 +317,7 @@ public:<br>
    void setEntryNode(SimpleFileNode *node) { _entryNode = node; }<br>
    SimpleFileNode *getEntryNode() const { return _entryNode; }<br>
  -  void setLibraryGroup(Group *group) { _libraryGroup = group; }<br>
-  Group *getLibraryGroup() const { return _libraryGroup; }<br>
+  void addLibraryFile(std::unique_<u></u>ptr<FileNode> file);<br>
      void setModuleDefinitionFile(const std::string val) {<br>
      _moduleDefinitionFile = val;<br>
@@ -441,9 +439,6 @@ private:<br>
    // The node containing the entry point file.<br>
    SimpleFileNode *_entryNode;<br>
  -  // The PECOFFGroup that contains all the .lib files.<br>
-  Group *_libraryGroup;<br>
-<br>
    // Name of the temporary file for lib.exe subcommand. For debugging<br>
    // only.<br>
    std::string _moduleDefinitionFile;<br>
<br>
Modified: lld/trunk/lib/Core/InputGraph.<u></u>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputGraph.cpp?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Core/<u></u>InputGraph.cpp?rev=223867&r1=<u></u>223866&r2=223867&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Core/InputGraph.<u></u>cpp (original)<br>
+++ lld/trunk/lib/Core/InputGraph.<u></u>cpp Tue Dec  9 18:33:00 2014<br>
@@ -36,8 +36,6 @@ ErrorOr<File &> InputGraph::getNextFile(<br>
    }<br>
  }<br>
  -void InputGraph::notifyProgress() { _currentInputElement-><u></u>notifyProgress(); }<br>
-<br>
  void InputGraph::registerObserver(<u></u>std::function<void(File *)> fn) {<br>
    _observers.push_back(fn);<br>
  }<br>
@@ -61,12 +59,13 @@ bool InputGraph::dump(raw_ostream &diagn<br>
  ErrorOr<InputElement *> InputGraph::<u></u>getNextInputElement() {<br>
    if (_nextElementIndex >= _inputArgs.size())<br>
      return make_error_code(<u></u>InputGraphError::no_more_<u></u>elements);<br>
-  return _inputArgs[_nextElementIndex++<u></u>].get();<br>
+  InputElement *elem = _inputArgs[_nextElementIndex++<u></u>].get();<br>
+  if (isa<GroupEnd>(elem))<br>
+    return getNextInputElement();<br>
+  return elem;<br>
  }<br>
    void InputGraph::normalize() {<br>
-  for (std::unique_ptr<InputElement> &elt : _inputArgs)<br>
-    elt->expand();<br>
    std::vector<std::unique_ptr<<u></u>InputElement>> vec;<br>
    for (std::unique_ptr<InputElement> &elt : _inputArgs) {<br>
      if (elt->getReplacements(vec))<br>
@@ -76,6 +75,25 @@ void InputGraph::normalize() {<br>
    _inputArgs = std::move(vec);<br>
  }<br>
  +// If we are at the end of a group, return its size (which indicates<br>
+// how many files we need to go back in the command line).<br>
+// Returns 0 if we are not at the end of a group.<br>
+int InputGraph::getGroupSize() {<br>
+  if (_nextElementIndex >= _inputArgs.size())<br>
+    return 0;<br>
+  InputElement *elem = _inputArgs[_nextElementIndex].<u></u>get();<br>
+  if (const GroupEnd *group = dyn_cast<GroupEnd>(elem))<br>
+    return group->getSize();<br>
+  return 0;<br>
+}<br>
+<br>
+void InputGraph::skipGroup() {<br>
+  if (_nextElementIndex >= _inputArgs.size())<br>
+    return;<br>
+  if (isa<GroupEnd>(_inputArgs[_<u></u>nextElementIndex].get()))<br>
+    _nextElementIndex++;<br>
+}<br>
+<br>
  /// \brief Read the file into _buffer.<br>
  std::error_code FileNode::getBuffer(StringRef filePath) {<br>
    // Create a memory buffer<br>
@@ -87,32 +105,10 @@ std::error_code FileNode::getBuffer(Stri<br>
    return std::error_code();<br>
  }<br>
  -/// \brief Return the next file that need to be processed by the resolver.<br>
-/// This also processes input elements depending on the resolve status<br>
-/// of the input elements contained in the group.<br>
-ErrorOr<File &> Group::getNextFile() {<br>
-  // If there are no elements, move on to the next input element<br>
-  if (_elements.empty())<br>
-    return make_error_code(<u></u>InputGraphError::no_more_<u></u>files);<br>
-<br>
-  for (;;) {<br>
-    // If we have processed all the elements, and have made no progress on<br>
-    // linking, we cannot resolve any symbol from this group. Continue to the<br>
-    // next one by returning no_more_files.<br>
-    if (_nextElementIndex == _elements.size()) {<br>
-      if (!_madeProgress)<br>
-        return make_error_code(<u></u>InputGraphError::no_more_<u></u>files);<br>
-      resetNextIndex();<br>
-    }<br>
-<br>
-    _currentElementIndex = _nextElementIndex;<br>
-    auto file = _elements[_nextElementIndex]-><u></u>getNextFile();<br>
-    // Move on to the next element if we have finished processing all<br>
-    // the files in the input element<br>
-    if (file.getError() == InputGraphError::no_more_<u></u>files) {<br>
-      _nextElementIndex++;<br>
-      continue;<br>
-    }<br>
-    return *file;<br>
-  }<br>
+bool FileNode::getReplacements(<u></u>InputGraph::<u></u>InputElementVectorT &result) {<br>
+  if (_files.size() < 2)<br>
+    return false;<br>
+  for (std::unique_ptr<File> &file : _files)<br>
+    result.push_back(llvm::make_<u></u>unique<SimpleFileNode>(_path, std::move(file)));<br>
+  return true;<br>
  }<br>
<br>
Modified: lld/trunk/lib/Core/Resolver.<u></u>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Core/<u></u>Resolver.cpp?rev=223867&r1=<u></u>223866&r2=223867&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Core/Resolver.<u></u>cpp (original)<br>
+++ lld/trunk/lib/Core/Resolver.<u></u>cpp Tue Dec  9 18:33:00 2014<br>
@@ -27,7 +27,7 @@<br>
    namespace lld {<br>
  -void Resolver::handleFile(const File &file) {<br>
+bool Resolver::handleFile(const File &file) {<br>
    bool undefAdded = false;<br>
    for (const DefinedAtom *atom : file.defined())<br>
      doDefinedAtom(*atom);<br>
@@ -38,13 +38,7 @@ void Resolver::handleFile(const File &fi<br>
      doSharedLibraryAtom(*atom);<br>
    for (const AbsoluteAtom *atom : file.absolute())<br>
      doAbsoluteAtom(*atom);<br>
-<br>
-  // Notify the input file manager of the fact that we have made some progress<br>
-  // on linking using the current input file. It may want to know the fact for<br>
-  // --start-group/--end-group.<br>
-  if (undefAdded) {<br>
-    _context.getInputGraph().<u></u>notifyProgress();<br>
-  }<br>
+  return undefAdded;<br>
  }<br>
    void Resolver::forEachUndefines(<u></u>bool searchForOverrides,<br>
@@ -76,17 +70,19 @@ void Resolver::forEachUndefines(<u></u>bool sea<br>
    } while (undefineGenCount != _symbolTable.size());<br>
  }<br>
  -void Resolver::handleArchiveFile(<u></u>const File &file) {<br>
+bool Resolver::handleArchiveFile(<u></u>const File &file) {<br>
    const ArchiveLibraryFile *archiveFile = cast<ArchiveLibraryFile>(&<u></u>file);<br>
    bool searchForOverrides =<br>
        _context.<u></u>searchArchivesToOverrideTentat<u></u>iveDefinitions();<br>
+  bool undefAdded = false;<br>
    forEachUndefines(<u></u>searchForOverrides,<br>
                     [&](StringRef undefName, bool dataSymbolOnly) {<br>
      if (const File *member = archiveFile->find(undefName, dataSymbolOnly)) {<br>
        member->setOrdinal(_context.<u></u>getNextOrdinalAndIncrement());<br>
-      handleFile(*member);<br>
+      undefAdded = handleFile(*member) || undefAdded;<br>
      }<br>
    });<br>
+  return undefAdded;<br>
  }<br>
    void Resolver::handleSharedLibrary(<u></u>const File &file) {<br>
@@ -233,31 +229,66 @@ void Resolver::addAtoms(const std::vecto<br>
      doDefinedAtom(*newAtom);<br>
  }<br>
  +// Returns true if at least one of N previous files has created an<br>
+// undefined symbol.<br>
+bool Resolver::undefinesAdded(int n) {<br>
+  for (size_t i = _fileIndex - n; i < _fileIndex; ++i)<br>
+    if (_newUndefinesAdded[_files[i]]<u></u>)<br>
+      return true;<br>
+  return false;<br>
+}<br>
+<br>
+ErrorOr<File &> Resolver::nextFile(bool &inGroup) {<br>
+  if (size_t groupSize = _context.getInputGraph().<u></u>getGroupSize()) {<br>
+    // We are at the end of the current group. If one or more new<br>
+    // undefined atom has been added in the last groupSize files, we<br>
+    // reiterate over the files.<br>
+    if (undefinesAdded(groupSize))<br>
+      _fileIndex -= groupSize;<br>
+    _context.getInputGraph().<u></u>skipGroup();<br>
+    return nextFile(inGroup);<br>
+  }<br>
+  if (_fileIndex < _files.size()) {<br>
+    // We are still in the current group.<br>
+    inGroup = true;<br>
+    return *_files[_fileIndex++];<br>
+  }<br>
+  // We are not in a group. Get a new file.<br>
+  ErrorOr<File &> file = _context.getInputGraph().<u></u>getNextFile();<br>
+  if (std::error_code ec = file.getError()) {<br>
+    if (ec != InputGraphError::no_more_<u></u>files)<br>
+      llvm::errs() << "Error occurred in getNextFile: " << ec.message() << "\n";<br>
+    return ec;<br>
+  }<br>
+  _files.push_back(&*file);<br>
+  ++_fileIndex;<br>
+  inGroup = false;<br>
+  return *file;<br>
+}<br>
+<br>
  // Keep adding atoms until _context.getNextFile() returns an error. This<br>
  // function is where undefined atoms are resolved.<br>
  bool Resolver::resolveUndefines() {<br>
    ScopedTask task(getDefaultDomain(), "resolveUndefines");<br>
      for (;;) {<br>
-    ErrorOr<File &> file = _context.getInputGraph().<u></u>getNextFile();<br>
-    std::error_code ec = file.getError();<br>
-    if (ec == InputGraphError::no_more_<u></u>files)<br>
-      return true;<br>
-    if (!file) {<br>
-      llvm::errs() << "Error occurred in getNextFile: " << ec.message() << "\n";<br>
-      return false;<br>
-    }<br>
-<br>
+    bool inGroup = false;<br>
+    bool undefAdded = false;<br>
+    ErrorOr<File &> file = nextFile(inGroup);<br>
+    if (std::error_code ec = file.getError())<br>
+      return ec == InputGraphError::no_more_<u></u>files;<br>
      switch (file->kind()) {<br>
      case File::kindObject:<br>
+      if (inGroup)<br>
+        break;<br>
        assert(!file->hasOrdinal());<br>
        file->setOrdinal(_context.<u></u>getNextOrdinalAndIncrement());<br>
-      handleFile(*file);<br>
+      undefAdded = handleFile(*file);<br>
        break;<br>
      case File::kindArchiveLibrary:<br>
        if (!file->hasOrdinal())<br>
          file->setOrdinal(_context.<u></u>getNextOrdinalAndIncrement());<br>
-      handleArchiveFile(*file);<br>
+      undefAdded = handleArchiveFile(*file);<br>
        break;<br>
      case File::kindSharedLibrary:<br>
        if (!file->hasOrdinal())<br>
@@ -265,6 +296,7 @@ bool Resolver::resolveUndefines() {<br>
        handleSharedLibrary(*file);<br>
        break;<br>
      }<br>
+    _newUndefinesAdded[&*file] = undefAdded;<br>
    }<br>
  }<br>
  <br>
Modified: lld/trunk/lib/Driver/<u></u>DarwinInputGraph.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinInputGraph.cpp?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Driver/<u></u>DarwinInputGraph.cpp?rev=<u></u>223867&r1=223866&r2=223867&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Driver/<u></u>DarwinInputGraph.cpp (original)<br>
+++ lld/trunk/lib/Driver/<u></u>DarwinInputGraph.cpp Tue Dec  9 18:33:00 2014<br>
@@ -18,48 +18,6 @@<br>
  namespace lld {<br>
    -ErrorOr<File &> DarwinInputGraph::getNextFile(<u></u>) {<br>
-  // The darwin linker processes input files in two phases.  The first phase<br>
-  // links in all object (.o) files in command line order. The second phase<br>
-  // links in libraries in command line order. If there are still UndefinedAtoms<br>
-  // the second phase is repeated until notifyProgress() is not called by<br>
-  // resolver.<br>
-  for (;;) {<br>
-    if (_currentInputElement) {<br>
-      for(;;) {<br>
-        ErrorOr<File &> next = _currentInputElement-><u></u>getNextFile();<br>
-        if (next.getError())<br>
-          break;<br>
-        File *file = &next.get();<br>
-        bool fileIsLibrary = isa<SharedLibraryFile>(file) ||<br>
-                             isa<ArchiveLibraryFile>(file);<br>
-        if (fileIsLibrary == _librariesPhase) {<br>
-          // Return library in library phase and object files in non-lib mode.<br>
-          return *file;<br>
-        }<br>
-      }<br>
-    }<br>
-<br>
-    if (_nextElementIndex >= _inputArgs.size()) {<br>
-      // If no more elements, done unless we need to repeat library scan.<br>
-      if (_librariesPhase && !_repeatLibraries)<br>
-        return make_error_code(<u></u>InputGraphError::no_more_<u></u>files);<br>
-      // Clear iterations and only look for libraries.<br>
-      _librariesPhase = true;<br>
-      _repeatLibraries = false;<br>
-      _nextElementIndex = 0;<br>
-      for (auto &ie : _inputArgs) {<br>
-        ie->resetNextIndex();<br>
-      }<br>
-    }<br>
-    _currentInputElement = _inputArgs[_nextElementIndex++<u></u>].get();<br>
-  }<br>
-}<br>
-<br>
-void DarwinInputGraph::<u></u>notifyProgress() {<br>
-  _repeatLibraries = true;<br>
-}<br>
-<br>
  /// \brief Parse the input file to lld::File.<br>
  std::error_code MachOFileNode::parse(const LinkingContext &ctx,<br>
                                       raw_ostream &diagnostics)  {<br>
<br>
Modified: lld/trunk/lib/Driver/<u></u>DarwinLdDriver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Driver/<u></u>DarwinLdDriver.cpp?rev=223867&<u></u>r1=223866&r2=223867&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Driver/<u></u>DarwinLdDriver.cpp (original)<br>
+++ lld/trunk/lib/Driver/<u></u>DarwinLdDriver.cpp Tue Dec  9 18:33:00 2014<br>
@@ -83,7 +83,7 @@ static std::string canonicalizePath(Stri<br>
    }<br>
  }<br>
  -static void addFile(StringRef path, std::unique_ptr<<u></u>DarwinInputGraph> &inputGraph,<br>
+static void addFile(StringRef path, std::unique_ptr<InputGraph> &inputGraph,<br>
                      MachOLinkingContext &ctx, bool loadWholeArchive,<br>
                      bool upwardDylib) {<br>
    auto node = llvm::make_unique<<u></u>MachOFileNode>(path, ctx);<br>
@@ -185,7 +185,7 @@ static std::error_code parseOrderFile(St<br>
  // per line. The <dir> prefix is prepended to each partial path.<br>
  //<br>
  static std::error_code parseFileList(StringRef fileListPath,<br>
-                                     std::unique_ptr<<u></u>DarwinInputGraph> &inputGraph,<br>
+                                     std::unique_ptr<InputGraph> &inputGraph,<br>
                                       MachOLinkingContext &ctx, bool forceLoad,<br>
                                       raw_ostream &diagnostics) {<br>
    // If there is a comma, split off <dir>.<br>
@@ -521,7 +521,7 @@ bool DarwinLdDriver::parse(int argc, con<br>
      }<br>
    }<br>
  -  std::unique_ptr<<u></u>DarwinInputGraph> inputGraph(new DarwinInputGraph());<br>
+  std::unique_ptr<InputGraph> inputGraph(new InputGraph());<br>
      // Now construct the set of library search directories, following ld64's<br>
    // baroque set of accumulated hacks. Mostly, the algorithm constructs<br>
<br>
Modified: lld/trunk/lib/Driver/Driver.<u></u>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Driver.cpp?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Driver/<u></u>Driver.cpp?rev=223867&r1=<u></u>223866&r2=223867&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Driver/Driver.<u></u>cpp (original)<br>
+++ lld/trunk/lib/Driver/Driver.<u></u>cpp Tue Dec  9 18:33:00 2014<br>
@@ -62,9 +62,6 @@ bool Driver::link(LinkingContext &contex<br>
        if (std::error_code ec = ie->parse(context, stream)) {<br>
          if (FileNode *fileNode = dyn_cast<FileNode>(ie.get()))<br>
            stream << fileNode->errStr(ec) << "\n";<br>
-        else if (dyn_cast<Group>(ie.get()))<br>
-          // FIXME: We need a better diagnostics here<br>
-          stream << "Cannot parse group input element\n";<br>
          else<br>
            llvm_unreachable("Unknown type of input element");<br>
          fail = true;<br>
@@ -83,21 +80,24 @@ bool Driver::link(LinkingContext &contex<br>
    if (fail)<br>
      return false;<br>
  -  std::unique_ptr<<u></u>SimpleFileNode> fileNode(<br>
-      new SimpleFileNode("Internal Files"));<br>
-<br>
    InputGraph::FileVectorT internalFiles;<br>
    context.createInternalFiles(<u></u>internalFiles);<br>
-<br>
-  if (internalFiles.size())<br>
-    fileNode->addFiles(std::move(<u></u>internalFiles));<br>
+  for (auto i = internalFiles.rbegin(), e = internalFiles.rend(); i != e; ++i) {<br>
+    context.getInputGraph().<u></u>addInputElementFront(<br>
+        llvm::make_unique<<u></u>SimpleFileNode>("internal", std::move(*i)));<br>
+  }<br>
      // Give target a chance to add files.<br>
    InputGraph::FileVectorT implicitFiles;<br>
    context.createImplicitFiles(<u></u>implicitFiles);<br>
-  if (implicitFiles.size())<br>
-    fileNode->addFiles(std::move(<u></u>implicitFiles));<br>
-  context.getInputGraph().<u></u>addInputElementFront(std::<u></u>move(fileNode));<br>
+  for (auto i = implicitFiles.rbegin(), e = implicitFiles.rend(); i != e; ++i) {<br>
+    context.getInputGraph().<u></u>addInputElementFront(<br>
+        llvm::make_unique<<u></u>SimpleFileNode>("implicit", std::move(*i)));<br>
+  }<br>
+<br>
+  // Give target a chance to sort the input files.<br>
+  // Mach-O uses this chance to move all object files before library files.<br>
+  context.maybeSortInputFiles();<br>
      // Do core linking.<br>
    ScopedTask resolveTask(getDefaultDomain()<u></u>, "Resolve");<br>
<br>
Modified: lld/trunk/lib/Driver/<u></u>GnuLdDriver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Driver/<u></u>GnuLdDriver.cpp?rev=223867&r1=<u></u>223866&r2=223867&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Driver/<u></u>GnuLdDriver.cpp (original)<br>
+++ lld/trunk/lib/Driver/<u></u>GnuLdDriver.cpp Tue Dec  9 18:33:00 2014<br>
@@ -295,7 +295,8 @@ bool GnuLdDriver::parse(int argc, const<br>
    }<br>
      std::unique_ptr<InputGraph> inputGraph(new InputGraph());<br>
-  std::stack<Group *> groupStack;<br>
+  std::stack<int> groupStack;<br>
+  int numfiles = 0;<br>
      ELFFileNode::Attributes attributes;<br>
  @@ -468,16 +469,21 @@ bool GnuLdDriver::parse(int argc, const<br>
        break;<br>
      }<br>
  -    case OPT_start_group: {<br>
-      std::unique_ptr<Group> group(new Group());<br>
-      groupStack.push(group.get());<br>
-      inputGraph->addInputElement(<u></u>std::move(group));<br>
+    case OPT_start_group:<br>
+      groupStack.push(numfiles);<br>
        break;<br>
-    }<br>
  -    case OPT_end_group:<br>
+    case OPT_end_group: {<br>
+      if (groupStack.empty()) {<br>
+        diagnostics << "stray --end-group\n";<br>
+        return false;<br>
+      }<br>
+      int startGroupPos = groupStack.top();<br>
+      inputGraph->addInputElement(<br>
+          llvm::make_unique<GroupEnd>(<u></u>numfiles - startGroupPos));<br>
        groupStack.pop();<br>
        break;<br>
+    }<br>
        case OPT_z: {<br>
        StringRef extOpt = inputArg->getValue();<br>
@@ -552,11 +558,8 @@ bool GnuLdDriver::parse(int argc, const<br>
          }<br>
        }<br>
        std::unique_ptr<InputElement> inputFile(inputNode);<br>
-      if (groupStack.empty()) {<br>
-        inputGraph->addInputElement(<u></u>std::move(inputFile));<br>
-      } else {<br>
-        groupStack.top()->addFile(std:<u></u>:move(inputFile));<br>
-      }<br>
+      ++numfiles;<br>
+      inputGraph->addInputElement(<u></u>std::move(inputFile));<br>
        break;<br>
      }<br>
  <br>
Modified: lld/trunk/lib/Driver/<u></u>GnuLdInputGraph.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdInputGraph.cpp?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Driver/<u></u>GnuLdInputGraph.cpp?rev=<u></u>223867&r1=223866&r2=223867&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Driver/<u></u>GnuLdInputGraph.cpp (original)<br>
+++ lld/trunk/lib/Driver/<u></u>GnuLdInputGraph.cpp Tue Dec  9 18:33:00 2014<br>
@@ -91,7 +91,7 @@ std::error_code ELFGNULdScript::parse(co<br>
      auto *group = dyn_cast<script::Group>(c);<br>
      if (!group)<br>
        continue;<br>
-    std::unique_ptr<Group> groupStart(new Group());<br>
+    size_t numfiles = 0;<br>
      for (const script::Path &path : group->getPaths()) {<br>
        // TODO : Propagate Set WholeArchive/dashlPrefix<br>
        attributes.setAsNeeded(path._<u></u>asNeeded);<br>
@@ -100,9 +100,10 @@ std::error_code ELFGNULdScript::parse(co<br>
            _elfLinkingContext, _elfLinkingContext.<u></u>allocateString(path._path),<br>
            attributes);<br>
        std::unique_ptr<InputElement> inputFile(inputNode);<br>
-      groupStart.get()->addFile(std:<u></u>:move(inputFile));<br>
+      _expandElements.push_back(std:<u></u>:move(inputFile));<br>
+      ++numfiles;<br>
      }<br>
-    _expandElements.push_back(std:<u></u>:move(groupStart));<br>
+    _expandElements.push_back(<u></u>llvm::make_unique<GroupEnd>(<u></u>numfiles));<br>
    }<br>
    return std::error_code();<br>
  }<br>
<br>
Modified: lld/trunk/lib/Driver/<u></u>WinLinkDriver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Driver/<u></u>WinLinkDriver.cpp?rev=223867&<u></u>r1=223866&r2=223867&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Driver/<u></u>WinLinkDriver.cpp (original)<br>
+++ lld/trunk/lib/Driver/<u></u>WinLinkDriver.cpp Tue Dec  9 18:33:00 2014<br>
@@ -781,7 +781,7 @@ static bool hasLibrary(const PECOFFLinki<br>
    ErrorOr<StringRef> path = fileNode->getPath(ctx);<br>
    if (!path)<br>
      return false;<br>
-  for (std::unique_ptr<InputElement> &p : ctx.getLibraryGroup()-><u></u>elements())<br>
+  for (std::unique_ptr<InputElement> &p : ctx.getInputGraph().<u></u>inputElements())<br>
      if (auto *f = dyn_cast<FileNode>(p.get()))<br>
        if (*path == *f->getPath(ctx))<br>
          return true;<br>
@@ -1397,10 +1397,8 @@ bool WinLinkDriver::parse(int argc, cons<br>
      ctx.setEntryNode(entry.get());<br>
      ctx.getInputGraph().<u></u>addInputElement(std::move(<u></u>entry));<br>
  -    // The container for all library files.<br>
-    std::unique_ptr<Group> group(new PECOFFGroup(ctx));<br>
-    ctx.setLibraryGroup(group.get(<u></u>));<br>
-    ctx.getInputGraph().<u></u>addInputElement(std::move(<u></u>group));<br>
+    // Add a group-end marker.<br>
+    ctx.getInputGraph().<u></u>addInputElement(llvm::make_<u></u>unique<GroupEnd>(0));<br>
    }<br>
      // Add the library files to the library group.<br>
@@ -1409,7 +1407,7 @@ bool WinLinkDriver::parse(int argc, cons<br>
        if (isReadingDirectiveSection)<br>
          if (lib->parse(ctx, diag))<br>
            return false;<br>
-      ctx.getLibraryGroup()-><u></u>addFile(std::move(lib));<br>
+      ctx.addLibraryFile(std::move(<u></u>lib));<br>
      }<br>
    }<br>
  <br>
Modified: lld/trunk/lib/ReaderWriter/<u></u>MachO/MachOLinkingContext.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/<u></u>ReaderWriter/MachO/<u></u>MachOLinkingContext.cpp?rev=<u></u>223867&r1=223866&r2=223867&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/ReaderWriter/<u></u>MachO/MachOLinkingContext.cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/<u></u>MachO/MachOLinkingContext.cpp Tue Dec  9 18:33:00 2014<br>
@@ -22,6 +22,7 @@<br>
  #include "llvm/ADT/Triple.h"<br>
  #include "llvm/Config/config.h"<br>
  #include "llvm/Support/Errc.h"<br>
+#include "llvm/Support/Debug.h"<br>
  #include "llvm/Support/Host.h"<br>
  #include "llvm/Support/MachO.h"<br>
  #include "llvm/Support/Path.h"<br>
@@ -923,4 +924,35 @@ bool MachOLinkingContext::<u></u>customAtomOrde<br>
    return true;<br>
  }<br>
  +static File *getFirstFile(const std::unique_ptr<InputElement> &elem) {<br>
+  FileNode *e = dyn_cast<FileNode>(const_cast<<u></u>InputElement *>(elem.get()));<br>
+  if (!e || e->files().empty())<br>
+    return nullptr;<br>
+  return e->files()[0].get();<br>
+}<br>
+<br>
+static bool isLibrary(const std::unique_ptr<InputElement> &elem) {<br>
+  File *f = getFirstFile(elem);<br>
+  return f && (isa<SharedLibraryFile>(f) || isa<ArchiveLibraryFile>(f));<br>
+}<br>
+<br>
+// The darwin linker processes input files in two phases.  The first phase<br>
+// links in all object (.o) files in command line order. The second phase<br>
+// links in libraries in command line order.<br>
+// In this function we reorder the input files so that all the object files<br>
+// comes before any library file. We also make a group for the library files<br>
+// so that the Resolver will reiterate over the libraries as long as we find<br>
+// new undefines from libraries.<br>
+void MachOLinkingContext::<u></u>maybeSortInputFiles() {<br>
+  std::vector<std::unique_ptr<<u></u>InputElement>> &elements<br>
+      = getInputGraph().inputElements(<u></u>);<br>
+  std::stable_sort(elements.<u></u>begin(), elements.end(),<br>
+                   [](const std::unique_ptr<InputElement> &a,<br>
+                      const std::unique_ptr<InputElement> &b) {<br>
+                     return !isLibrary(a) && isLibrary(b);<br>
+                   });<br>
+  size_t numLibs = std::count_if(elements.begin()<u></u>, elements.end(), isLibrary);<br>
+  elements.push_back(llvm::make_<u></u>unique<GroupEnd>(numLibs));<br>
+}<br>
+<br>
  } // end namespace lld<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/<u></u>PECOFF/PECOFFLinkingContext.<u></u>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/<u></u>ReaderWriter/PECOFF/<u></u>PECOFFLinkingContext.cpp?rev=<u></u>223867&r1=223866&r2=223867&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/ReaderWriter/<u></u>PECOFF/PECOFFLinkingContext.<u></u>cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/<u></u>PECOFF/PECOFFLinkingContext.<u></u>cpp Tue Dec  9 18:33:00 2014<br>
@@ -87,6 +87,23 @@ std::unique_ptr<File> PECOFFLinkingConte<br>
        "<command line option /include>");<br>
  }<br>
  +void PECOFFLinkingContext::<u></u>addLibraryFile(std::unique_<u></u>ptr<FileNode> file) {<br>
+  GroupEnd *currentGroupEnd;<br>
+  int pos = -1;<br>
+  std::vector<std::unique_ptr<<u></u>InputElement>> &elements<br>
+      = getInputGraph().inputElements(<u></u>);<br>
+  for (int i = 0, e = elements.size(); i < e; ++i) {<br>
+    if ((currentGroupEnd = dyn_cast<GroupEnd>(elements[i]<u></u>.get()))) {<br>
+      pos = i;<br>
+      break;<br>
+    }<br>
+  }<br>
+  assert(pos >= 0);<br>
+  elements.insert(elements.<u></u>begin() + pos, std::move(file));<br>
+  elements[pos + 1] = llvm::make_unique<GroupEnd>(<br>
+      currentGroupEnd->getSize() + 1);<br>
+}<br>
+<br>
  bool PECOFFLinkingContext::<u></u>createImplicitFiles(<br>
      std::vector<std::unique_ptr<<u></u>File>> &) {<br>
    // Create a file for __ImageBase.<br>
@@ -109,7 +126,7 @@ bool PECOFFLinkingContext::<u></u>createImplici<br>
    auto exportNode = llvm::make_unique<<u></u>SimpleFileNode>("<export>");<br>
    exportNode->appendInputFile(<br>
        llvm::make_unique<pecoff::<u></u>ExportedSymbolRenameFile>(*<u></u>this, syms));<br>
-  getLibraryGroup()->addFile(<u></u>std::move(exportNode));<br>
+  addLibraryFile(std::move(<u></u>exportNode));<br>
      // Create a file for the entry point function.<br>
    getEntryNode()-><u></u>appendInputFile(<br>
<br>
Modified: lld/trunk/unittests/<u></u>DriverTests/DriverTest.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/DriverTest.h?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/unittests/<u></u>DriverTests/DriverTest.h?rev=<u></u>223867&r1=223866&r2=223867&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/unittests/<u></u>DriverTests/DriverTest.h (original)<br>
+++ lld/trunk/unittests/<u></u>DriverTests/DriverTest.h Tue Dec  9 18:33:00 2014<br>
@@ -37,18 +37,6 @@ protected:<br>
      llvm_unreachable("not handling other types of input files");<br>
    }<br>
  -  // Convenience method for getting i'th input files name.<br>
-  std::string inputFile(int index1, int index2) {<br>
-    Group *group = dyn_cast<Group>(<br>
-        linkingContext()-><u></u>getInputGraph().inputElements(<u></u>)[index1].get());<br>
-    if (!group)<br>
-      llvm_unreachable("not handling other types of input files");<br>
-    FileNode *file = dyn_cast<FileNode>(group-><u></u>elements()[index2].get());<br>
-    if (!file)<br>
-      llvm_unreachable("not handling other types of input files");<br>
-    return *file->getPath(*<u></u>linkingContext());<br>
-  }<br>
-<br>
    // For unit tests to call driver with various command lines.<br>
    bool parse(const char *args, ...) {<br>
      // Construct command line options from varargs.<br>
<br>
Modified: lld/trunk/unittests/<u></u>DriverTests/InputGraphTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/InputGraphTest.cpp?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/unittests/<u></u>DriverTests/InputGraphTest.<u></u>cpp?rev=223867&r1=223866&r2=<u></u>223867&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/unittests/<u></u>DriverTests/InputGraphTest.cpp (original)<br>
+++ lld/trunk/unittests/<u></u>DriverTests/InputGraphTest.cpp Tue Dec  9 18:33:00 2014<br>
@@ -77,7 +77,7 @@ protected:<br>
    } // end anonymous namespace<br>
  -static std::unique_ptr<TestFileNode> createFile1(StringRef name) {<br>
+static std::unique_ptr<TestFileNode> createFile(StringRef name) {<br>
    std::vector<std::unique_ptr<<u></u>File>> files;<br>
    files.push_back(std::unique_<u></u>ptr<SimpleFile>(new SimpleFile(name)));<br>
    std::unique_ptr<TestFileNode> file(new TestFileNode("filenode"));<br>
@@ -85,109 +85,30 @@ static std::unique_ptr<TestFileNode> cre<br>
    return file;<br>
  }<br>
  -static std::unique_ptr<TestFileNode> createFile2(StringRef name1,<br>
-                                                 StringRef name2) {<br>
-  std::vector<std::unique_ptr<<u></u>File>> files;<br>
-  files.push_back(std::unique_<u></u>ptr<SimpleFile>(new SimpleFile(name1)));<br>
-  files.push_back(std::unique_<u></u>ptr<SimpleFile>(new SimpleFile(name2)));<br>
-  std::unique_ptr<TestFileNode> file(new TestFileNode("filenode"));<br>
-  file->addFiles(std::move(<u></u>files));<br>
-  return file;<br>
-}<br>
-<br>
  TEST_F(InputGraphTest, Empty) {<br>
    expectEnd();<br>
  }<br>
    TEST_F(InputGraphTest, File) {<br>
-  _graph->addInputElement(<u></u>createFile1("file1"));<br>
-  EXPECT_EQ("file1", getNext());<br>
-  expectEnd();<br>
-}<br>
-<br>
-TEST_F(InputGraphTest, Files) {<br>
-  _graph->addInputElement(<u></u>createFile2("file1", "file2"));<br>
-  EXPECT_EQ("file1", getNext());<br>
-  EXPECT_EQ("file2", getNext());<br>
-  expectEnd();<br>
-}<br>
-<br>
-TEST_F(InputGraphTest, Group) {<br>
-  _graph->addInputElement(<u></u>createFile2("file1", "file2"));<br>
-<br>
-  std::unique_ptr<Group> group(new Group());<br>
-  group->addFile(createFile2("<u></u>file3", "file4"));<br>
-  group->addFile(createFile1("<u></u>file5"));<br>
-  group->addFile(createFile1("<u></u>file6"));<br>
-  _graph->addInputElement(std::<u></u>move(group));<br>
-<br>
+  _graph->addInputElement(<u></u>createFile("file1"));<br>
    EXPECT_EQ("file1", getNext());<br>
-  EXPECT_EQ("file2", getNext());<br>
-  EXPECT_EQ("file3", getNext());<br>
-  EXPECT_EQ("file4", getNext());<br>
-  EXPECT_EQ("file5", getNext());<br>
-  EXPECT_EQ("file6", getNext());<br>
-  expectEnd();<br>
-}<br>
-<br>
-// Iterate through the group<br>
-TEST_F(InputGraphTest, GroupIteration) {<br>
-  _graph->addInputElement(<u></u>createFile2("file1", "file2"));<br>
-<br>
-  std::unique_ptr<Group> group(new Group());<br>
-  group->addFile(createFile2("<u></u>file3", "file4"));<br>
-  group->addFile(createFile1("<u></u>file5"));<br>
-  group->addFile(createFile1("<u></u>file6"));<br>
-  _graph->addInputElement(std::<u></u>move(group));<br>
-<br>
-  EXPECT_EQ("file1", getNext());<br>
-  EXPECT_EQ("file2", getNext());<br>
-<br>
-  EXPECT_EQ("file3", getNext());<br>
-  EXPECT_EQ("file4", getNext());<br>
-  EXPECT_EQ("file5", getNext());<br>
-  EXPECT_EQ("file6", getNext());<br>
-  _graph->notifyProgress();<br>
-<br>
-  EXPECT_EQ("file3", getNext());<br>
-  EXPECT_EQ("file4", getNext());<br>
-  _graph->notifyProgress();<br>
-  EXPECT_EQ("file5", getNext());<br>
-  EXPECT_EQ("file6", getNext());<br>
-<br>
-  EXPECT_EQ("file3", getNext());<br>
-  EXPECT_EQ("file4", getNext());<br>
-  EXPECT_EQ("file5", getNext());<br>
-  EXPECT_EQ("file6", getNext());<br>
    expectEnd();<br>
  }<br>
    // Node expansion tests<br>
  TEST_F(InputGraphTest, Normalize) {<br>
-  _graph->addInputElement(<u></u>createFile2("file1", "file2"));<br>
+  _graph->addInputElement(<u></u>createFile("file1"));<br>
      std::unique_ptr<<u></u>TestExpandFileNode> expandFile(<br>
        new TestExpandFileNode("node"));<br>
-  expandFile->addElement(<u></u>createFile1("file3"));<br>
-  expandFile->addElement(<u></u>createFile1("file4"));<br>
+  expandFile->addElement(<u></u>createFile("file2"));<br>
+  expandFile->addElement(<u></u>createFile("file3"));<br>
    _graph->addInputElement(std::<u></u>move(expandFile));<br>
-<br>
-  std::unique_ptr<Group> group(new Group());<br>
-  std::unique_ptr<<u></u>TestExpandFileNode> expandFile2(<br>
-      new TestExpandFileNode("node"));<br>
-  expandFile2->addElement(<u></u>createFile1("file5"));<br>
-  group->addFile(std::move(<u></u>expandFile2));<br>
-  _graph->addInputElement(std::<u></u>move(group));<br>
-<br>
-  _graph->addInputElement(<u></u>createFile1("file6"));<br>
    _graph->normalize();<br>
      EXPECT_EQ("file1", getNext());<br>
    EXPECT_EQ("file2", getNext());<br>
    EXPECT_EQ("file3", getNext());<br>
-  EXPECT_EQ("file4", getNext());<br>
-  EXPECT_EQ("file5", getNext());<br>
-  EXPECT_EQ("file6", getNext());<br>
    expectEnd();<br>
  }<br>
  @@ -195,8 +116,8 @@ TEST_F(InputGraphTest, Observer) {<br>
    std::vector<std::string> files;<br>
    _graph->registerObserver([&](<u></u>File *file) { files.push_back(file->path()); });<br>
  -  _graph->addInputElement(<u></u>createFile1("file1"));<br>
-  _graph->addInputElement(<u></u>createFile1("file2"));<br>
+  _graph->addInputElement(<u></u>createFile("file1"));<br>
+  _graph->addInputElement(<u></u>createFile("file2"));<br>
    EXPECT_EQ("file1", getNext());<br>
    EXPECT_EQ("file2", getNext());<br>
    expectEnd();<br>
<br>
Modified: lld/trunk/unittests/<u></u>DriverTests/WinLinkDriverTest.<u></u>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=223867&r1=223866&r2=223867&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/unittests/<u></u>DriverTests/WinLinkDriverTest.<u></u>cpp?rev=223867&r1=223866&r2=<u></u>223867&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/unittests/<u></u>DriverTests/WinLinkDriverTest.<u></u>cpp (original)<br>
+++ lld/trunk/unittests/<u></u>DriverTests/WinLinkDriverTest.<u></u>cpp Tue Dec  9 18:33:00 2014<br>
@@ -137,11 +137,11 @@ TEST_F(WinLinkParserTest, Libpath) {<br>
  TEST_F(WinLinkParserTest, InputOrder) {<br>
    EXPECT_TRUE(parse("link.exe", "a.lib", "b.obj", "c.obj", "a.lib", "d.obj",<br>
                      nullptr));<br>
-  EXPECT_EQ(5, inputFileCount());<br>
+  EXPECT_EQ(6, inputFileCount());<br>
    EXPECT_EQ("b.obj", inputFile(0));<br>
    EXPECT_EQ("c.obj", inputFile(1));<br>
    EXPECT_EQ("d.obj", inputFile(2));<br>
-  EXPECT_EQ("a.lib", inputFile(4, 0));<br>
+  EXPECT_EQ("a.lib", inputFile(4));<br>
  }<br>
    //<br>
@@ -393,36 +393,36 @@ TEST_F(WinLinkParserTest, SectionMultipl<br>
  TEST_F(WinLinkParserTest, DefaultLib) {<br>
    EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",<br>
                      "/defaultlib:kernel32", "a.obj", nullptr));<br>
-  EXPECT_EQ(3, inputFileCount());<br>
+  EXPECT_EQ(5, inputFileCount());<br>
    EXPECT_EQ("a.obj", inputFile(0));<br>
-  EXPECT_EQ("user32.lib", inputFile(2, 0));<br>
-  EXPECT_EQ("kernel32.lib", inputFile(2, 1));<br>
+  EXPECT_EQ("user32.lib", inputFile(2));<br>
+  EXPECT_EQ("kernel32.lib", inputFile(3));<br>
  }<br>
    TEST_F(WinLinkParserTest, DefaultLibDuplicates) {<br>
    EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",<br>
                      "/defaultlib:user32.lib", "a.obj", nullptr));<br>
-  EXPECT_EQ(3, inputFileCount());<br>
+  EXPECT_EQ(4, inputFileCount());<br>
    EXPECT_EQ("a.obj", inputFile(0));<br>
-  EXPECT_EQ("user32.lib", inputFile(2, 0));<br>
+  EXPECT_EQ("user32.lib", inputFile(2));<br>
  }<br>
    TEST_F(WinLinkParserTest, NoDefaultLib) {<br>
    EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",<br>
                      "/defaultlib:kernel32", "/nodefaultlib:user32.lib", "a.obj",<br>
                      nullptr));<br>
-  EXPECT_EQ(3, inputFileCount());<br>
+  EXPECT_EQ(4, inputFileCount());<br>
    EXPECT_EQ("a.obj", inputFile(0));<br>
-  EXPECT_EQ("kernel32.lib", inputFile(2, 0));<br>
+  EXPECT_EQ("kernel32.lib", inputFile(2));<br>
  }<br>
    TEST_F(WinLinkParserTest, NoDefaultLibCase) {<br>
    EXPECT_TRUE(parse("link.exe", "/defaultlib:user32",<br>
                      "/defaultlib:kernel32", "/nodefaultlib:USER32.LIB", "a.obj",<br>
                      nullptr));<br>
-  EXPECT_EQ(3, inputFileCount());<br>
+  EXPECT_EQ(4, inputFileCount());<br>
    EXPECT_EQ("a.obj", inputFile(0));<br>
-  EXPECT_EQ("kernel32.lib", inputFile(2, 0));<br>
+  EXPECT_EQ("kernel32.lib", inputFile(2));<br>
  }<br>
    TEST_F(WinLinkParserTest, NoDefaultLibAll) {<br>
@@ -436,9 +436,9 @@ TEST_F(WinLinkParserTest, DisallowLib) {<br>
    EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",<br>
                      "/defaultlib:kernel32", "/disallowlib:user32.lib", "a.obj",<br>
                      nullptr));<br>
-  EXPECT_EQ(3, inputFileCount());<br>
+  EXPECT_EQ(4, inputFileCount());<br>
    EXPECT_EQ("a.obj", inputFile(0));<br>
-  EXPECT_EQ("kernel32.lib", inputFile(2, 0));<br>
+  EXPECT_EQ("kernel32.lib", inputFile(2));<br>
  }<br>
    //<br>
<br>
<br>
______________________________<u></u>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/llvm-commits</a><br>
<br>
<br>
</blockquote>
<br>
<br></div></div><span class="HOEnZb"><font color="#888888">
-- <br>
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation<br>
<br>
</font></span></blockquote></div><br></div>