Revert "Rewrite InputGraph's Group"

This reverts commit r223330 because it broke Darwin and ELF
linkers in a way that we couldn't have caught with the existing
test cases.

llvm-svn: 223373
diff --git a/lld/lib/Core/InputGraph.cpp b/lld/lib/Core/InputGraph.cpp
index cde4127..27cbcbb 100644
--- a/lld/lib/Core/InputGraph.cpp
+++ b/lld/lib/Core/InputGraph.cpp
@@ -36,6 +36,8 @@
   }
 }
 
+void InputGraph::notifyProgress() { _currentInputElement->notifyProgress(); }
+
 void InputGraph::registerObserver(std::function<void(File *)> fn) {
   _observers.push_back(fn);
 }
@@ -59,13 +61,12 @@
 ErrorOr<InputElement *> InputGraph::getNextInputElement() {
   if (_nextElementIndex >= _inputArgs.size())
     return make_error_code(InputGraphError::no_more_elements);
-  InputElement *elem = _inputArgs[_nextElementIndex++].get();
-  if (isa<GroupEnd>(elem))
-    return getNextInputElement();
-  return elem;
+  return _inputArgs[_nextElementIndex++].get();
 }
 
 void InputGraph::normalize() {
+  for (std::unique_ptr<InputElement> &elt : _inputArgs)
+    elt->expand();
   std::vector<std::unique_ptr<InputElement>> vec;
   for (std::unique_ptr<InputElement> &elt : _inputArgs) {
     if (elt->getReplacements(vec))
@@ -75,25 +76,6 @@
   _inputArgs = std::move(vec);
 }
 
-// If we are at the end of a group, return its size (which indicates
-// how many files we need to go back in the command line).
-// Returns 0 if we are not at the end of a group.
-int InputGraph::getGroupSize() {
-  if (_nextElementIndex >= _inputArgs.size())
-    return 0;
-  InputElement *elem = _inputArgs[_nextElementIndex].get();
-  if (const GroupEnd *group = dyn_cast<GroupEnd>(elem))
-    return group->getSize();
-  return 0;
-}
-
-void InputGraph::skipGroup() {
-  if (_nextElementIndex >= _inputArgs.size())
-    return;
-  if (isa<GroupEnd>(_inputArgs[_nextElementIndex].get()))
-    _nextElementIndex++;
-}
-
 /// \brief Read the file into _buffer.
 std::error_code FileNode::getBuffer(StringRef filePath) {
   // Create a memory buffer
@@ -105,10 +87,32 @@
   return std::error_code();
 }
 
-bool FileNode::getReplacements(InputGraph::InputElementVectorT &result) {
-  if (_files.size() < 2)
-    return false;
-  for (std::unique_ptr<File> &file : _files)
-    result.push_back(llvm::make_unique<SimpleFileNode>(_path, std::move(file)));
-  return true;
+/// \brief Return the next file that need to be processed by the resolver.
+/// This also processes input elements depending on the resolve status
+/// of the input elements contained in the group.
+ErrorOr<File &> Group::getNextFile() {
+  // If there are no elements, move on to the next input element
+  if (_elements.empty())
+    return make_error_code(InputGraphError::no_more_files);
+
+  for (;;) {
+    // If we have processed all the elements, and have made no progress on
+    // linking, we cannot resolve any symbol from this group. Continue to the
+    // next one by returning no_more_files.
+    if (_nextElementIndex == _elements.size()) {
+      if (!_madeProgress)
+        return make_error_code(InputGraphError::no_more_files);
+      resetNextIndex();
+    }
+
+    _currentElementIndex = _nextElementIndex;
+    auto file = _elements[_nextElementIndex]->getNextFile();
+    // Move on to the next element if we have finished processing all
+    // the files in the input element
+    if (file.getError() == InputGraphError::no_more_files) {
+      _nextElementIndex++;
+      continue;
+    }
+    return *file;
+  }
 }
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp
index f92c115..e4a1b53 100644
--- a/lld/lib/Core/Resolver.cpp
+++ b/lld/lib/Core/Resolver.cpp
@@ -27,7 +27,7 @@
 
 namespace lld {
 
-bool Resolver::handleFile(const File &file) {
+void Resolver::handleFile(const File &file) {
   bool undefAdded = false;
   for (const DefinedAtom *atom : file.defined())
     doDefinedAtom(*atom);
@@ -38,7 +38,13 @@
     doSharedLibraryAtom(*atom);
   for (const AbsoluteAtom *atom : file.absolute())
     doAbsoluteAtom(*atom);
-  return undefAdded;
+
+  // Notify the input file manager of the fact that we have made some progress
+  // on linking using the current input file. It may want to know the fact for
+  // --start-group/--end-group.
+  if (undefAdded) {
+    _context.getInputGraph().notifyProgress();
+  }
 }
 
 void Resolver::forEachUndefines(bool searchForOverrides,
@@ -70,19 +76,17 @@
   } while (undefineGenCount != _symbolTable.size());
 }
 
-bool Resolver::handleArchiveFile(const File &file) {
+void Resolver::handleArchiveFile(const File &file) {
   const ArchiveLibraryFile *archiveFile = cast<ArchiveLibraryFile>(&file);
   bool searchForOverrides =
       _context.searchArchivesToOverrideTentativeDefinitions();
-  bool undefAdded = false;
   forEachUndefines(searchForOverrides,
                    [&](StringRef undefName, bool dataSymbolOnly) {
     if (const File *member = archiveFile->find(undefName, dataSymbolOnly)) {
       member->setOrdinal(_context.getNextOrdinalAndIncrement());
-      undefAdded = undefAdded || handleFile(*member);
+      handleFile(*member);
     }
   });
-  return undefAdded;
 }
 
 void Resolver::handleSharedLibrary(const File &file) {
@@ -229,66 +233,31 @@
     doDefinedAtom(*newAtom);
 }
 
-// Returns true if at least one of N previous files has created an
-// undefined symbol.
-bool Resolver::undefinesAdded(int n) {
-  for (size_t i = _fileIndex - n; i < _fileIndex; ++i)
-    if (_newUndefinesAdded[_files[i]])
-      return true;
-  return false;
-}
-
-ErrorOr<File &> Resolver::nextFile(bool &inGroup) {
-  if (size_t groupSize = _context.getInputGraph().getGroupSize()) {
-    // We are at the end of the current group. If one or more new
-    // undefined atom has been added in the last groupSize files, we
-    // reiterate over the files.
-    if (undefinesAdded(groupSize))
-      _fileIndex -= groupSize;
-    _context.getInputGraph().skipGroup();
-    return nextFile(inGroup);
-  }
-  if (_fileIndex < _files.size()) {
-    // We are still in the current group.
-    inGroup = true;
-    return *_files[_fileIndex++];
-  }
-  // We are not in a group. Get a new file.
-  ErrorOr<File &> file = _context.getInputGraph().getNextFile();
-  if (std::error_code ec = file.getError()) {
-    if (ec != InputGraphError::no_more_files)
-      llvm::errs() << "Error occurred in getNextFile: " << ec.message() << "\n";
-    return ec;
-  }
-  _files.push_back(&*file);
-  ++_fileIndex;
-  inGroup = false;
-  return *file;
-}
-
 // Keep adding atoms until _context.getNextFile() returns an error. This
 // function is where undefined atoms are resolved.
 bool Resolver::resolveUndefines() {
   ScopedTask task(getDefaultDomain(), "resolveUndefines");
 
   for (;;) {
-    bool inGroup = false;
-    bool undefAdded = false;
-    ErrorOr<File &> file = nextFile(inGroup);
-    if (std::error_code ec = file.getError())
-      return ec == InputGraphError::no_more_files;
+    ErrorOr<File &> file = _context.getInputGraph().getNextFile();
+    std::error_code ec = file.getError();
+    if (ec == InputGraphError::no_more_files)
+      return true;
+    if (!file) {
+      llvm::errs() << "Error occurred in getNextFile: " << ec.message() << "\n";
+      return false;
+    }
+
     switch (file->kind()) {
     case File::kindObject:
-      if (inGroup)
-        break;
       assert(!file->hasOrdinal());
       file->setOrdinal(_context.getNextOrdinalAndIncrement());
-      undefAdded = handleFile(*file);
+      handleFile(*file);
       break;
     case File::kindArchiveLibrary:
       if (!file->hasOrdinal())
         file->setOrdinal(_context.getNextOrdinalAndIncrement());
-      undefAdded = handleArchiveFile(*file);
+      handleArchiveFile(*file);
       break;
     case File::kindSharedLibrary:
       if (!file->hasOrdinal())
@@ -296,7 +265,6 @@
       handleSharedLibrary(*file);
       break;
     }
-    _newUndefinesAdded[&*file] = undefAdded;
   }
 }