<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">Hi Rui,<br>
      <br>
      I try to build clang with lld by just taking the arguments
      directly from the usual clang build, without any change.<br>
      <br>
      You should be able to reproduce it locally, but anyways here are
      the arguments to build clang with lld with the Gnu flavor :-<br>
      <br>
      <b>lld -flavor gnu</b>  -z relro --hash-style=gnu --build-id
      --eh-frame-hdr -m elf_x86_64 -dynamic-linker
      /lib64/ld-linux-x86-64.so.2 -o bin/clang-3.6
      /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o
      /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o
      /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/crtbegin.o
      -L/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9
      -L/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu
      -L/lib/x86_64-linux-gnu -L/lib/../lib64
      -L/usr/lib/x86_64-linux-gnu
      -L/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../..
      -L/usr/lib/llvm-3.5/bin/../lib -L/lib -L/usr/lib
      -allow-shlib-undefined --export-dynamic -O3
      tools/clang/tools/driver/CMakeFiles/clang.dir/driver.cpp.o
      tools/clang/tools/driver/CMakeFiles/clang.dir/cc1_main.cpp.o
      tools/clang/tools/driver/CMakeFiles/clang.dir/cc1as_main.cpp.o
      lib/libLLVMAArch64CodeGen.a lib/libLLVMAArch64AsmPrinter.a
      lib/libLLVMAArch64AsmParser.a lib/libLLVMAArch64Desc.a
      lib/libLLVMAArch64Info.a lib/libLLVMAArch64Disassembler.a
      lib/libLLVMARMCodeGen.a lib/libLLVMARMAsmPrinter.a
      lib/libLLVMARMAsmParser.a lib/libLLVMARMDesc.a
      lib/libLLVMARMInfo.a lib/libLLVMARMDisassembler.a
      lib/libLLVMCppBackendCodeGen.a lib/libLLVMCppBackendInfo.a
      lib/libLLVMHexagonCodeGen.a lib/libLLVMHexagonDesc.a
      lib/libLLVMHexagonInfo.a lib/libLLVMHexagonDisassembler.a
      lib/libLLVMMipsCodeGen.a lib/libLLVMMipsAsmPrinter.a
      lib/libLLVMMipsAsmParser.a lib/libLLVMMipsDesc.a
      lib/libLLVMMipsInfo.a lib/libLLVMMipsDisassembler.a
      lib/libLLVMMSP430CodeGen.a lib/libLLVMMSP430AsmPrinter.a
      lib/libLLVMMSP430Desc.a lib/libLLVMMSP430Info.a
      lib/libLLVMNVPTXCodeGen.a lib/libLLVMNVPTXAsmPrinter.a
      lib/libLLVMNVPTXDesc.a lib/libLLVMNVPTXInfo.a
      lib/libLLVMPowerPCCodeGen.a lib/libLLVMPowerPCAsmPrinter.a
      lib/libLLVMPowerPCAsmParser.a lib/libLLVMPowerPCDesc.a
      lib/libLLVMPowerPCInfo.a lib/libLLVMPowerPCDisassembler.a
      lib/libLLVMR600CodeGen.a lib/libLLVMR600AsmPrinter.a
      lib/libLLVMR600AsmParser.a lib/libLLVMR600Desc.a
      lib/libLLVMR600Info.a lib/libLLVMSparcCodeGen.a
      lib/libLLVMSparcAsmPrinter.a lib/libLLVMSparcAsmParser.a
      lib/libLLVMSparcDesc.a lib/libLLVMSparcInfo.a
      lib/libLLVMSparcDisassembler.a lib/libLLVMSystemZCodeGen.a
      lib/libLLVMSystemZAsmPrinter.a lib/libLLVMSystemZAsmParser.a
      lib/libLLVMSystemZDesc.a lib/libLLVMSystemZInfo.a
      lib/libLLVMSystemZDisassembler.a lib/libLLVMX86CodeGen.a
      lib/libLLVMX86AsmPrinter.a lib/libLLVMX86AsmParser.a
      lib/libLLVMX86Desc.a lib/libLLVMX86Info.a
      lib/libLLVMX86Disassembler.a lib/libLLVMXCoreCodeGen.a
      lib/libLLVMXCoreAsmPrinter.a lib/libLLVMXCoreDesc.a
      lib/libLLVMXCoreInfo.a lib/libLLVMXCoreDisassembler.a
      lib/libLLVMAnalysis.a lib/libLLVMCodeGen.a lib/libLLVMCore.a
      lib/libLLVMipa.a lib/libLLVMipo.a lib/libLLVMInstCombine.a
      lib/libLLVMInstrumentation.a lib/libLLVMMC.a lib/libLLVMMCParser.a
      lib/libLLVMObjCARCOpts.a lib/libLLVMOption.a
      lib/libLLVMScalarOpts.a lib/libLLVMSupport.a
      lib/libLLVMTransformUtils.a lib/libLLVMVectorize.a
      lib/libclangBasic.a lib/libclangDriver.a lib/libclangFrontend.a
      lib/libclangFrontendTool.a lib/libLLVMAArch64AsmPrinter.a
      lib/libLLVMAArch64Info.a lib/libLLVMAArch64Utils.a
      lib/libLLVMARMDesc.a lib/libLLVMARMAsmPrinter.a
      lib/libLLVMARMInfo.a lib/libLLVMHexagonDesc.a
      lib/libLLVMHexagonInfo.a lib/libLLVMMipsAsmPrinter.a
      lib/libLLVMMipsInfo.a lib/libLLVMMSP430AsmPrinter.a
      lib/libLLVMNVPTXAsmPrinter.a lib/libLLVMPowerPCAsmPrinter.a
      lib/libLLVMPowerPCInfo.a lib/libLLVMR600AsmPrinter.a
      lib/libLLVMSparcAsmPrinter.a lib/libLLVMSparcInfo.a
      lib/libLLVMSystemZDesc.a lib/libLLVMSystemZAsmPrinter.a
      lib/libLLVMSystemZInfo.a lib/libLLVMX86CodeGen.a
      lib/libLLVMX86Desc.a lib/libLLVMX86AsmPrinter.a
      lib/libLLVMX86Utils.a lib/libLLVMX86Info.a
      lib/libLLVMXCoreAsmPrinter.a lib/libLLVMAsmPrinter.a
      lib/libLLVMSelectionDAG.a lib/libLLVMCodeGen.a
      lib/libLLVMXCoreInfo.a lib/libLLVMMCDisassembler.a
      lib/libclangCodeGen.a lib/libLLVMipo.a lib/libLLVMVectorize.a
      lib/libLLVMInstrumentation.a lib/libLLVMObjCARCOpts.a
      lib/libLLVMScalarOpts.a lib/libLLVMInstCombine.a
      lib/libLLVMProfileData.a lib/libLLVMObject.a
      lib/libLLVMBitWriter.a lib/libLLVMIRReader.a
      lib/libLLVMAsmParser.a lib/libLLVMLinker.a
      lib/libLLVMTransformUtils.a lib/libLLVMipa.a lib/libLLVMAnalysis.a
      lib/libLLVMTarget.a lib/libclangRewriteFrontend.a
      lib/libclangARCMigrate.a lib/libclangStaticAnalyzerFrontend.a
      lib/libclangFrontend.a lib/libclangDriver.a lib/libLLVMOption.a
      lib/libclangParse.a lib/libLLVMMCParser.a
      lib/libclangSerialization.a lib/libclangSema.a lib/libclangEdit.a
      lib/libLLVMBitReader.a lib/libclangStaticAnalyzerCheckers.a
      lib/libclangStaticAnalyzerCore.a lib/libclangAnalysis.a
      lib/libclangAST.a lib/libclangRewrite.a lib/libclangLex.a
      lib/libclangBasic.a lib/libLLVMCore.a lib/libLLVMMC.a
      lib/libLLVMSupport.a -lrt -ldl -ltinfo -latomic -lpthread -lz -lm
      -rpath "\$ORIGIN/../lib" -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s
      -lgcc /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/crtend.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crtn.o<br>
      <br>
      Shankar Easwaran<br>
      <br>
      On 12/4/2014 12:26 PM, Rui Ueyama wrote:<br>
    </div>
    <blockquote
cite="mid:CAJENXgv2Serxon4a4zc0DFKpWyU3T2+S_QNRzc-MaNX4SYCboA@mail.gmail.com"
      type="cite">
      <pre wrap="">Let me roll this back first.

Jean-Deniel and Shankar, please send me code so that I can reproduce that
issue locally (and I will add the tests).

On Thu, Dec 4, 2014 at 9:34 AM, Shankar Easwaran <a class="moz-txt-link-rfc2396E" href="mailto:shankare@codeaurora.org"><shankare@codeaurora.org></a>
wrote:

</pre>
      <blockquote type="cite">
        <pre wrap=""> Hi Ruiu,

Sorry I missed this review completely.

We have taken a lot of effort to be able to build clang with lld, and this
change prevents building clang with lld anymore as it fails with unresolved
symbols.  Please revert this change.

*There are two things missing for modeling the Gnu flavor with this model
as part of this change as well when I reviewed :-*

a) The ELF writer needs to dump the way the linker resolved with
start-group/end-group information.

b) This model is also difficult to model --as-needed, --no-as-needed. The
shared libraries in the list need to be added, only if the shared libraries
resolved any symbol.
For the above, the resolver has to notify the LinkingContext about how
symbols were resolved for this functionality.

Finally I would think we thoroughly review the the proposal that
myself/Bigcheese talked about in the developers conference.

The linkingcontext will be completely responsible for managing the input
graph, which will just be a vector of InputElements that contain a tag in
addition to the FileLocator.


<a class="moz-txt-link-freetext" href="http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20141027/242287.html">http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20141027/242287.html</a>

Shankar Easwaran


On 12/3/2014 7:09 PM, Rui Ueyama wrote:

Author: ruiu
Date: Wed Dec  3 19:09:06 2014
New Revision: 223330

URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project?rev=223330&view=rev">http://llvm.org/viewvc/llvm-project?rev=223330&view=rev</a>
Log:
Rewrite InputGraph's Group

The aim of this patch is to reduce the excessive abstraction from
the InputGraph. We found that even a simple thing, such as sorting
input files (Mach-O) or adding a new file to the input file list
(PE/COFF), is nearly impossible with the InputGraph abstraction,
because it hides too much information behind it. As a result,
we invented complex interactions between components (e.g.
notifyProgress() mechanism) and tricky code to work around that
limitation. There were many occasions that we needed to write
awkward code.

This patch is a first step to make it cleaner. As a first step,
this removes Group class from the InputGraph. The grouping feature
is now directly handled by the Resolver. notifyProgress is removed
since we no longer need that. I could have cleaned it up even more,
but in order to keep the patch minimum, I focused on Group.

SimpleFileNode class, a container of File objects, is now limited
to have only one File. We shold have done this earlier.
We used to allow putting multiple File objects to FileNode.
Although SimpleFileNode usually has only one file, the Driver class
actually used that capability. I modified the Driver class a bit,
so that one FileNode is created for each input File.

We should now probably remove SimpleFileNode and directly store
File objects to the InputGraph in some way, because a container
that can contain only one object is useless. This is a TODO.

Mach-O input files are now sorted before they are passe to the
Resolver. DarwinInputGraph class is no longer needed, so removed.

PECOFF still has hacky code to add a new file to the input file list.
This will be cleaned up in another patch.

Modified:
    lld/trunk/include/lld/Core/InputGraph.h
    lld/trunk/include/lld/Core/LinkingContext.h
    lld/trunk/include/lld/Core/Resolver.h
    lld/trunk/include/lld/Driver/DarwinInputGraph.h
    lld/trunk/include/lld/Driver/WinLinkInputGraph.h
    lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
    lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
    lld/trunk/lib/Core/InputGraph.cpp
    lld/trunk/lib/Core/Resolver.cpp
    lld/trunk/lib/Driver/DarwinInputGraph.cpp
    lld/trunk/lib/Driver/DarwinLdDriver.cpp
    lld/trunk/lib/Driver/Driver.cpp
    lld/trunk/lib/Driver/GnuLdDriver.cpp
    lld/trunk/lib/Driver/GnuLdInputGraph.cpp
    lld/trunk/lib/Driver/WinLinkDriver.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
    lld/trunk/unittests/DriverTests/DriverTest.h
    lld/trunk/unittests/DriverTests/InputGraphTest.cpp
    lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp

Modified: lld/trunk/include/lld/Core/InputGraph.h
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputGraph.h?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputGraph.h?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/include/lld/Core/InputGraph.h (original)
+++ lld/trunk/include/lld/Core/InputGraph.h Wed Dec  3 19:09:06 2014
@@ -59,12 +59,6 @@ public:
   /// assigned in the way files are resolved.
   virtual ErrorOr<File &> getNextFile();

-  /// Notifies the current input element of Resolver made some progress on
-  /// resolving undefined symbols using the current file. Group (representing
-  /// --start-group and --end-group) uses that notification to make a decision
-  /// whether it should iterate over again or terminate or not.
-  virtual void notifyProgress();
-
   /// Adds an observer of getNextFile(). Each time a new file is about to be
   /// returned from getNextFile(), registered observers are called with the file
   /// being returned.
@@ -76,14 +70,18 @@ public:
   /// \brief Adds a node at the beginning of the InputGraph
   void addInputElementFront(std::unique_ptr<InputElement>);

-  /// Normalize the InputGraph. It calls expand() on each node and then replace
-  /// it with getReplacements() results.
+  /// Normalize the InputGraph. It calls getReplacements() on each element.
   void normalize();

-  range<InputElementIterT> inputElements() {
-    return make_range(_inputArgs.begin(), _inputArgs.end());
+  InputElementVectorT &inputElements() {
+    return _inputArgs;
   }

+  // Returns the current group size if we are at an --end-group.
+  // Otherwise returns 0.
+  int getGroupSize();
+  void skipGroup();
+
   // \brief Returns the number of input files.
   size_t size() const { return _inputArgs.size(); }

@@ -108,8 +106,8 @@ class InputElement {
 public:
   /// Each input element in the graph can be a File or a control
   enum class Kind : uint8_t {
-    Group,      // Represents a type associated with Group
-    File        // Represents a type associated with File Nodes
+    File,       // Represents a type associated with File Nodes
+    GroupEnd,
   };

   InputElement(Kind type) : _kind(type) {}
@@ -129,16 +127,9 @@ public:
   /// Get the next file to be processed by the resolver
   virtual ErrorOr<File &> getNextFile() = 0;

-  /// Refer InputGraph::notifyProgress(). By default, it does nothing. Only
-  /// Group is interested in this message.
-  virtual void notifyProgress() {};
-
   /// \brief Reset the next index
   virtual void resetNextIndex() = 0;

-  /// Returns true if we want to replace this node with children.
-  virtual void expand() {}
-
   /// Get the elements that we want to expand with.
   virtual bool getReplacements(InputGraph::InputElementVectorT &) {
     return false;
@@ -148,73 +139,31 @@ protected:
   Kind _kind; // The type of the Element
 };

-/// \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 InputElement {
+// This is a marker for --end-group. getSize() returns the number of
+// files between the corresponding --start-group and this marker.
+class GroupEnd : public InputElement {
 public:
-  Group()
-      : InputElement(InputElement::Kind::Group), _currentElementIndex(0),
-        _nextElementIndex(0), _madeProgress(false) {}
+  GroupEnd(int size) : InputElement(Kind::GroupEnd), _size(size) {}

-  static inline bool classof(const InputElement *a) {
-    return a->kind() == InputElement::Kind::Group;
-  }
-
-  /// \brief Process input element and add it to the group
-  bool addFile(std::unique_ptr<InputElement> element) {
-    _elements.push_back(std::move(element));
-    return true;
-  }
+  int getSize() const { return _size; }

-  range<InputGraph::InputElementIterT> elements() {
-    return make_range(_elements.begin(), _elements.end());
-  }
-
-  void resetNextIndex() override {
-    _madeProgress = false;
-    _currentElementIndex = 0;
-    _nextElementIndex = 0;
-    for (std::unique_ptr<InputElement> &elem : _elements)
-      elem->resetNextIndex();
+  static inline bool classof(const InputElement *a) {
+    return a->kind() == Kind::GroupEnd;
   }

   /// \brief Parse the group members.
   std::error_code parse(const LinkingContext &ctx, raw_ostream &diag) override {
-    for (std::unique_ptr<InputElement> &ei : _elements)
-      if (std::error_code ec = ei->parse(ctx, diag))
-        return ec;
     return std::error_code();
   }

-  /// If Resolver made a progress using the current file, it's ok to revisit
-  /// files in this group in future.
-  void notifyProgress() override {
-    for (std::unique_ptr<InputElement> &elem : _elements)
-      elem->notifyProgress();
-    _madeProgress = true;
-  }
-
-  ErrorOr<File &> getNextFile() override;
-
-  void expand() override {
-    for (std::unique_ptr<InputElement> &elt : _elements)
-      elt->expand();
-    std::vector<std::unique_ptr<InputElement>> result;
-    for (std::unique_ptr<InputElement> &elt : _elements) {
-      if (elt->getReplacements(result))
-        continue;
-      result.push_back(std::move(elt));
-    }
-    _elements.swap(result);
+  ErrorOr<File &> getNextFile() override {
+    llvm_unreachable("shouldn't be here.");
   }

-protected:
-  InputGraph::InputElementVectorT _elements;
-  uint32_t _currentElementIndex;
-  uint32_t _nextElementIndex;
-  bool _madeProgress;
+  void resetNextIndex() override {}
+
+private:
+  int _size;
 };

 /// \brief Represents an Input file in the graph
@@ -252,6 +201,8 @@ public:

   /// \brief add a file to the list of files
   virtual void addFiles(InputGraph::FileVectorT files) {
+    assert(files.size() == 1);
+    assert(_files.empty());
     for (std::unique_ptr<File> &ai : files)
       _files.push_back(std::move(ai));
   }
@@ -260,6 +211,8 @@ public:
   /// the node again.
   void resetNextIndex() override { _nextFileIndex = 0; }

+  bool getReplacements(InputGraph::InputElementVectorT &result) override;
+
 protected:
   /// \brief Read the file into _buffer.
   std::error_code getBuffer(StringRef filePath);
@@ -276,6 +229,10 @@ protected:
 class SimpleFileNode : public FileNode {
 public:
   SimpleFileNode(StringRef path) : FileNode(path) {}
+  SimpleFileNode(StringRef path, std::unique_ptr<File> f)
+      : FileNode(path) {
+    _files.push_back(std::move(f));
+  }

   virtual ~SimpleFileNode() {}


Modified: lld/trunk/include/lld/Core/LinkingContext.h
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/LinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/LinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/include/lld/Core/LinkingContext.h (original)
+++ lld/trunk/include/lld/Core/LinkingContext.h Wed Dec  3 19:09:06 2014
@@ -322,6 +322,10 @@ public:
   bool runRoundTripPass() const { return _runRoundTripPasses; }
 #endif

+  // This function is called just before the Resolver kicks in.
+  // Derived classes may use that chance to rearrange the input files.
+  virtual void maybeSortInputFiles() {}
+
   /// @}
 protected:
   LinkingContext(); // Must be subclassed

Modified: lld/trunk/include/lld/Core/Resolver.h
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/include/lld/Core/Resolver.h (original)
+++ lld/trunk/include/lld/Core/Resolver.h Wed Dec  3 19:09:06 2014
@@ -28,7 +28,8 @@ class LinkingContext;
 class Resolver {
 public:
   Resolver(LinkingContext &context)
-      : _context(context), _symbolTable(context), _result(new MergedFile()) {}
+      : _context(context), _symbolTable(context), _result(new MergedFile()),
+        _fileIndex(0) {}

   // InputFiles::Handler methods
   void doDefinedAtom(const DefinedAtom&);
@@ -38,10 +39,10 @@ public:

   // Handle files, this adds atoms from the current file thats
   // being processed by the resolver
-  void handleFile(const File &);
+  bool handleFile(const File &);

   // Handle an archive library file.
-  void handleArchiveFile(const File &);
+  bool handleArchiveFile(const File &);

   // Handle a shared library file.
   void handleSharedLibrary(const File &);
@@ -54,6 +55,9 @@ public:
 private:
   typedef std::function<void(StringRef, bool)> UndefCallback;

+  bool undefinesAdded(int count);
+  ErrorOr<File &> nextFile(bool &inGroup);
+
   /// \brief Add section group/.gnu.linkonce if it does not exist previously.
   void maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom);

@@ -110,6 +114,11 @@ private:
   llvm::DenseSet<const Atom *>  _deadAtoms;
   std::unique_ptr<MergedFile>   _result;
   llvm::DenseMap<const Atom *, llvm::DenseSet<const Atom *>> _reverseRef;
+
+  // --start-group and --end-group
+  std::vector<File *> _files;
+  std::map<File *, bool> _newUndefinesAdded;
+  size_t _fileIndex;
 };

 } // namespace lld

Modified: lld/trunk/include/lld/Driver/DarwinInputGraph.h
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/DarwinInputGraph.h?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/DarwinInputGraph.h?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/include/lld/Driver/DarwinInputGraph.h (original)
+++ lld/trunk/include/lld/Driver/DarwinInputGraph.h Wed Dec  3 19:09:06 2014
@@ -23,18 +23,6 @@

 namespace lld {

-
-class DarwinInputGraph : public InputGraph {
-public:
-  DarwinInputGraph() : _librariesPhase(false), _repeatLibraries(false) { }
-  ErrorOr<File &> getNextFile() override;
-  void notifyProgress() override;
-private:
-  bool _librariesPhase;
-  bool _repeatLibraries;
-};
-
-
 /// \brief Represents a MachO File
 class MachOFileNode : public FileNode {
 public:

Modified: lld/trunk/include/lld/Driver/WinLinkInputGraph.h
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/WinLinkInputGraph.h?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/WinLinkInputGraph.h?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/include/lld/Driver/WinLinkInputGraph.h (original)
+++ lld/trunk/include/lld/Driver/WinLinkInputGraph.h Wed Dec  3 19:09:06 2014
@@ -55,21 +55,6 @@ public:
   ErrorOr<StringRef> getPath(const LinkingContext &ctx) const override;
 };

-/// \brief Represents a ELF control node
-class PECOFFGroup : public Group {
-public:
-  PECOFFGroup(PECOFFLinkingContext &ctx) : Group(), _ctx(ctx) {}
-
-  /// \brief Parse the group members.
-  std::error_code parse(const LinkingContext &ctx, raw_ostream &diag) override {
-    std::lock_guard<std::recursive_mutex> lock(_ctx.getMutex());
-    return Group::parse(ctx, diag);
-  }
-
-private:
-  PECOFFLinkingContext &_ctx;
-};
-
 } // namespace lld

 #endif

Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Wed Dec  3 19:09:06 2014
@@ -283,6 +283,8 @@ public:
   /// bits are xxxx.yy.zz.  Largest number is 65535.255.255
   static bool parsePackedVersion(StringRef str, uint32_t &result);

+  void maybeSortInputFiles() override;
+
 private:
   Writer &writer() const override;
   mach_o::MachODylibFile* loadIndirectDylib(StringRef path);

Modified: lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Wed Dec  3 19:09:06 2014
@@ -29,7 +29,6 @@ using llvm::COFF::WindowsSubsystem;
 static const uint8_t DEFAULT_DOS_STUB[128] = {'M', 'Z'};

 namespace lld {
-class Group;

 class PECOFFLinkingContext : public LinkingContext {
 public:
@@ -315,8 +314,7 @@ public:
   void setEntryNode(SimpleFileNode *node) { _entryNode = node; }
   SimpleFileNode *getEntryNode() const { return _entryNode; }

-  void setLibraryGroup(Group *group) { _libraryGroup = group; }
-  Group *getLibraryGroup() const { return _libraryGroup; }
+  void addLibraryFile(std::unique_ptr<FileNode> file);

   void setModuleDefinitionFile(const std::string val) {
     _moduleDefinitionFile = val;
@@ -438,9 +436,6 @@ private:
   // The node containing the entry point file.
   SimpleFileNode *_entryNode;

-  // The PECOFFGroup that contains all the .lib files.
-  Group *_libraryGroup;
-
   // Name of the temporary file for lib.exe subcommand. For debugging
   // only.
   std::string _moduleDefinitionFile;

Modified: lld/trunk/lib/Core/InputGraph.cpp
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/lib/Core/InputGraph.cpp (original)
+++ lld/trunk/lib/Core/InputGraph.cpp Wed Dec  3 19:09:06 2014
@@ -36,8 +36,6 @@ ErrorOr<File &> InputGraph::getNextFile(
   }
 }

-void InputGraph::notifyProgress() { _currentInputElement->notifyProgress(); }
-
 void InputGraph::registerObserver(std::function<void(File *)> fn) {
   _observers.push_back(fn);
 }
@@ -61,12 +59,13 @@ bool InputGraph::dump(raw_ostream &diagn
 ErrorOr<InputElement *> InputGraph::getNextInputElement() {
   if (_nextElementIndex >= _inputArgs.size())
     return make_error_code(InputGraphError::no_more_elements);
-  return _inputArgs[_nextElementIndex++].get();
+  InputElement *elem = _inputArgs[_nextElementIndex++].get();
+  if (isa<GroupEnd>(elem))
+    return getNextInputElement();
+  return elem;
 }

 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))
@@ -76,6 +75,25 @@ void InputGraph::normalize() {
   _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
@@ -87,32 +105,10 @@ std::error_code FileNode::getBuffer(Stri
   return std::error_code();
 }

-/// \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;
-  }
+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;
 }

Modified: lld/trunk/lib/Core/Resolver.cpp
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Wed Dec  3 19:09:06 2014
@@ -27,7 +27,7 @@

 namespace lld {

-void Resolver::handleFile(const File &file) {
+bool Resolver::handleFile(const File &file) {
   bool undefAdded = false;
   for (const DefinedAtom *atom : file.defined())
     doDefinedAtom(*atom);
@@ -38,13 +38,7 @@ void Resolver::handleFile(const File &fi
     doSharedLibraryAtom(*atom);
   for (const AbsoluteAtom *atom : file.absolute())
     doAbsoluteAtom(*atom);
-
-  // 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();
-  }
+  return undefAdded;
 }

 void Resolver::forEachUndefines(bool searchForOverrides,
@@ -76,17 +70,19 @@ void Resolver::forEachUndefines(bool sea
   } while (undefineGenCount != _symbolTable.size());
 }

-void Resolver::handleArchiveFile(const File &file) {
+bool 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());
-      handleFile(*member);
+      undefAdded = undefAdded || handleFile(*member);
     }
   });
+  return undefAdded;
 }

 void Resolver::handleSharedLibrary(const File &file) {
@@ -233,31 +229,66 @@ void Resolver::addAtoms(const std::vecto
     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 (;;) {
-    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;
-    }
-
+    bool inGroup = false;
+    bool undefAdded = false;
+    ErrorOr<File &> file = nextFile(inGroup);
+    if (std::error_code ec = file.getError())
+      return ec == InputGraphError::no_more_files;
     switch (file->kind()) {
     case File::kindObject:
+      if (inGroup)
+        break;
       assert(!file->hasOrdinal());
       file->setOrdinal(_context.getNextOrdinalAndIncrement());
-      handleFile(*file);
+      undefAdded = handleFile(*file);
       break;
     case File::kindArchiveLibrary:
       if (!file->hasOrdinal())
         file->setOrdinal(_context.getNextOrdinalAndIncrement());
-      handleArchiveFile(*file);
+      undefAdded = handleArchiveFile(*file);
       break;
     case File::kindSharedLibrary:
       if (!file->hasOrdinal())
@@ -265,6 +296,7 @@ bool Resolver::resolveUndefines() {
       handleSharedLibrary(*file);
       break;
     }
+    _newUndefinesAdded[&*file] = undefAdded;
   }
 }


Modified: lld/trunk/lib/Driver/DarwinInputGraph.cpp
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinInputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinInputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/lib/Driver/DarwinInputGraph.cpp (original)
+++ lld/trunk/lib/Driver/DarwinInputGraph.cpp Wed Dec  3 19:09:06 2014
@@ -18,48 +18,6 @@
 namespace lld {


-ErrorOr<File &> DarwinInputGraph::getNextFile() {
-  // The darwin linker processes input files in two phases.  The first phase
-  // links in all object (.o) files in command line order. The second phase
-  // links in libraries in command line order. If there are still UndefinedAtoms
-  // the second phase is repeated until notifyProgress() is not called by
-  // resolver.
-  for (;;) {
-    if (_currentInputElement) {
-      for(;;) {
-        ErrorOr<File &> next = _currentInputElement->getNextFile();
-        if (next.getError())
-          break;
-        File *file = &next.get();
-        bool fileIsLibrary = isa<SharedLibraryFile>(file) ||
-                             isa<ArchiveLibraryFile>(file);
-        if (fileIsLibrary == _librariesPhase) {
-          // Return library in library phase and object files in non-lib mode.
-          return *file;
-        }
-      }
-    }
-
-    if (_nextElementIndex >= _inputArgs.size()) {
-      // If no more elements, done unless we need to repeat library scan.
-      if (_librariesPhase && !_repeatLibraries)
-        return make_error_code(InputGraphError::no_more_files);
-      // Clear iterations and only look for libraries.
-      _librariesPhase = true;
-      _repeatLibraries = false;
-      _nextElementIndex = 0;
-      for (auto &ie : _inputArgs) {
-        ie->resetNextIndex();
-      }
-    }
-    _currentInputElement = _inputArgs[_nextElementIndex++].get();
-  }
-}
-
-void DarwinInputGraph::notifyProgress() {
-  _repeatLibraries = true;
-}
-
 /// \brief Parse the input file to lld::File.
 std::error_code MachOFileNode::parse(const LinkingContext &ctx,
                                      raw_ostream &diagnostics)  {

Modified: lld/trunk/lib/Driver/DarwinLdDriver.cpp
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/DarwinLdDriver.cpp Wed Dec  3 19:09:06 2014
@@ -83,7 +83,7 @@ static std::string canonicalizePath(Stri
   }
 }

-static void addFile(StringRef path, std::unique_ptr<DarwinInputGraph> &inputGraph,
+static void addFile(StringRef path, std::unique_ptr<InputGraph> &inputGraph,
                     MachOLinkingContext &ctx, bool loadWholeArchive,
                     bool upwardDylib) {
   auto node = llvm::make_unique<MachOFileNode>(path, ctx);
@@ -185,7 +185,7 @@ static std::error_code parseOrderFile(St
 // per line. The <dir> prefix is prepended to each partial path.
 //
 static std::error_code parseFileList(StringRef fileListPath,
-                                     std::unique_ptr<DarwinInputGraph> &inputGraph,
+                                     std::unique_ptr<InputGraph> &inputGraph,
                                      MachOLinkingContext &ctx, bool forceLoad,
                                      raw_ostream &diagnostics) {
   // If there is a comma, split off <dir>.
@@ -521,7 +521,7 @@ bool DarwinLdDriver::parse(int argc, con
     }
   }

-  std::unique_ptr<DarwinInputGraph> inputGraph(new DarwinInputGraph());
+  std::unique_ptr<InputGraph> inputGraph(new InputGraph());

   // Now construct the set of library search directories, following ld64's
   // baroque set of accumulated hacks. Mostly, the algorithm constructs

Modified: lld/trunk/lib/Driver/Driver.cpp
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Driver.cpp?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Driver.cpp?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/lib/Driver/Driver.cpp (original)
+++ lld/trunk/lib/Driver/Driver.cpp Wed Dec  3 19:09:06 2014
@@ -62,9 +62,6 @@ bool Driver::link(LinkingContext &contex
       if (std::error_code ec = ie->parse(context, stream)) {
         if (FileNode *fileNode = dyn_cast<FileNode>(ie.get()))
           stream << fileNode->errStr(ec) << "\n";
-        else if (dyn_cast<Group>(ie.get()))
-          // FIXME: We need a better diagnostics here
-          stream << "Cannot parse group input element\n";
         else
           llvm_unreachable("Unknown type of input element");
         fail = true;
@@ -83,21 +80,24 @@ bool Driver::link(LinkingContext &contex
   if (fail)
     return false;

-  std::unique_ptr<SimpleFileNode> fileNode(
-      new SimpleFileNode("Internal Files"));
-
   InputGraph::FileVectorT internalFiles;
   context.createInternalFiles(internalFiles);
-
-  if (internalFiles.size())
-    fileNode->addFiles(std::move(internalFiles));
+  for (auto i = internalFiles.rbegin(), e = internalFiles.rend(); i != e; ++i) {
+    context.getInputGraph().addInputElementFront(
+        llvm::make_unique<SimpleFileNode>("internal", std::move(*i)));
+  }

   // Give target a chance to add files.
   InputGraph::FileVectorT implicitFiles;
   context.createImplicitFiles(implicitFiles);
-  if (implicitFiles.size())
-    fileNode->addFiles(std::move(implicitFiles));
-  context.getInputGraph().addInputElementFront(std::move(fileNode));
+  for (auto i = implicitFiles.rbegin(), e = implicitFiles.rend(); i != e; ++i) {
+    context.getInputGraph().addInputElementFront(
+        llvm::make_unique<SimpleFileNode>("implicit", std::move(*i)));
+  }
+
+  // Give target a chance to sort the input files.
+  // Mach-O uses this chance to move all object files before library files.
+  context.maybeSortInputFiles();

   // Do core linking.
   ScopedTask resolveTask(getDefaultDomain(), "Resolve");

Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdDriver.cpp Wed Dec  3 19:09:06 2014
@@ -295,7 +295,8 @@ bool GnuLdDriver::parse(int argc, const
   }

   std::unique_ptr<InputGraph> inputGraph(new InputGraph());
-  std::stack<Group *> groupStack;
+  std::stack<int> groupStack;
+  int numfiles = 0;

   ELFFileNode::Attributes attributes;

@@ -468,16 +469,21 @@ bool GnuLdDriver::parse(int argc, const
       break;
     }

-    case OPT_start_group: {
-      std::unique_ptr<Group> group(new Group());
-      groupStack.push(group.get());
-      inputGraph->addInputElement(std::move(group));
+    case OPT_start_group:
+      groupStack.push(numfiles);
       break;
-    }

-    case OPT_end_group:
+    case OPT_end_group: {
+      if (groupStack.empty()) {
+        diagnostics << "stray --end-group\n";
+        return false;
+      }
+      int startGroupPos = groupStack.top();
+      inputGraph->addInputElement(
+          llvm::make_unique<GroupEnd>(numfiles - startGroupPos));
       groupStack.pop();
       break;
+    }

     case OPT_z: {
       StringRef extOpt = inputArg->getValue();
@@ -552,11 +558,8 @@ bool GnuLdDriver::parse(int argc, const
         }
       }
       std::unique_ptr<InputElement> inputFile(inputNode);
-      if (groupStack.empty()) {
-        inputGraph->addInputElement(std::move(inputFile));
-      } else {
-        groupStack.top()->addFile(std::move(inputFile));
-      }
+      ++numfiles;
+      inputGraph->addInputElement(std::move(inputFile));
       break;
     }


Modified: lld/trunk/lib/Driver/GnuLdInputGraph.cpp
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdInputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdInputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/lib/Driver/GnuLdInputGraph.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdInputGraph.cpp Wed Dec  3 19:09:06 2014
@@ -91,7 +91,7 @@ std::error_code ELFGNULdScript::parse(co
     auto *group = dyn_cast<script::Group>(c);
     if (!group)
       continue;
-    std::unique_ptr<Group> groupStart(new Group());
+    size_t numfiles = 0;
     for (const script::Path &path : group->getPaths()) {
       // TODO : Propagate Set WholeArchive/dashlPrefix
       attributes.setAsNeeded(path._asNeeded);
@@ -100,9 +100,10 @@ std::error_code ELFGNULdScript::parse(co
           _elfLinkingContext, _elfLinkingContext.allocateString(path._path),
           attributes);
       std::unique_ptr<InputElement> inputFile(inputNode);
-      groupStart.get()->addFile(std::move(inputFile));
+      _expandElements.push_back(std::move(inputFile));
+      ++numfiles;
     }
-    _expandElements.push_back(std::move(groupStart));
+    _expandElements.push_back(llvm::make_unique<GroupEnd>(numfiles));
   }
   return std::error_code();
 }

Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
+++ lld/trunk/lib/Driver/WinLinkDriver.cpp Wed Dec  3 19:09:06 2014
@@ -781,7 +781,7 @@ static bool hasLibrary(const PECOFFLinki
   ErrorOr<StringRef> path = fileNode->getPath(ctx);
   if (!path)
     return false;
-  for (std::unique_ptr<InputElement> &p : ctx.getLibraryGroup()->elements())
+  for (std::unique_ptr<InputElement> &p : ctx.getInputGraph().inputElements())
     if (auto *f = dyn_cast<FileNode>(p.get()))
       if (*path == *f->getPath(ctx))
         return true;
@@ -1397,10 +1397,8 @@ bool WinLinkDriver::parse(int argc, cons
     ctx.setEntryNode(entry.get());
     ctx.getInputGraph().addInputElement(std::move(entry));

-    // The container for all library files.
-    std::unique_ptr<Group> group(new PECOFFGroup(ctx));
-    ctx.setLibraryGroup(group.get());
-    ctx.getInputGraph().addInputElement(std::move(group));
+    // Add a group-end marker.
+    ctx.getInputGraph().addInputElement(llvm::make_unique<GroupEnd>(0));
   }

   // Add the library files to the library group.
@@ -1409,7 +1407,7 @@ bool WinLinkDriver::parse(int argc, cons
       if (isReadingDirectiveSection)
         if (lib->parse(ctx, diag))
           return false;
-      ctx.getLibraryGroup()->addFile(std::move(lib));
+      ctx.addLibraryFile(std::move(lib));
     }
   }


Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Wed Dec  3 19:09:06 2014
@@ -22,6 +22,7 @@
 #include "llvm/ADT/Triple.h"
 #include "llvm/Config/config.h"
 #include "llvm/Support/Errc.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/MachO.h"
 #include "llvm/Support/Path.h"
@@ -923,4 +924,35 @@ bool MachOLinkingContext::customAtomOrde
   return true;
 }

+static File *getFirstFile(const std::unique_ptr<InputElement> &elem) {
+  FileNode *e = dyn_cast<FileNode>(const_cast<InputElement *>(elem.get()));
+  if (!e || e->files().empty())
+    return nullptr;
+  return e->files()[0].get();
+}
+
+static bool isLibrary(const std::unique_ptr<InputElement> &elem) {
+  File *f = getFirstFile(elem);
+  return f && (isa<SharedLibraryFile>(f) || isa<ArchiveLibraryFile>(f));
+}
+
+// The darwin linker processes input files in two phases.  The first phase
+// links in all object (.o) files in command line order. The second phase
+// links in libraries in command line order.
+// In this function we reorder the input files so that all the object files
+// comes before any library file. We also make a group for the library files
+// so that the Resolver will reiterate over the libraries as long as we find
+// new undefines from libraries.
+void MachOLinkingContext::maybeSortInputFiles() {
+  std::vector<std::unique_ptr<InputElement>> &elements
+      = getInputGraph().inputElements();
+  std::stable_sort(elements.begin(), elements.end(),
+                   [](const std::unique_ptr<InputElement> &a,
+                      const std::unique_ptr<InputElement> &b) {
+                     return !isLibrary(a) && isLibrary(b);
+                   });
+  size_t numLibs = std::count_if(elements.begin(), elements.end(), isLibrary);
+  elements.push_back(llvm::make_unique<GroupEnd>(numLibs));
+}
+
 } // end namespace lld

Modified: lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp Wed Dec  3 19:09:06 2014
@@ -87,6 +87,23 @@ std::unique_ptr<File> PECOFFLinkingConte
       "<command line option /include>");
 }

+void PECOFFLinkingContext::addLibraryFile(std::unique_ptr<FileNode> file) {
+  GroupEnd *currentGroupEnd;
+  int pos = -1;
+  std::vector<std::unique_ptr<InputElement>> &elements
+      = getInputGraph().inputElements();
+  for (int i = 0, e = elements.size(); i < e; ++i) {
+    if ((currentGroupEnd = dyn_cast<GroupEnd>(elements[i].get()))) {
+      pos = i;
+      break;
+    }
+  }
+  assert(pos >= 0);
+  elements.insert(elements.begin() + pos, std::move(file));
+  elements[pos + 1] = llvm::make_unique<GroupEnd>(
+      currentGroupEnd->getSize() + 1);
+}
+
 bool PECOFFLinkingContext::createImplicitFiles(
     std::vector<std::unique_ptr<File>> &) {
   // Create a file for __ImageBase.
@@ -109,7 +126,7 @@ bool PECOFFLinkingContext::createImplici
   auto exportNode = llvm::make_unique<SimpleFileNode>("<export>");
   exportNode->appendInputFile(
       llvm::make_unique<pecoff::ExportedSymbolRenameFile>(*this, syms));
-  getLibraryGroup()->addFile(std::move(exportNode));
+  addLibraryFile(std::move(exportNode));

   // Create a file for the entry point function.
   getEntryNode()->appendInputFile(

Modified: lld/trunk/unittests/DriverTests/DriverTest.h
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/DriverTest.h?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/DriverTest.h?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/unittests/DriverTests/DriverTest.h (original)
+++ lld/trunk/unittests/DriverTests/DriverTest.h Wed Dec  3 19:09:06 2014
@@ -37,18 +37,6 @@ protected:
     llvm_unreachable("not handling other types of input files");
   }

-  // Convenience method for getting i'th input files name.
-  std::string inputFile(int index1, int index2) {
-    Group *group = dyn_cast<Group>(
-        linkingContext()->getInputGraph().inputElements()[index1].get());
-    if (!group)
-      llvm_unreachable("not handling other types of input files");
-    FileNode *file = dyn_cast<FileNode>(group->elements()[index2].get());
-    if (!file)
-      llvm_unreachable("not handling other types of input files");
-    return *file->getPath(*linkingContext());
-  }
-
   // For unit tests to call driver with various command lines.
   bool parse(const char *args, ...) {
     // Construct command line options from varargs.

Modified: lld/trunk/unittests/DriverTests/InputGraphTest.cpp
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/InputGraphTest.cpp?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/InputGraphTest.cpp?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/unittests/DriverTests/InputGraphTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/InputGraphTest.cpp Wed Dec  3 19:09:06 2014
@@ -77,7 +77,7 @@ protected:

 } // end anonymous namespace

-static std::unique_ptr<TestFileNode> createFile1(StringRef name) {
+static std::unique_ptr<TestFileNode> createFile(StringRef name) {
   std::vector<std::unique_ptr<File>> files;
   files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name)));
   std::unique_ptr<TestFileNode> file(new TestFileNode("filenode"));
@@ -85,109 +85,30 @@ static std::unique_ptr<TestFileNode> cre
   return file;
 }

-static std::unique_ptr<TestFileNode> createFile2(StringRef name1,
-                                                 StringRef name2) {
-  std::vector<std::unique_ptr<File>> files;
-  files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name1)));
-  files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name2)));
-  std::unique_ptr<TestFileNode> file(new TestFileNode("filenode"));
-  file->addFiles(std::move(files));
-  return file;
-}
-
 TEST_F(InputGraphTest, Empty) {
   expectEnd();
 }

 TEST_F(InputGraphTest, File) {
-  _graph->addInputElement(createFile1("file1"));
-  EXPECT_EQ("file1", getNext());
-  expectEnd();
-}
-
-TEST_F(InputGraphTest, Files) {
-  _graph->addInputElement(createFile2("file1", "file2"));
-  EXPECT_EQ("file1", getNext());
-  EXPECT_EQ("file2", getNext());
-  expectEnd();
-}
-
-TEST_F(InputGraphTest, Group) {
-  _graph->addInputElement(createFile2("file1", "file2"));
-
-  std::unique_ptr<Group> group(new Group());
-  group->addFile(createFile2("file3", "file4"));
-  group->addFile(createFile1("file5"));
-  group->addFile(createFile1("file6"));
-  _graph->addInputElement(std::move(group));
-
+  _graph->addInputElement(createFile("file1"));
   EXPECT_EQ("file1", getNext());
-  EXPECT_EQ("file2", getNext());
-  EXPECT_EQ("file3", getNext());
-  EXPECT_EQ("file4", getNext());
-  EXPECT_EQ("file5", getNext());
-  EXPECT_EQ("file6", getNext());
-  expectEnd();
-}
-
-// Iterate through the group
-TEST_F(InputGraphTest, GroupIteration) {
-  _graph->addInputElement(createFile2("file1", "file2"));
-
-  std::unique_ptr<Group> group(new Group());
-  group->addFile(createFile2("file3", "file4"));
-  group->addFile(createFile1("file5"));
-  group->addFile(createFile1("file6"));
-  _graph->addInputElement(std::move(group));
-
-  EXPECT_EQ("file1", getNext());
-  EXPECT_EQ("file2", getNext());
-
-  EXPECT_EQ("file3", getNext());
-  EXPECT_EQ("file4", getNext());
-  EXPECT_EQ("file5", getNext());
-  EXPECT_EQ("file6", getNext());
-  _graph->notifyProgress();
-
-  EXPECT_EQ("file3", getNext());
-  EXPECT_EQ("file4", getNext());
-  _graph->notifyProgress();
-  EXPECT_EQ("file5", getNext());
-  EXPECT_EQ("file6", getNext());
-
-  EXPECT_EQ("file3", getNext());
-  EXPECT_EQ("file4", getNext());
-  EXPECT_EQ("file5", getNext());
-  EXPECT_EQ("file6", getNext());
   expectEnd();
 }

 // Node expansion tests
 TEST_F(InputGraphTest, Normalize) {
-  _graph->addInputElement(createFile2("file1", "file2"));
+  _graph->addInputElement(createFile("file1"));

   std::unique_ptr<TestExpandFileNode> expandFile(
       new TestExpandFileNode("node"));
-  expandFile->addElement(createFile1("file3"));
-  expandFile->addElement(createFile1("file4"));
+  expandFile->addElement(createFile("file2"));
+  expandFile->addElement(createFile("file3"));
   _graph->addInputElement(std::move(expandFile));
-
-  std::unique_ptr<Group> group(new Group());
-  std::unique_ptr<TestExpandFileNode> expandFile2(
-      new TestExpandFileNode("node"));
-  expandFile2->addElement(createFile1("file5"));
-  group->addFile(std::move(expandFile2));
-  _graph->addInputElement(std::move(group));
-
-  _graph->addInputElement(createFile1("file6"));
   _graph->normalize();

   EXPECT_EQ("file1", getNext());
   EXPECT_EQ("file2", getNext());
   EXPECT_EQ("file3", getNext());
-  EXPECT_EQ("file4", getNext());
-  EXPECT_EQ("file5", getNext());
-  EXPECT_EQ("file6", getNext());
   expectEnd();
 }

@@ -195,8 +116,8 @@ TEST_F(InputGraphTest, Observer) {
   std::vector<std::string> files;
   _graph->registerObserver([&](File *file) { files.push_back(file->path()); });

-  _graph->addInputElement(createFile1("file1"));
-  _graph->addInputElement(createFile1("file2"));
+  _graph->addInputElement(createFile("file1"));
+  _graph->addInputElement(createFile("file2"));
   EXPECT_EQ("file1", getNext());
   EXPECT_EQ("file2", getNext());
   expectEnd();

Modified: lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp
URL: <a class="moz-txt-link-freetext" href="http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=223330&r1=223329&r2=223330&view=diff">http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=223330&r1=223329&r2=223330&view=diff</a>
==============================================================================
--- lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp Wed Dec  3 19:09:06 2014
@@ -137,11 +137,11 @@ TEST_F(WinLinkParserTest, Libpath) {
 TEST_F(WinLinkParserTest, InputOrder) {
   EXPECT_TRUE(parse("link.exe", "a.lib", "b.obj", "c.obj", "a.lib", "d.obj",
                     nullptr));
-  EXPECT_EQ(5, inputFileCount());
+  EXPECT_EQ(6, inputFileCount());
   EXPECT_EQ("b.obj", inputFile(0));
   EXPECT_EQ("c.obj", inputFile(1));
   EXPECT_EQ("d.obj", inputFile(2));
-  EXPECT_EQ("a.lib", inputFile(4, 0));
+  EXPECT_EQ("a.lib", inputFile(4));
 }

 //
@@ -393,36 +393,36 @@ TEST_F(WinLinkParserTest, SectionMultipl
 TEST_F(WinLinkParserTest, DefaultLib) {
   EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
                     "/defaultlib:kernel32", "a.obj", nullptr));
-  EXPECT_EQ(3, inputFileCount());
+  EXPECT_EQ(5, inputFileCount());
   EXPECT_EQ("a.obj", inputFile(0));
-  EXPECT_EQ("user32.lib", inputFile(2, 0));
-  EXPECT_EQ("kernel32.lib", inputFile(2, 1));
+  EXPECT_EQ("user32.lib", inputFile(2));
+  EXPECT_EQ("kernel32.lib", inputFile(3));
 }

 TEST_F(WinLinkParserTest, DefaultLibDuplicates) {
   EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
                     "/defaultlib:user32.lib", "a.obj", nullptr));
-  EXPECT_EQ(3, inputFileCount());
+  EXPECT_EQ(4, inputFileCount());
   EXPECT_EQ("a.obj", inputFile(0));
-  EXPECT_EQ("user32.lib", inputFile(2, 0));
+  EXPECT_EQ("user32.lib", inputFile(2));
 }

 TEST_F(WinLinkParserTest, NoDefaultLib) {
   EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
                     "/defaultlib:kernel32", "/nodefaultlib:user32.lib", "a.obj",
                     nullptr));
-  EXPECT_EQ(3, inputFileCount());
+  EXPECT_EQ(4, inputFileCount());
   EXPECT_EQ("a.obj", inputFile(0));
-  EXPECT_EQ("kernel32.lib", inputFile(2, 0));
+  EXPECT_EQ("kernel32.lib", inputFile(2));
 }

 TEST_F(WinLinkParserTest, NoDefaultLibCase) {
   EXPECT_TRUE(parse("link.exe", "/defaultlib:user32",
                     "/defaultlib:kernel32", "/nodefaultlib:USER32.LIB", "a.obj",
                     nullptr));
-  EXPECT_EQ(3, inputFileCount());
+  EXPECT_EQ(4, inputFileCount());
   EXPECT_EQ("a.obj", inputFile(0));
-  EXPECT_EQ("kernel32.lib", inputFile(2, 0));
+  EXPECT_EQ("kernel32.lib", inputFile(2));
 }

 TEST_F(WinLinkParserTest, NoDefaultLibAll) {
@@ -436,9 +436,9 @@ TEST_F(WinLinkParserTest, DisallowLib) {
   EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
                     "/defaultlib:kernel32", "/disallowlib:user32.lib", "a.obj",
                     nullptr));
-  EXPECT_EQ(3, inputFileCount());
+  EXPECT_EQ(4, inputFileCount());
   EXPECT_EQ("a.obj", inputFile(0));
-  EXPECT_EQ("kernel32.lib", inputFile(2, 0));
+  EXPECT_EQ("kernel32.lib", inputFile(2));
 }

 //


_______________________________________________
llvm-commits mailing <a class="moz-txt-link-abbreviated" href="mailto:listllvm-commits@cs.uiuc.eduhttp://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits">listllvm-commits@cs.uiuc.eduhttp://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a>



--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation


</pre>
      </blockquote>
      <pre wrap="">
</pre>
    </blockquote>
    <br>
    <br>
    <pre class="moz-signature" cols="72">-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation</pre>
  </body>
</html>