<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""></div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">Le 9 déc. 2014 à 01:43, Rui Ueyama <<a href="mailto:ruiu@google.com" class="">ruiu@google.com</a>> a écrit :</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">I'm still getting the same error even though I removed -dead_strip from the command line. Hmm, what's wrong...? Does it work for you?</div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Mon, Dec 8, 2014 at 10:33 PM, Jean-Daniel Dupas <span dir="ltr" class=""><<a href="mailto:dev@xenonium.com" target="_blank" class="">dev@xenonium.com</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="">AFAIK, this is a bug that occurs when dead_strip is enabled. Try to remove the -dead_strip argument and try again.<div class=""><br class=""></div><div class=""><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">Le 8 déc. 2014 à 08:15, Rui Ueyama <<a href="mailto:ruiu@google.com" target="_blank" class="">ruiu@google.com</a>> a écrit :</div><div class=""><div class="h5"><br class=""><div class=""><div dir="ltr" class="">I'm having trouble to link LLD using LLD on Darwin. Could you help me figure out what's wrong?<div class=""><br class=""></div><div class="">LLD aborts with the following error message</div><blockquote style="margin:0 0 0 40px;border:none;padding:0px" class=""><div class=""><p class=""><span class="">warning: ignoring unknown argument: -search_paths_first<br class=""></span>warning: ignoring unknown argument: -headerpad_max_install_names<br class="">Failed to write file 'bin/lld': Exec format error</p></div></blockquote><div class="">







<div class="">when I try to link LLD with the following command (../ld is stage 1 LLD executable)</div></div><div class=""><br class=""></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px" class=""><div class=""><div class="">$ ../ld "-demangle" "-dynamic" "-arch" "x86_64" "-macosx_version_min" "10.10.0" "-o" bin/lld "-search_paths_first" "-headerpad_max_install_names" "-dead_strip" "tools/lld/tools/lld/CMakeFiles/lld.dir/lld.cpp.o" "lib/liblldDriver.a" "lib/liblldPECOFF.a" "lib/liblldDriver.a" "lib/liblldPECOFF.a" "lib/liblldConfig.a" "lib/liblldMachO.a" "lib/liblldELF.a" "lib/liblldHexagonELFTarget.a" "lib/liblldMipsELFTarget.a" "lib/liblldPPCELFTarget.a" "lib/liblldX86ELFTarget.a" "lib/liblldX86_64ELFTarget.a" "lib/liblldAArch64ELFTarget.a" "lib/libLLVMOption.a" "lib/liblldPasses.a" "lib/liblldCore.a" "lib/liblldNative.a" "lib/liblldReaderWriter.a" "lib/liblldYAML.a" "lib/liblldPasses.a" "lib/liblldCore.a" "lib/liblldNative.a" "lib/liblldReaderWriter.a" "lib/liblldYAML.a" "lib/libLLVMObject.a" "lib/libLLVMBitReader.a" "lib/libLLVMCore.a" "lib/libLLVMMCParser.a" "lib/libLLVMMC.a" "lib/libLLVMSupport.a" "-lcurses" "-lpthread" "-lz" "-lm" "-lc++" "-lSystem" "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.0/lib/darwin/libclang_rt.osx.a"</div></div></blockquote><br class=""><div class="">I got this command line by passing -### to Clang. I'm using the latest version of Xcode. LLVM/LLD is at head with no local patch (including this one).</div><div class=""><br class=""></div><div class="">Nick said that the LLD is now able to self-host it on Darwin. Is it still working?</div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Fri, Dec 5, 2014 at 12:11 AM, Jean-Daniel Dupas <span dir="ltr" class=""><<a href="mailto:dev@xenonium.com" target="_blank" class="">dev@xenonium.com</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I think that change broke the Darwin linker.<br class="">
<br class="">
When trying to link executable using lld, I know have a lot of ‘undefined symbol’ error for symbols provided by (static) libraries.<br class="">
<br class="">
> Le 4 déc. 2014 à 02:09, Rui Ueyama <<a href="mailto:ruiu@google.com" target="_blank" class="">ruiu@google.com</a>> a écrit :<br class="">
<div class=""><div class="">><br class="">
> Author: ruiu<br class="">
> Date: Wed Dec  3 19:09:06 2014<br class="">
> New Revision: 223330<br class="">
><br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=223330&view=rev" target="_blank" class="">http://llvm.org/viewvc/llvm-project?rev=223330&view=rev</a><br class="">
> Log:<br class="">
> Rewrite InputGraph's Group<br class="">
><br class="">
> The aim of this patch is to reduce the excessive abstraction from<br class="">
> the InputGraph. We found that even a simple thing, such as sorting<br class="">
> input files (Mach-O) or adding a new file to the input file list<br class="">
> (PE/COFF), is nearly impossible with the InputGraph abstraction,<br class="">
> because it hides too much information behind it. As a result,<br class="">
> we invented complex interactions between components (e.g.<br class="">
> notifyProgress() mechanism) and tricky code to work around that<br class="">
> limitation. There were many occasions that we needed to write<br class="">
> awkward code.<br class="">
><br class="">
> This patch is a first step to make it cleaner. As a first step,<br class="">
> this removes Group class from the InputGraph. The grouping feature<br class="">
> is now directly handled by the Resolver. notifyProgress is removed<br class="">
> since we no longer need that. I could have cleaned it up even more,<br class="">
> but in order to keep the patch minimum, I focused on Group.<br class="">
><br class="">
> SimpleFileNode class, a container of File objects, is now limited<br class="">
> to have only one File. We shold have done this earlier.<br class="">
> We used to allow putting multiple File objects to FileNode.<br class="">
> Although SimpleFileNode usually has only one file, the Driver class<br class="">
> actually used that capability. I modified the Driver class a bit,<br class="">
> so that one FileNode is created for each input File.<br class="">
><br class="">
> We should now probably remove SimpleFileNode and directly store<br class="">
> File objects to the InputGraph in some way, because a container<br class="">
> that can contain only one object is useless. This is a TODO.<br class="">
><br class="">
> Mach-O input files are now sorted before they are passe to the<br class="">
> Resolver. DarwinInputGraph class is no longer needed, so removed.<br class="">
><br class="">
> PECOFF still has hacky code to add a new file to the input file list.<br class="">
> This will be cleaned up in another patch.<br class="">
><br class="">
> Modified:<br class="">
>    lld/trunk/include/lld/Core/InputGraph.h<br class="">
>    lld/trunk/include/lld/Core/LinkingContext.h<br class="">
>    lld/trunk/include/lld/Core/Resolver.h<br class="">
>    lld/trunk/include/lld/Driver/DarwinInputGraph.h<br class="">
>    lld/trunk/include/lld/Driver/WinLinkInputGraph.h<br class="">
>    lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h<br class="">
>    lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h<br class="">
>    lld/trunk/lib/Core/InputGraph.cpp<br class="">
>    lld/trunk/lib/Core/Resolver.cpp<br class="">
>    lld/trunk/lib/Driver/DarwinInputGraph.cpp<br class="">
>    lld/trunk/lib/Driver/DarwinLdDriver.cpp<br class="">
>    lld/trunk/lib/Driver/Driver.cpp<br class="">
>    lld/trunk/lib/Driver/GnuLdDriver.cpp<br class="">
>    lld/trunk/lib/Driver/GnuLdInputGraph.cpp<br class="">
>    lld/trunk/lib/Driver/WinLinkDriver.cpp<br class="">
>    lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp<br class="">
>    lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp<br class="">
>    lld/trunk/unittests/DriverTests/DriverTest.h<br class="">
>    lld/trunk/unittests/DriverTests/InputGraphTest.cpp<br class="">
>    lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp<br class="">
><br class="">
> Modified: lld/trunk/include/lld/Core/InputGraph.h<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputGraph.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputGraph.h?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/include/lld/Core/InputGraph.h (original)<br class="">
> +++ lld/trunk/include/lld/Core/InputGraph.h Wed Dec  3 19:09:06 2014<br class="">
> @@ -59,12 +59,6 @@ public:<br class="">
>   /// assigned in the way files are resolved.<br class="">
>   virtual ErrorOr<File &> getNextFile();<br class="">
><br class="">
> -  /// Notifies the current input element of Resolver made some progress on<br class="">
> -  /// resolving undefined symbols using the current file. Group (representing<br class="">
> -  /// --start-group and --end-group) uses that notification to make a decision<br class="">
> -  /// whether it should iterate over again or terminate or not.<br class="">
> -  virtual void notifyProgress();<br class="">
> -<br class="">
>   /// Adds an observer of getNextFile(). Each time a new file is about to be<br class="">
>   /// returned from getNextFile(), registered observers are called with the file<br class="">
>   /// being returned.<br class="">
> @@ -76,14 +70,18 @@ public:<br class="">
>   /// \brief Adds a node at the beginning of the InputGraph<br class="">
>   void addInputElementFront(std::unique_ptr<InputElement>);<br class="">
><br class="">
> -  /// Normalize the InputGraph. It calls expand() on each node and then replace<br class="">
> -  /// it with getReplacements() results.<br class="">
> +  /// Normalize the InputGraph. It calls getReplacements() on each element.<br class="">
>   void normalize();<br class="">
><br class="">
> -  range<InputElementIterT> inputElements() {<br class="">
> -    return make_range(_inputArgs.begin(), _inputArgs.end());<br class="">
> +  InputElementVectorT &inputElements() {<br class="">
> +    return _inputArgs;<br class="">
>   }<br class="">
><br class="">
> +  // Returns the current group size if we are at an --end-group.<br class="">
> +  // Otherwise returns 0.<br class="">
> +  int getGroupSize();<br class="">
> +  void skipGroup();<br class="">
> +<br class="">
>   // \brief Returns the number of input files.<br class="">
>   size_t size() const { return _inputArgs.size(); }<br class="">
><br class="">
> @@ -108,8 +106,8 @@ class InputElement {<br class="">
> public:<br class="">
>   /// Each input element in the graph can be a File or a control<br class="">
>   enum class Kind : uint8_t {<br class="">
> -    Group,      // Represents a type associated with Group<br class="">
> -    File        // Represents a type associated with File Nodes<br class="">
> +    File,       // Represents a type associated with File Nodes<br class="">
> +    GroupEnd,<br class="">
>   };<br class="">
><br class="">
>   InputElement(Kind type) : _kind(type) {}<br class="">
> @@ -129,16 +127,9 @@ public:<br class="">
>   /// Get the next file to be processed by the resolver<br class="">
>   virtual ErrorOr<File &> getNextFile() = 0;<br class="">
><br class="">
> -  /// Refer InputGraph::notifyProgress(). By default, it does nothing. Only<br class="">
> -  /// Group is interested in this message.<br class="">
> -  virtual void notifyProgress() {};<br class="">
> -<br class="">
>   /// \brief Reset the next index<br class="">
>   virtual void resetNextIndex() = 0;<br class="">
><br class="">
> -  /// Returns true if we want to replace this node with children.<br class="">
> -  virtual void expand() {}<br class="">
> -<br class="">
>   /// Get the elements that we want to expand with.<br class="">
>   virtual bool getReplacements(InputGraph::InputElementVectorT &) {<br class="">
>     return false;<br class="">
> @@ -148,73 +139,31 @@ protected:<br class="">
>   Kind _kind; // The type of the Element<br class="">
> };<br class="">
><br class="">
> -/// \brief A Control node which contains a group of InputElements<br class="">
> -/// This affects the resolver so that it resolves undefined symbols<br class="">
> -/// in the group completely before looking at other input files that<br class="">
> -/// follow the group<br class="">
> -class Group : public InputElement {<br class="">
> +// This is a marker for --end-group. getSize() returns the number of<br class="">
> +// files between the corresponding --start-group and this marker.<br class="">
> +class GroupEnd : public InputElement {<br class="">
> public:<br class="">
> -  Group()<br class="">
> -      : InputElement(InputElement::Kind::Group), _currentElementIndex(0),<br class="">
> -        _nextElementIndex(0), _madeProgress(false) {}<br class="">
> +  GroupEnd(int size) : InputElement(Kind::GroupEnd), _size(size) {}<br class="">
><br class="">
> -  static inline bool classof(const InputElement *a) {<br class="">
> -    return a->kind() == InputElement::Kind::Group;<br class="">
> -  }<br class="">
> -<br class="">
> -  /// \brief Process input element and add it to the group<br class="">
> -  bool addFile(std::unique_ptr<InputElement> element) {<br class="">
> -    _elements.push_back(std::move(element));<br class="">
> -    return true;<br class="">
> -  }<br class="">
> +  int getSize() const { return _size; }<br class="">
><br class="">
> -  range<InputGraph::InputElementIterT> elements() {<br class="">
> -    return make_range(_elements.begin(), _elements.end());<br class="">
> -  }<br class="">
> -<br class="">
> -  void resetNextIndex() override {<br class="">
> -    _madeProgress = false;<br class="">
> -    _currentElementIndex = 0;<br class="">
> -    _nextElementIndex = 0;<br class="">
> -    for (std::unique_ptr<InputElement> &elem : _elements)<br class="">
> -      elem->resetNextIndex();<br class="">
> +  static inline bool classof(const InputElement *a) {<br class="">
> +    return a->kind() == Kind::GroupEnd;<br class="">
>   }<br class="">
><br class="">
>   /// \brief Parse the group members.<br class="">
>   std::error_code parse(const LinkingContext &ctx, raw_ostream &diag) override {<br class="">
> -    for (std::unique_ptr<InputElement> &ei : _elements)<br class="">
> -      if (std::error_code ec = ei->parse(ctx, diag))<br class="">
> -        return ec;<br class="">
>     return std::error_code();<br class="">
>   }<br class="">
><br class="">
> -  /// If Resolver made a progress using the current file, it's ok to revisit<br class="">
> -  /// files in this group in future.<br class="">
> -  void notifyProgress() override {<br class="">
> -    for (std::unique_ptr<InputElement> &elem : _elements)<br class="">
> -      elem->notifyProgress();<br class="">
> -    _madeProgress = true;<br class="">
> -  }<br class="">
> -<br class="">
> -  ErrorOr<File &> getNextFile() override;<br class="">
> -<br class="">
> -  void expand() override {<br class="">
> -    for (std::unique_ptr<InputElement> &elt : _elements)<br class="">
> -      elt->expand();<br class="">
> -    std::vector<std::unique_ptr<InputElement>> result;<br class="">
> -    for (std::unique_ptr<InputElement> &elt : _elements) {<br class="">
> -      if (elt->getReplacements(result))<br class="">
> -        continue;<br class="">
> -      result.push_back(std::move(elt));<br class="">
> -    }<br class="">
> -    _elements.swap(result);<br class="">
> +  ErrorOr<File &> getNextFile() override {<br class="">
> +    llvm_unreachable("shouldn't be here.");<br class="">
>   }<br class="">
><br class="">
> -protected:<br class="">
> -  InputGraph::InputElementVectorT _elements;<br class="">
> -  uint32_t _currentElementIndex;<br class="">
> -  uint32_t _nextElementIndex;<br class="">
> -  bool _madeProgress;<br class="">
> +  void resetNextIndex() override {}<br class="">
> +<br class="">
> +private:<br class="">
> +  int _size;<br class="">
> };<br class="">
><br class="">
> /// \brief Represents an Input file in the graph<br class="">
> @@ -252,6 +201,8 @@ public:<br class="">
><br class="">
>   /// \brief add a file to the list of files<br class="">
>   virtual void addFiles(InputGraph::FileVectorT files) {<br class="">
> +    assert(files.size() == 1);<br class="">
> +    assert(_files.empty());<br class="">
>     for (std::unique_ptr<File> &ai : files)<br class="">
>       _files.push_back(std::move(ai));<br class="">
>   }<br class="">
> @@ -260,6 +211,8 @@ public:<br class="">
>   /// the node again.<br class="">
>   void resetNextIndex() override { _nextFileIndex = 0; }<br class="">
><br class="">
> +  bool getReplacements(InputGraph::InputElementVectorT &result) override;<br class="">
> +<br class="">
> protected:<br class="">
>   /// \brief Read the file into _buffer.<br class="">
>   std::error_code getBuffer(StringRef filePath);<br class="">
> @@ -276,6 +229,10 @@ protected:<br class="">
> class SimpleFileNode : public FileNode {<br class="">
> public:<br class="">
>   SimpleFileNode(StringRef path) : FileNode(path) {}<br class="">
> +  SimpleFileNode(StringRef path, std::unique_ptr<File> f)<br class="">
> +      : FileNode(path) {<br class="">
> +    _files.push_back(std::move(f));<br class="">
> +  }<br class="">
><br class="">
>   virtual ~SimpleFileNode() {}<br class="">
><br class="">
><br class="">
> Modified: lld/trunk/include/lld/Core/LinkingContext.h<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/LinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/LinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/include/lld/Core/LinkingContext.h (original)<br class="">
> +++ lld/trunk/include/lld/Core/LinkingContext.h Wed Dec  3 19:09:06 2014<br class="">
> @@ -322,6 +322,10 @@ public:<br class="">
>   bool runRoundTripPass() const { return _runRoundTripPasses; }<br class="">
> #endif<br class="">
><br class="">
> +  // This function is called just before the Resolver kicks in.<br class="">
> +  // Derived classes may use that chance to rearrange the input files.<br class="">
> +  virtual void maybeSortInputFiles() {}<br class="">
> +<br class="">
>   /// @}<br class="">
> protected:<br class="">
>   LinkingContext(); // Must be subclassed<br class="">
><br class="">
> Modified: lld/trunk/include/lld/Core/Resolver.h<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/include/lld/Core/Resolver.h (original)<br class="">
> +++ lld/trunk/include/lld/Core/Resolver.h Wed Dec  3 19:09:06 2014<br class="">
> @@ -28,7 +28,8 @@ class LinkingContext;<br class="">
> class Resolver {<br class="">
> public:<br class="">
>   Resolver(LinkingContext &context)<br class="">
> -      : _context(context), _symbolTable(context), _result(new MergedFile()) {}<br class="">
> +      : _context(context), _symbolTable(context), _result(new MergedFile()),<br class="">
> +        _fileIndex(0) {}<br class="">
><br class="">
>   // InputFiles::Handler methods<br class="">
>   void doDefinedAtom(const DefinedAtom&);<br class="">
> @@ -38,10 +39,10 @@ public:<br class="">
><br class="">
>   // Handle files, this adds atoms from the current file thats<br class="">
>   // being processed by the resolver<br class="">
> -  void handleFile(const File &);<br class="">
> +  bool handleFile(const File &);<br class="">
><br class="">
>   // Handle an archive library file.<br class="">
> -  void handleArchiveFile(const File &);<br class="">
> +  bool handleArchiveFile(const File &);<br class="">
><br class="">
>   // Handle a shared library file.<br class="">
>   void handleSharedLibrary(const File &);<br class="">
> @@ -54,6 +55,9 @@ public:<br class="">
> private:<br class="">
>   typedef std::function<void(StringRef, bool)> UndefCallback;<br class="">
><br class="">
> +  bool undefinesAdded(int count);<br class="">
> +  ErrorOr<File &> nextFile(bool &inGroup);<br class="">
> +<br class="">
>   /// \brief Add section group/.gnu.linkonce if it does not exist previously.<br class="">
>   void maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom);<br class="">
><br class="">
> @@ -110,6 +114,11 @@ private:<br class="">
>   llvm::DenseSet<const Atom *>  _deadAtoms;<br class="">
>   std::unique_ptr<MergedFile>   _result;<br class="">
>   llvm::DenseMap<const Atom *, llvm::DenseSet<const Atom *>> _reverseRef;<br class="">
> +<br class="">
> +  // --start-group and --end-group<br class="">
> +  std::vector<File *> _files;<br class="">
> +  std::map<File *, bool> _newUndefinesAdded;<br class="">
> +  size_t _fileIndex;<br class="">
> };<br class="">
><br class="">
> } // namespace lld<br class="">
><br class="">
> Modified: lld/trunk/include/lld/Driver/DarwinInputGraph.h<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/DarwinInputGraph.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/DarwinInputGraph.h?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/include/lld/Driver/DarwinInputGraph.h (original)<br class="">
> +++ lld/trunk/include/lld/Driver/DarwinInputGraph.h Wed Dec  3 19:09:06 2014<br class="">
> @@ -23,18 +23,6 @@<br class="">
><br class="">
> namespace lld {<br class="">
><br class="">
> -<br class="">
> -class DarwinInputGraph : public InputGraph {<br class="">
> -public:<br class="">
> -  DarwinInputGraph() : _librariesPhase(false), _repeatLibraries(false) { }<br class="">
> -  ErrorOr<File &> getNextFile() override;<br class="">
> -  void notifyProgress() override;<br class="">
> -private:<br class="">
> -  bool _librariesPhase;<br class="">
> -  bool _repeatLibraries;<br class="">
> -};<br class="">
> -<br class="">
> -<br class="">
> /// \brief Represents a MachO File<br class="">
> class MachOFileNode : public FileNode {<br class="">
> public:<br class="">
><br class="">
> Modified: lld/trunk/include/lld/Driver/WinLinkInputGraph.h<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/WinLinkInputGraph.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/WinLinkInputGraph.h?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/include/lld/Driver/WinLinkInputGraph.h (original)<br class="">
> +++ lld/trunk/include/lld/Driver/WinLinkInputGraph.h Wed Dec  3 19:09:06 2014<br class="">
> @@ -55,21 +55,6 @@ public:<br class="">
>   ErrorOr<StringRef> getPath(const LinkingContext &ctx) const override;<br class="">
> };<br class="">
><br class="">
> -/// \brief Represents a ELF control node<br class="">
> -class PECOFFGroup : public Group {<br class="">
> -public:<br class="">
> -  PECOFFGroup(PECOFFLinkingContext &ctx) : Group(), _ctx(ctx) {}<br class="">
> -<br class="">
> -  /// \brief Parse the group members.<br class="">
> -  std::error_code parse(const LinkingContext &ctx, raw_ostream &diag) override {<br class="">
> -    std::lock_guard<std::recursive_mutex> lock(_ctx.getMutex());<br class="">
> -    return Group::parse(ctx, diag);<br class="">
> -  }<br class="">
> -<br class="">
> -private:<br class="">
> -  PECOFFLinkingContext &_ctx;<br class="">
> -};<br class="">
> -<br class="">
> } // namespace lld<br class="">
><br class="">
> #endif<br class="">
><br class="">
> Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)<br class="">
> +++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Wed Dec  3 19:09:06 2014<br class="">
> @@ -283,6 +283,8 @@ public:<br class="">
>   /// bits are xxxx.yy.zz.  Largest number is 65535.255.255<br class="">
>   static bool parsePackedVersion(StringRef str, uint32_t &result);<br class="">
><br class="">
> +  void maybeSortInputFiles() override;<br class="">
> +<br class="">
> private:<br class="">
>   Writer &writer() const override;<br class="">
>   mach_o::MachODylibFile* loadIndirectDylib(StringRef path);<br class="">
><br class="">
> Modified: lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h (original)<br class="">
> +++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Wed Dec  3 19:09:06 2014<br class="">
> @@ -29,7 +29,6 @@ using llvm::COFF::WindowsSubsystem;<br class="">
> static const uint8_t DEFAULT_DOS_STUB[128] = {'M', 'Z'};<br class="">
><br class="">
> namespace lld {<br class="">
> -class Group;<br class="">
><br class="">
> class PECOFFLinkingContext : public LinkingContext {<br class="">
> public:<br class="">
> @@ -315,8 +314,7 @@ public:<br class="">
>   void setEntryNode(SimpleFileNode *node) { _entryNode = node; }<br class="">
>   SimpleFileNode *getEntryNode() const { return _entryNode; }<br class="">
><br class="">
> -  void setLibraryGroup(Group *group) { _libraryGroup = group; }<br class="">
> -  Group *getLibraryGroup() const { return _libraryGroup; }<br class="">
> +  void addLibraryFile(std::unique_ptr<FileNode> file);<br class="">
><br class="">
>   void setModuleDefinitionFile(const std::string val) {<br class="">
>     _moduleDefinitionFile = val;<br class="">
> @@ -438,9 +436,6 @@ private:<br class="">
>   // The node containing the entry point file.<br class="">
>   SimpleFileNode *_entryNode;<br class="">
><br class="">
> -  // The PECOFFGroup that contains all the .lib files.<br class="">
> -  Group *_libraryGroup;<br class="">
> -<br class="">
>   // Name of the temporary file for lib.exe subcommand. For debugging<br class="">
>   // only.<br class="">
>   std::string _moduleDefinitionFile;<br class="">
><br class="">
> Modified: lld/trunk/lib/Core/InputGraph.cpp<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/lib/Core/InputGraph.cpp (original)<br class="">
> +++ lld/trunk/lib/Core/InputGraph.cpp Wed Dec  3 19:09:06 2014<br class="">
> @@ -36,8 +36,6 @@ ErrorOr<File &> InputGraph::getNextFile(<br class="">
>   }<br class="">
> }<br class="">
><br class="">
> -void InputGraph::notifyProgress() { _currentInputElement->notifyProgress(); }<br class="">
> -<br class="">
> void InputGraph::registerObserver(std::function<void(File *)> fn) {<br class="">
>   _observers.push_back(fn);<br class="">
> }<br class="">
> @@ -61,12 +59,13 @@ bool InputGraph::dump(raw_ostream &diagn<br class="">
> ErrorOr<InputElement *> InputGraph::getNextInputElement() {<br class="">
>   if (_nextElementIndex >= _inputArgs.size())<br class="">
>     return make_error_code(InputGraphError::no_more_elements);<br class="">
> -  return _inputArgs[_nextElementIndex++].get();<br class="">
> +  InputElement *elem = _inputArgs[_nextElementIndex++].get();<br class="">
> +  if (isa<GroupEnd>(elem))<br class="">
> +    return getNextInputElement();<br class="">
> +  return elem;<br class="">
> }<br class="">
><br class="">
> void InputGraph::normalize() {<br class="">
> -  for (std::unique_ptr<InputElement> &elt : _inputArgs)<br class="">
> -    elt->expand();<br class="">
>   std::vector<std::unique_ptr<InputElement>> vec;<br class="">
>   for (std::unique_ptr<InputElement> &elt : _inputArgs) {<br class="">
>     if (elt->getReplacements(vec))<br class="">
> @@ -76,6 +75,25 @@ void InputGraph::normalize() {<br class="">
>   _inputArgs = std::move(vec);<br class="">
> }<br class="">
><br class="">
> +// If we are at the end of a group, return its size (which indicates<br class="">
> +// how many files we need to go back in the command line).<br class="">
> +// Returns 0 if we are not at the end of a group.<br class="">
> +int InputGraph::getGroupSize() {<br class="">
> +  if (_nextElementIndex >= _inputArgs.size())<br class="">
> +    return 0;<br class="">
> +  InputElement *elem = _inputArgs[_nextElementIndex].get();<br class="">
> +  if (const GroupEnd *group = dyn_cast<GroupEnd>(elem))<br class="">
> +    return group->getSize();<br class="">
> +  return 0;<br class="">
> +}<br class="">
> +<br class="">
> +void InputGraph::skipGroup() {<br class="">
> +  if (_nextElementIndex >= _inputArgs.size())<br class="">
> +    return;<br class="">
> +  if (isa<GroupEnd>(_inputArgs[_nextElementIndex].get()))<br class="">
> +    _nextElementIndex++;<br class="">
> +}<br class="">
> +<br class="">
> /// \brief Read the file into _buffer.<br class="">
> std::error_code FileNode::getBuffer(StringRef filePath) {<br class="">
>   // Create a memory buffer<br class="">
> @@ -87,32 +105,10 @@ std::error_code FileNode::getBuffer(Stri<br class="">
>   return std::error_code();<br class="">
> }<br class="">
><br class="">
> -/// \brief Return the next file that need to be processed by the resolver.<br class="">
> -/// This also processes input elements depending on the resolve status<br class="">
> -/// of the input elements contained in the group.<br class="">
> -ErrorOr<File &> Group::getNextFile() {<br class="">
> -  // If there are no elements, move on to the next input element<br class="">
> -  if (_elements.empty())<br class="">
> -    return make_error_code(InputGraphError::no_more_files);<br class="">
> -<br class="">
> -  for (;;) {<br class="">
> -    // If we have processed all the elements, and have made no progress on<br class="">
> -    // linking, we cannot resolve any symbol from this group. Continue to the<br class="">
> -    // next one by returning no_more_files.<br class="">
> -    if (_nextElementIndex == _elements.size()) {<br class="">
> -      if (!_madeProgress)<br class="">
> -        return make_error_code(InputGraphError::no_more_files);<br class="">
> -      resetNextIndex();<br class="">
> -    }<br class="">
> -<br class="">
> -    _currentElementIndex = _nextElementIndex;<br class="">
> -    auto file = _elements[_nextElementIndex]->getNextFile();<br class="">
> -    // Move on to the next element if we have finished processing all<br class="">
> -    // the files in the input element<br class="">
> -    if (file.getError() == InputGraphError::no_more_files) {<br class="">
> -      _nextElementIndex++;<br class="">
> -      continue;<br class="">
> -    }<br class="">
> -    return *file;<br class="">
> -  }<br class="">
> +bool FileNode::getReplacements(InputGraph::InputElementVectorT &result) {<br class="">
> +  if (_files.size() < 2)<br class="">
> +    return false;<br class="">
> +  for (std::unique_ptr<File> &file : _files)<br class="">
> +    result.push_back(llvm::make_unique<SimpleFileNode>(_path, std::move(file)));<br class="">
> +  return true;<br class="">
> }<br class="">
><br class="">
> Modified: lld/trunk/lib/Core/Resolver.cpp<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/lib/Core/Resolver.cpp (original)<br class="">
> +++ lld/trunk/lib/Core/Resolver.cpp Wed Dec  3 19:09:06 2014<br class="">
> @@ -27,7 +27,7 @@<br class="">
><br class="">
> namespace lld {<br class="">
><br class="">
> -void Resolver::handleFile(const File &file) {<br class="">
> +bool Resolver::handleFile(const File &file) {<br class="">
>   bool undefAdded = false;<br class="">
>   for (const DefinedAtom *atom : file.defined())<br class="">
>     doDefinedAtom(*atom);<br class="">
> @@ -38,13 +38,7 @@ void Resolver::handleFile(const File &fi<br class="">
>     doSharedLibraryAtom(*atom);<br class="">
>   for (const AbsoluteAtom *atom : file.absolute())<br class="">
>     doAbsoluteAtom(*atom);<br class="">
> -<br class="">
> -  // Notify the input file manager of the fact that we have made some progress<br class="">
> -  // on linking using the current input file. It may want to know the fact for<br class="">
> -  // --start-group/--end-group.<br class="">
> -  if (undefAdded) {<br class="">
> -    _context.getInputGraph().notifyProgress();<br class="">
> -  }<br class="">
> +  return undefAdded;<br class="">
> }<br class="">
><br class="">
> void Resolver::forEachUndefines(bool searchForOverrides,<br class="">
> @@ -76,17 +70,19 @@ void Resolver::forEachUndefines(bool sea<br class="">
>   } while (undefineGenCount != _symbolTable.size());<br class="">
> }<br class="">
><br class="">
> -void Resolver::handleArchiveFile(const File &file) {<br class="">
> +bool Resolver::handleArchiveFile(const File &file) {<br class="">
>   const ArchiveLibraryFile *archiveFile = cast<ArchiveLibraryFile>(&file);<br class="">
>   bool searchForOverrides =<br class="">
>       _context.searchArchivesToOverrideTentativeDefinitions();<br class="">
> +  bool undefAdded = false;<br class="">
>   forEachUndefines(searchForOverrides,<br class="">
>                    [&](StringRef undefName, bool dataSymbolOnly) {<br class="">
>     if (const File *member = archiveFile->find(undefName, dataSymbolOnly)) {<br class="">
>       member->setOrdinal(_context.getNextOrdinalAndIncrement());<br class="">
> -      handleFile(*member);<br class="">
> +      undefAdded = undefAdded || handleFile(*member);<br class="">
>     }<br class="">
>   });<br class="">
> +  return undefAdded;<br class="">
> }<br class="">
><br class="">
> void Resolver::handleSharedLibrary(const File &file) {<br class="">
> @@ -233,31 +229,66 @@ void Resolver::addAtoms(const std::vecto<br class="">
>     doDefinedAtom(*newAtom);<br class="">
> }<br class="">
><br class="">
> +// Returns true if at least one of N previous files has created an<br class="">
> +// undefined symbol.<br class="">
> +bool Resolver::undefinesAdded(int n) {<br class="">
> +  for (size_t i = _fileIndex - n; i < _fileIndex; ++i)<br class="">
> +    if (_newUndefinesAdded[_files[i]])<br class="">
> +      return true;<br class="">
> +  return false;<br class="">
> +}<br class="">
> +<br class="">
> +ErrorOr<File &> Resolver::nextFile(bool &inGroup) {<br class="">
> +  if (size_t groupSize = _context.getInputGraph().getGroupSize()) {<br class="">
> +    // We are at the end of the current group. If one or more new<br class="">
> +    // undefined atom has been added in the last groupSize files, we<br class="">
> +    // reiterate over the files.<br class="">
> +    if (undefinesAdded(groupSize))<br class="">
> +      _fileIndex -= groupSize;<br class="">
> +    _context.getInputGraph().skipGroup();<br class="">
> +    return nextFile(inGroup);<br class="">
> +  }<br class="">
> +  if (_fileIndex < _files.size()) {<br class="">
> +    // We are still in the current group.<br class="">
> +    inGroup = true;<br class="">
> +    return *_files[_fileIndex++];<br class="">
> +  }<br class="">
> +  // We are not in a group. Get a new file.<br class="">
> +  ErrorOr<File &> file = _context.getInputGraph().getNextFile();<br class="">
> +  if (std::error_code ec = file.getError()) {<br class="">
> +    if (ec != InputGraphError::no_more_files)<br class="">
> +      llvm::errs() << "Error occurred in getNextFile: " << ec.message() << "\n";<br class="">
> +    return ec;<br class="">
> +  }<br class="">
> +  _files.push_back(&*file);<br class="">
> +  ++_fileIndex;<br class="">
> +  inGroup = false;<br class="">
> +  return *file;<br class="">
> +}<br class="">
> +<br class="">
> // Keep adding atoms until _context.getNextFile() returns an error. This<br class="">
> // function is where undefined atoms are resolved.<br class="">
> bool Resolver::resolveUndefines() {<br class="">
>   ScopedTask task(getDefaultDomain(), "resolveUndefines");<br class="">
><br class="">
>   for (;;) {<br class="">
> -    ErrorOr<File &> file = _context.getInputGraph().getNextFile();<br class="">
> -    std::error_code ec = file.getError();<br class="">
> -    if (ec == InputGraphError::no_more_files)<br class="">
> -      return true;<br class="">
> -    if (!file) {<br class="">
> -      llvm::errs() << "Error occurred in getNextFile: " << ec.message() << "\n";<br class="">
> -      return false;<br class="">
> -    }<br class="">
> -<br class="">
> +    bool inGroup = false;<br class="">
> +    bool undefAdded = false;<br class="">
> +    ErrorOr<File &> file = nextFile(inGroup);<br class="">
> +    if (std::error_code ec = file.getError())<br class="">
> +      return ec == InputGraphError::no_more_files;<br class="">
>     switch (file->kind()) {<br class="">
>     case File::kindObject:<br class="">
> +      if (inGroup)<br class="">
> +        break;<br class="">
>       assert(!file->hasOrdinal());<br class="">
>       file->setOrdinal(_context.getNextOrdinalAndIncrement());<br class="">
> -      handleFile(*file);<br class="">
> +      undefAdded = handleFile(*file);<br class="">
>       break;<br class="">
>     case File::kindArchiveLibrary:<br class="">
>       if (!file->hasOrdinal())<br class="">
>         file->setOrdinal(_context.getNextOrdinalAndIncrement());<br class="">
> -      handleArchiveFile(*file);<br class="">
> +      undefAdded = handleArchiveFile(*file);<br class="">
>       break;<br class="">
>     case File::kindSharedLibrary:<br class="">
>       if (!file->hasOrdinal())<br class="">
> @@ -265,6 +296,7 @@ bool Resolver::resolveUndefines() {<br class="">
>       handleSharedLibrary(*file);<br class="">
>       break;<br class="">
>     }<br class="">
> +    _newUndefinesAdded[&*file] = undefAdded;<br class="">
>   }<br class="">
> }<br class="">
><br class="">
><br class="">
> Modified: lld/trunk/lib/Driver/DarwinInputGraph.cpp<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinInputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinInputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/lib/Driver/DarwinInputGraph.cpp (original)<br class="">
> +++ lld/trunk/lib/Driver/DarwinInputGraph.cpp Wed Dec  3 19:09:06 2014<br class="">
> @@ -18,48 +18,6 @@<br class="">
> namespace lld {<br class="">
><br class="">
><br class="">
> -ErrorOr<File &> DarwinInputGraph::getNextFile() {<br class="">
> -  // The darwin linker processes input files in two phases.  The first phase<br class="">
> -  // links in all object (.o) files in command line order. The second phase<br class="">
> -  // links in libraries in command line order. If there are still UndefinedAtoms<br class="">
> -  // the second phase is repeated until notifyProgress() is not called by<br class="">
> -  // resolver.<br class="">
> -  for (;;) {<br class="">
> -    if (_currentInputElement) {<br class="">
> -      for(;;) {<br class="">
> -        ErrorOr<File &> next = _currentInputElement->getNextFile();<br class="">
> -        if (next.getError())<br class="">
> -          break;<br class="">
> -        File *file = &next.get();<br class="">
> -        bool fileIsLibrary = isa<SharedLibraryFile>(file) ||<br class="">
> -                             isa<ArchiveLibraryFile>(file);<br class="">
> -        if (fileIsLibrary == _librariesPhase) {<br class="">
> -          // Return library in library phase and object files in non-lib mode.<br class="">
> -          return *file;<br class="">
> -        }<br class="">
> -      }<br class="">
> -    }<br class="">
> -<br class="">
> -    if (_nextElementIndex >= _inputArgs.size()) {<br class="">
> -      // If no more elements, done unless we need to repeat library scan.<br class="">
> -      if (_librariesPhase && !_repeatLibraries)<br class="">
> -        return make_error_code(InputGraphError::no_more_files);<br class="">
> -      // Clear iterations and only look for libraries.<br class="">
> -      _librariesPhase = true;<br class="">
> -      _repeatLibraries = false;<br class="">
> -      _nextElementIndex = 0;<br class="">
> -      for (auto &ie : _inputArgs) {<br class="">
> -        ie->resetNextIndex();<br class="">
> -      }<br class="">
> -    }<br class="">
> -    _currentInputElement = _inputArgs[_nextElementIndex++].get();<br class="">
> -  }<br class="">
> -}<br class="">
> -<br class="">
> -void DarwinInputGraph::notifyProgress() {<br class="">
> -  _repeatLibraries = true;<br class="">
> -}<br class="">
> -<br class="">
> /// \brief Parse the input file to lld::File.<br class="">
> std::error_code MachOFileNode::parse(const LinkingContext &ctx,<br class="">
>                                      raw_ostream &diagnostics)  {<br class="">
><br class="">
> Modified: lld/trunk/lib/Driver/DarwinLdDriver.cpp<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/lib/Driver/DarwinLdDriver.cpp (original)<br class="">
> +++ lld/trunk/lib/Driver/DarwinLdDriver.cpp Wed Dec  3 19:09:06 2014<br class="">
> @@ -83,7 +83,7 @@ static std::string canonicalizePath(Stri<br class="">
>   }<br class="">
> }<br class="">
><br class="">
> -static void addFile(StringRef path, std::unique_ptr<DarwinInputGraph> &inputGraph,<br class="">
> +static void addFile(StringRef path, std::unique_ptr<InputGraph> &inputGraph,<br class="">
>                     MachOLinkingContext &ctx, bool loadWholeArchive,<br class="">
>                     bool upwardDylib) {<br class="">
>   auto node = llvm::make_unique<MachOFileNode>(path, ctx);<br class="">
> @@ -185,7 +185,7 @@ static std::error_code parseOrderFile(St<br class="">
> // per line. The <dir> prefix is prepended to each partial path.<br class="">
> //<br class="">
> static std::error_code parseFileList(StringRef fileListPath,<br class="">
> -                                     std::unique_ptr<DarwinInputGraph> &inputGraph,<br class="">
> +                                     std::unique_ptr<InputGraph> &inputGraph,<br class="">
>                                      MachOLinkingContext &ctx, bool forceLoad,<br class="">
>                                      raw_ostream &diagnostics) {<br class="">
>   // If there is a comma, split off <dir>.<br class="">
> @@ -521,7 +521,7 @@ bool DarwinLdDriver::parse(int argc, con<br class="">
>     }<br class="">
>   }<br class="">
><br class="">
> -  std::unique_ptr<DarwinInputGraph> inputGraph(new DarwinInputGraph());<br class="">
> +  std::unique_ptr<InputGraph> inputGraph(new InputGraph());<br class="">
><br class="">
>   // Now construct the set of library search directories, following ld64's<br class="">
>   // baroque set of accumulated hacks. Mostly, the algorithm constructs<br class="">
><br class="">
> Modified: lld/trunk/lib/Driver/Driver.cpp<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Driver.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Driver.cpp?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/lib/Driver/Driver.cpp (original)<br class="">
> +++ lld/trunk/lib/Driver/Driver.cpp Wed Dec  3 19:09:06 2014<br class="">
> @@ -62,9 +62,6 @@ bool Driver::link(LinkingContext &contex<br class="">
>       if (std::error_code ec = ie->parse(context, stream)) {<br class="">
>         if (FileNode *fileNode = dyn_cast<FileNode>(ie.get()))<br class="">
>           stream << fileNode->errStr(ec) << "\n";<br class="">
> -        else if (dyn_cast<Group>(ie.get()))<br class="">
> -          // FIXME: We need a better diagnostics here<br class="">
> -          stream << "Cannot parse group input element\n";<br class="">
>         else<br class="">
>           llvm_unreachable("Unknown type of input element");<br class="">
>         fail = true;<br class="">
> @@ -83,21 +80,24 @@ bool Driver::link(LinkingContext &contex<br class="">
>   if (fail)<br class="">
>     return false;<br class="">
><br class="">
> -  std::unique_ptr<SimpleFileNode> fileNode(<br class="">
> -      new SimpleFileNode("Internal Files"));<br class="">
> -<br class="">
>   InputGraph::FileVectorT internalFiles;<br class="">
>   context.createInternalFiles(internalFiles);<br class="">
> -<br class="">
> -  if (internalFiles.size())<br class="">
> -    fileNode->addFiles(std::move(internalFiles));<br class="">
> +  for (auto i = internalFiles.rbegin(), e = internalFiles.rend(); i != e; ++i) {<br class="">
> +    context.getInputGraph().addInputElementFront(<br class="">
> +        llvm::make_unique<SimpleFileNode>("internal", std::move(*i)));<br class="">
> +  }<br class="">
><br class="">
>   // Give target a chance to add files.<br class="">
>   InputGraph::FileVectorT implicitFiles;<br class="">
>   context.createImplicitFiles(implicitFiles);<br class="">
> -  if (implicitFiles.size())<br class="">
> -    fileNode->addFiles(std::move(implicitFiles));<br class="">
> -  context.getInputGraph().addInputElementFront(std::move(fileNode));<br class="">
> +  for (auto i = implicitFiles.rbegin(), e = implicitFiles.rend(); i != e; ++i) {<br class="">
> +    context.getInputGraph().addInputElementFront(<br class="">
> +        llvm::make_unique<SimpleFileNode>("implicit", std::move(*i)));<br class="">
> +  }<br class="">
> +<br class="">
> +  // Give target a chance to sort the input files.<br class="">
> +  // Mach-O uses this chance to move all object files before library files.<br class="">
> +  context.maybeSortInputFiles();<br class="">
><br class="">
>   // Do core linking.<br class="">
>   ScopedTask resolveTask(getDefaultDomain(), "Resolve");<br class="">
><br class="">
> Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)<br class="">
> +++ lld/trunk/lib/Driver/GnuLdDriver.cpp Wed Dec  3 19:09:06 2014<br class="">
> @@ -295,7 +295,8 @@ bool GnuLdDriver::parse(int argc, const<br class="">
>   }<br class="">
><br class="">
>   std::unique_ptr<InputGraph> inputGraph(new InputGraph());<br class="">
> -  std::stack<Group *> groupStack;<br class="">
> +  std::stack<int> groupStack;<br class="">
> +  int numfiles = 0;<br class="">
><br class="">
>   ELFFileNode::Attributes attributes;<br class="">
><br class="">
> @@ -468,16 +469,21 @@ bool GnuLdDriver::parse(int argc, const<br class="">
>       break;<br class="">
>     }<br class="">
><br class="">
> -    case OPT_start_group: {<br class="">
> -      std::unique_ptr<Group> group(new Group());<br class="">
> -      groupStack.push(group.get());<br class="">
> -      inputGraph->addInputElement(std::move(group));<br class="">
> +    case OPT_start_group:<br class="">
> +      groupStack.push(numfiles);<br class="">
>       break;<br class="">
> -    }<br class="">
><br class="">
> -    case OPT_end_group:<br class="">
> +    case OPT_end_group: {<br class="">
> +      if (groupStack.empty()) {<br class="">
> +        diagnostics << "stray --end-group\n";<br class="">
> +        return false;<br class="">
> +      }<br class="">
> +      int startGroupPos = groupStack.top();<br class="">
> +      inputGraph->addInputElement(<br class="">
> +          llvm::make_unique<GroupEnd>(numfiles - startGroupPos));<br class="">
>       groupStack.pop();<br class="">
>       break;<br class="">
> +    }<br class="">
><br class="">
>     case OPT_z: {<br class="">
>       StringRef extOpt = inputArg->getValue();<br class="">
> @@ -552,11 +558,8 @@ bool GnuLdDriver::parse(int argc, const<br class="">
>         }<br class="">
>       }<br class="">
>       std::unique_ptr<InputElement> inputFile(inputNode);<br class="">
> -      if (groupStack.empty()) {<br class="">
> -        inputGraph->addInputElement(std::move(inputFile));<br class="">
> -      } else {<br class="">
> -        groupStack.top()->addFile(std::move(inputFile));<br class="">
> -      }<br class="">
> +      ++numfiles;<br class="">
> +      inputGraph->addInputElement(std::move(inputFile));<br class="">
>       break;<br class="">
>     }<br class="">
><br class="">
><br class="">
> Modified: lld/trunk/lib/Driver/GnuLdInputGraph.cpp<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdInputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdInputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/lib/Driver/GnuLdInputGraph.cpp (original)<br class="">
> +++ lld/trunk/lib/Driver/GnuLdInputGraph.cpp Wed Dec  3 19:09:06 2014<br class="">
> @@ -91,7 +91,7 @@ std::error_code ELFGNULdScript::parse(co<br class="">
>     auto *group = dyn_cast<script::Group>(c);<br class="">
>     if (!group)<br class="">
>       continue;<br class="">
> -    std::unique_ptr<Group> groupStart(new Group());<br class="">
> +    size_t numfiles = 0;<br class="">
>     for (const script::Path &path : group->getPaths()) {<br class="">
>       // TODO : Propagate Set WholeArchive/dashlPrefix<br class="">
>       attributes.setAsNeeded(path._asNeeded);<br class="">
> @@ -100,9 +100,10 @@ std::error_code ELFGNULdScript::parse(co<br class="">
>           _elfLinkingContext, _elfLinkingContext.allocateString(path._path),<br class="">
>           attributes);<br class="">
>       std::unique_ptr<InputElement> inputFile(inputNode);<br class="">
> -      groupStart.get()->addFile(std::move(inputFile));<br class="">
> +      _expandElements.push_back(std::move(inputFile));<br class="">
> +      ++numfiles;<br class="">
>     }<br class="">
> -    _expandElements.push_back(std::move(groupStart));<br class="">
> +    _expandElements.push_back(llvm::make_unique<GroupEnd>(numfiles));<br class="">
>   }<br class="">
>   return std::error_code();<br class="">
> }<br class="">
><br class="">
> Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)<br class="">
> +++ lld/trunk/lib/Driver/WinLinkDriver.cpp Wed Dec  3 19:09:06 2014<br class="">
> @@ -781,7 +781,7 @@ static bool hasLibrary(const PECOFFLinki<br class="">
>   ErrorOr<StringRef> path = fileNode->getPath(ctx);<br class="">
>   if (!path)<br class="">
>     return false;<br class="">
> -  for (std::unique_ptr<InputElement> &p : ctx.getLibraryGroup()->elements())<br class="">
> +  for (std::unique_ptr<InputElement> &p : ctx.getInputGraph().inputElements())<br class="">
>     if (auto *f = dyn_cast<FileNode>(p.get()))<br class="">
>       if (*path == *f->getPath(ctx))<br class="">
>         return true;<br class="">
> @@ -1397,10 +1397,8 @@ bool WinLinkDriver::parse(int argc, cons<br class="">
>     ctx.setEntryNode(entry.get());<br class="">
>     ctx.getInputGraph().addInputElement(std::move(entry));<br class="">
><br class="">
> -    // The container for all library files.<br class="">
> -    std::unique_ptr<Group> group(new PECOFFGroup(ctx));<br class="">
> -    ctx.setLibraryGroup(group.get());<br class="">
> -    ctx.getInputGraph().addInputElement(std::move(group));<br class="">
> +    // Add a group-end marker.<br class="">
> +    ctx.getInputGraph().addInputElement(llvm::make_unique<GroupEnd>(0));<br class="">
>   }<br class="">
><br class="">
>   // Add the library files to the library group.<br class="">
> @@ -1409,7 +1407,7 @@ bool WinLinkDriver::parse(int argc, cons<br class="">
>       if (isReadingDirectiveSection)<br class="">
>         if (lib->parse(ctx, diag))<br class="">
>           return false;<br class="">
> -      ctx.getLibraryGroup()->addFile(std::move(lib));<br class="">
> +      ctx.addLibraryFile(std::move(lib));<br class="">
>     }<br class="">
>   }<br class="">
><br class="">
><br class="">
> Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)<br class="">
> +++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Wed Dec  3 19:09:06 2014<br class="">
> @@ -22,6 +22,7 @@<br class="">
> #include "llvm/ADT/Triple.h"<br class="">
> #include "llvm/Config/config.h"<br class="">
> #include "llvm/Support/Errc.h"<br class="">
> +#include "llvm/Support/Debug.h"<br class="">
> #include "llvm/Support/Host.h"<br class="">
> #include "llvm/Support/MachO.h"<br class="">
> #include "llvm/Support/Path.h"<br class="">
> @@ -923,4 +924,35 @@ bool MachOLinkingContext::customAtomOrde<br class="">
>   return true;<br class="">
> }<br class="">
><br class="">
> +static File *getFirstFile(const std::unique_ptr<InputElement> &elem) {<br class="">
> +  FileNode *e = dyn_cast<FileNode>(const_cast<InputElement *>(elem.get()));<br class="">
> +  if (!e || e->files().empty())<br class="">
> +    return nullptr;<br class="">
> +  return e->files()[0].get();<br class="">
> +}<br class="">
> +<br class="">
> +static bool isLibrary(const std::unique_ptr<InputElement> &elem) {<br class="">
> +  File *f = getFirstFile(elem);<br class="">
> +  return f && (isa<SharedLibraryFile>(f) || isa<ArchiveLibraryFile>(f));<br class="">
> +}<br class="">
> +<br class="">
> +// The darwin linker processes input files in two phases.  The first phase<br class="">
> +// links in all object (.o) files in command line order. The second phase<br class="">
> +// links in libraries in command line order.<br class="">
> +// In this function we reorder the input files so that all the object files<br class="">
> +// comes before any library file. We also make a group for the library files<br class="">
> +// so that the Resolver will reiterate over the libraries as long as we find<br class="">
> +// new undefines from libraries.<br class="">
> +void MachOLinkingContext::maybeSortInputFiles() {<br class="">
> +  std::vector<std::unique_ptr<InputElement>> &elements<br class="">
> +      = getInputGraph().inputElements();<br class="">
> +  std::stable_sort(elements.begin(), elements.end(),<br class="">
> +                   [](const std::unique_ptr<InputElement> &a,<br class="">
> +                      const std::unique_ptr<InputElement> &b) {<br class="">
> +                     return !isLibrary(a) && isLibrary(b);<br class="">
> +                   });<br class="">
> +  size_t numLibs = std::count_if(elements.begin(), elements.end(), isLibrary);<br class="">
> +  elements.push_back(llvm::make_unique<GroupEnd>(numLibs));<br class="">
> +}<br class="">
> +<br class="">
> } // end namespace lld<br class="">
><br class="">
> Modified: lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp (original)<br class="">
> +++ lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp Wed Dec  3 19:09:06 2014<br class="">
> @@ -87,6 +87,23 @@ std::unique_ptr<File> PECOFFLinkingConte<br class="">
>       "<command line option /include>");<br class="">
> }<br class="">
><br class="">
> +void PECOFFLinkingContext::addLibraryFile(std::unique_ptr<FileNode> file) {<br class="">
> +  GroupEnd *currentGroupEnd;<br class="">
> +  int pos = -1;<br class="">
> +  std::vector<std::unique_ptr<InputElement>> &elements<br class="">
> +      = getInputGraph().inputElements();<br class="">
> +  for (int i = 0, e = elements.size(); i < e; ++i) {<br class="">
> +    if ((currentGroupEnd = dyn_cast<GroupEnd>(elements[i].get()))) {<br class="">
> +      pos = i;<br class="">
> +      break;<br class="">
> +    }<br class="">
> +  }<br class="">
> +  assert(pos >= 0);<br class="">
> +  elements.insert(elements.begin() + pos, std::move(file));<br class="">
> +  elements[pos + 1] = llvm::make_unique<GroupEnd>(<br class="">
> +      currentGroupEnd->getSize() + 1);<br class="">
> +}<br class="">
> +<br class="">
> bool PECOFFLinkingContext::createImplicitFiles(<br class="">
>     std::vector<std::unique_ptr<File>> &) {<br class="">
>   // Create a file for __ImageBase.<br class="">
> @@ -109,7 +126,7 @@ bool PECOFFLinkingContext::createImplici<br class="">
>   auto exportNode = llvm::make_unique<SimpleFileNode>("<export>");<br class="">
>   exportNode->appendInputFile(<br class="">
>       llvm::make_unique<pecoff::ExportedSymbolRenameFile>(*this, syms));<br class="">
> -  getLibraryGroup()->addFile(std::move(exportNode));<br class="">
> +  addLibraryFile(std::move(exportNode));<br class="">
><br class="">
>   // Create a file for the entry point function.<br class="">
>   getEntryNode()->appendInputFile(<br class="">
><br class="">
> Modified: lld/trunk/unittests/DriverTests/DriverTest.h<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/DriverTest.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/DriverTest.h?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/unittests/DriverTests/DriverTest.h (original)<br class="">
> +++ lld/trunk/unittests/DriverTests/DriverTest.h Wed Dec  3 19:09:06 2014<br class="">
> @@ -37,18 +37,6 @@ protected:<br class="">
>     llvm_unreachable("not handling other types of input files");<br class="">
>   }<br class="">
><br class="">
> -  // Convenience method for getting i'th input files name.<br class="">
> -  std::string inputFile(int index1, int index2) {<br class="">
> -    Group *group = dyn_cast<Group>(<br class="">
> -        linkingContext()->getInputGraph().inputElements()[index1].get());<br class="">
> -    if (!group)<br class="">
> -      llvm_unreachable("not handling other types of input files");<br class="">
> -    FileNode *file = dyn_cast<FileNode>(group->elements()[index2].get());<br class="">
> -    if (!file)<br class="">
> -      llvm_unreachable("not handling other types of input files");<br class="">
> -    return *file->getPath(*linkingContext());<br class="">
> -  }<br class="">
> -<br class="">
>   // For unit tests to call driver with various command lines.<br class="">
>   bool parse(const char *args, ...) {<br class="">
>     // Construct command line options from varargs.<br class="">
><br class="">
> Modified: lld/trunk/unittests/DriverTests/InputGraphTest.cpp<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/InputGraphTest.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/InputGraphTest.cpp?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/unittests/DriverTests/InputGraphTest.cpp (original)<br class="">
> +++ lld/trunk/unittests/DriverTests/InputGraphTest.cpp Wed Dec  3 19:09:06 2014<br class="">
> @@ -77,7 +77,7 @@ protected:<br class="">
><br class="">
> } // end anonymous namespace<br class="">
><br class="">
> -static std::unique_ptr<TestFileNode> createFile1(StringRef name) {<br class="">
> +static std::unique_ptr<TestFileNode> createFile(StringRef name) {<br class="">
>   std::vector<std::unique_ptr<File>> files;<br class="">
>   files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name)));<br class="">
>   std::unique_ptr<TestFileNode> file(new TestFileNode("filenode"));<br class="">
> @@ -85,109 +85,30 @@ static std::unique_ptr<TestFileNode> cre<br class="">
>   return file;<br class="">
> }<br class="">
><br class="">
> -static std::unique_ptr<TestFileNode> createFile2(StringRef name1,<br class="">
> -                                                 StringRef name2) {<br class="">
> -  std::vector<std::unique_ptr<File>> files;<br class="">
> -  files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name1)));<br class="">
> -  files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name2)));<br class="">
> -  std::unique_ptr<TestFileNode> file(new TestFileNode("filenode"));<br class="">
> -  file->addFiles(std::move(files));<br class="">
> -  return file;<br class="">
> -}<br class="">
> -<br class="">
> TEST_F(InputGraphTest, Empty) {<br class="">
>   expectEnd();<br class="">
> }<br class="">
><br class="">
> TEST_F(InputGraphTest, File) {<br class="">
> -  _graph->addInputElement(createFile1("file1"));<br class="">
> -  EXPECT_EQ("file1", getNext());<br class="">
> -  expectEnd();<br class="">
> -}<br class="">
> -<br class="">
> -TEST_F(InputGraphTest, Files) {<br class="">
> -  _graph->addInputElement(createFile2("file1", "file2"));<br class="">
> -  EXPECT_EQ("file1", getNext());<br class="">
> -  EXPECT_EQ("file2", getNext());<br class="">
> -  expectEnd();<br class="">
> -}<br class="">
> -<br class="">
> -TEST_F(InputGraphTest, Group) {<br class="">
> -  _graph->addInputElement(createFile2("file1", "file2"));<br class="">
> -<br class="">
> -  std::unique_ptr<Group> group(new Group());<br class="">
> -  group->addFile(createFile2("file3", "file4"));<br class="">
> -  group->addFile(createFile1("file5"));<br class="">
> -  group->addFile(createFile1("file6"));<br class="">
> -  _graph->addInputElement(std::move(group));<br class="">
> -<br class="">
> +  _graph->addInputElement(createFile("file1"));<br class="">
>   EXPECT_EQ("file1", getNext());<br class="">
> -  EXPECT_EQ("file2", getNext());<br class="">
> -  EXPECT_EQ("file3", getNext());<br class="">
> -  EXPECT_EQ("file4", getNext());<br class="">
> -  EXPECT_EQ("file5", getNext());<br class="">
> -  EXPECT_EQ("file6", getNext());<br class="">
> -  expectEnd();<br class="">
> -}<br class="">
> -<br class="">
> -// Iterate through the group<br class="">
> -TEST_F(InputGraphTest, GroupIteration) {<br class="">
> -  _graph->addInputElement(createFile2("file1", "file2"));<br class="">
> -<br class="">
> -  std::unique_ptr<Group> group(new Group());<br class="">
> -  group->addFile(createFile2("file3", "file4"));<br class="">
> -  group->addFile(createFile1("file5"));<br class="">
> -  group->addFile(createFile1("file6"));<br class="">
> -  _graph->addInputElement(std::move(group));<br class="">
> -<br class="">
> -  EXPECT_EQ("file1", getNext());<br class="">
> -  EXPECT_EQ("file2", getNext());<br class="">
> -<br class="">
> -  EXPECT_EQ("file3", getNext());<br class="">
> -  EXPECT_EQ("file4", getNext());<br class="">
> -  EXPECT_EQ("file5", getNext());<br class="">
> -  EXPECT_EQ("file6", getNext());<br class="">
> -  _graph->notifyProgress();<br class="">
> -<br class="">
> -  EXPECT_EQ("file3", getNext());<br class="">
> -  EXPECT_EQ("file4", getNext());<br class="">
> -  _graph->notifyProgress();<br class="">
> -  EXPECT_EQ("file5", getNext());<br class="">
> -  EXPECT_EQ("file6", getNext());<br class="">
> -<br class="">
> -  EXPECT_EQ("file3", getNext());<br class="">
> -  EXPECT_EQ("file4", getNext());<br class="">
> -  EXPECT_EQ("file5", getNext());<br class="">
> -  EXPECT_EQ("file6", getNext());<br class="">
>   expectEnd();<br class="">
> }<br class="">
><br class="">
> // Node expansion tests<br class="">
> TEST_F(InputGraphTest, Normalize) {<br class="">
> -  _graph->addInputElement(createFile2("file1", "file2"));<br class="">
> +  _graph->addInputElement(createFile("file1"));<br class="">
><br class="">
>   std::unique_ptr<TestExpandFileNode> expandFile(<br class="">
>       new TestExpandFileNode("node"));<br class="">
> -  expandFile->addElement(createFile1("file3"));<br class="">
> -  expandFile->addElement(createFile1("file4"));<br class="">
> +  expandFile->addElement(createFile("file2"));<br class="">
> +  expandFile->addElement(createFile("file3"));<br class="">
>   _graph->addInputElement(std::move(expandFile));<br class="">
> -<br class="">
> -  std::unique_ptr<Group> group(new Group());<br class="">
> -  std::unique_ptr<TestExpandFileNode> expandFile2(<br class="">
> -      new TestExpandFileNode("node"));<br class="">
> -  expandFile2->addElement(createFile1("file5"));<br class="">
> -  group->addFile(std::move(expandFile2));<br class="">
> -  _graph->addInputElement(std::move(group));<br class="">
> -<br class="">
> -  _graph->addInputElement(createFile1("file6"));<br class="">
>   _graph->normalize();<br class="">
><br class="">
>   EXPECT_EQ("file1", getNext());<br class="">
>   EXPECT_EQ("file2", getNext());<br class="">
>   EXPECT_EQ("file3", getNext());<br class="">
> -  EXPECT_EQ("file4", getNext());<br class="">
> -  EXPECT_EQ("file5", getNext());<br class="">
> -  EXPECT_EQ("file6", getNext());<br class="">
>   expectEnd();<br class="">
> }<br class="">
><br class="">
> @@ -195,8 +116,8 @@ TEST_F(InputGraphTest, Observer) {<br class="">
>   std::vector<std::string> files;<br class="">
>   _graph->registerObserver([&](File *file) { files.push_back(file->path()); });<br class="">
><br class="">
> -  _graph->addInputElement(createFile1("file1"));<br class="">
> -  _graph->addInputElement(createFile1("file2"));<br class="">
> +  _graph->addInputElement(createFile("file1"));<br class="">
> +  _graph->addInputElement(createFile("file2"));<br class="">
>   EXPECT_EQ("file1", getNext());<br class="">
>   EXPECT_EQ("file2", getNext());<br class="">
>   expectEnd();<br class="">
><br class="">
> Modified: lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp<br class="">
> URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=223330&r1=223329&r2=223330&view=diff</a><br class="">
> ==============================================================================<br class="">
> --- lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp (original)<br class="">
> +++ lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp Wed Dec  3 19:09:06 2014<br class="">
> @@ -137,11 +137,11 @@ TEST_F(WinLinkParserTest, Libpath) {<br class="">
> TEST_F(WinLinkParserTest, InputOrder) {<br class="">
>   EXPECT_TRUE(parse("link.exe", "a.lib", "b.obj", "c.obj", "a.lib", "d.obj",<br class="">
>                     nullptr));<br class="">
> -  EXPECT_EQ(5, inputFileCount());<br class="">
> +  EXPECT_EQ(6, inputFileCount());<br class="">
>   EXPECT_EQ("b.obj", inputFile(0));<br class="">
>   EXPECT_EQ("c.obj", inputFile(1));<br class="">
>   EXPECT_EQ("d.obj", inputFile(2));<br class="">
> -  EXPECT_EQ("a.lib", inputFile(4, 0));<br class="">
> +  EXPECT_EQ("a.lib", inputFile(4));<br class="">
> }<br class="">
><br class="">
> //<br class="">
> @@ -393,36 +393,36 @@ TEST_F(WinLinkParserTest, SectionMultipl<br class="">
> TEST_F(WinLinkParserTest, DefaultLib) {<br class="">
>   EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",<br class="">
>                     "/defaultlib:kernel32", "a.obj", nullptr));<br class="">
> -  EXPECT_EQ(3, inputFileCount());<br class="">
> +  EXPECT_EQ(5, inputFileCount());<br class="">
>   EXPECT_EQ("a.obj", inputFile(0));<br class="">
> -  EXPECT_EQ("user32.lib", inputFile(2, 0));<br class="">
> -  EXPECT_EQ("kernel32.lib", inputFile(2, 1));<br class="">
> +  EXPECT_EQ("user32.lib", inputFile(2));<br class="">
> +  EXPECT_EQ("kernel32.lib", inputFile(3));<br class="">
> }<br class="">
><br class="">
> TEST_F(WinLinkParserTest, DefaultLibDuplicates) {<br class="">
>   EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",<br class="">
>                     "/defaultlib:user32.lib", "a.obj", nullptr));<br class="">
> -  EXPECT_EQ(3, inputFileCount());<br class="">
> +  EXPECT_EQ(4, inputFileCount());<br class="">
>   EXPECT_EQ("a.obj", inputFile(0));<br class="">
> -  EXPECT_EQ("user32.lib", inputFile(2, 0));<br class="">
> +  EXPECT_EQ("user32.lib", inputFile(2));<br class="">
> }<br class="">
><br class="">
> TEST_F(WinLinkParserTest, NoDefaultLib) {<br class="">
>   EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",<br class="">
>                     "/defaultlib:kernel32", "/nodefaultlib:user32.lib", "a.obj",<br class="">
>                     nullptr));<br class="">
> -  EXPECT_EQ(3, inputFileCount());<br class="">
> +  EXPECT_EQ(4, inputFileCount());<br class="">
>   EXPECT_EQ("a.obj", inputFile(0));<br class="">
> -  EXPECT_EQ("kernel32.lib", inputFile(2, 0));<br class="">
> +  EXPECT_EQ("kernel32.lib", inputFile(2));<br class="">
> }<br class="">
><br class="">
> TEST_F(WinLinkParserTest, NoDefaultLibCase) {<br class="">
>   EXPECT_TRUE(parse("link.exe", "/defaultlib:user32",<br class="">
>                     "/defaultlib:kernel32", "/nodefaultlib:USER32.LIB", "a.obj",<br class="">
>                     nullptr));<br class="">
> -  EXPECT_EQ(3, inputFileCount());<br class="">
> +  EXPECT_EQ(4, inputFileCount());<br class="">
>   EXPECT_EQ("a.obj", inputFile(0));<br class="">
> -  EXPECT_EQ("kernel32.lib", inputFile(2, 0));<br class="">
> +  EXPECT_EQ("kernel32.lib", inputFile(2));<br class="">
> }<br class="">
><br class="">
> TEST_F(WinLinkParserTest, NoDefaultLibAll) {<br class="">
> @@ -436,9 +436,9 @@ TEST_F(WinLinkParserTest, DisallowLib) {<br class="">
>   EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",<br class="">
>                     "/defaultlib:kernel32", "/disallowlib:user32.lib", "a.obj",<br class="">
>                     nullptr));<br class="">
> -  EXPECT_EQ(3, inputFileCount());<br class="">
> +  EXPECT_EQ(4, inputFileCount());<br class="">
>   EXPECT_EQ("a.obj", inputFile(0));<br class="">
> -  EXPECT_EQ("kernel32.lib", inputFile(2, 0));<br class="">
> +  EXPECT_EQ("kernel32.lib", inputFile(2));<br class="">
> }<br class="">
><br class="">
> //<br class="">
><br class="">
><br class="">
> _______________________________________________<br class="">
> llvm-commits mailing list<br class="">
> <a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank" class="">llvm-commits@cs.uiuc.edu</a><br class="">
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank" class="">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br class="">
<br class="">
</div></div></blockquote></div><br class=""></div>
_______________________________________________<br class="">llvm-commits mailing list<br class=""><a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank" class="">llvm-commits@cs.uiuc.edu</a><br class=""><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank" class="">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br class=""></div></div></div></blockquote></div><br class=""></div></div></div></blockquote></div><br class=""></div>
_______________________________________________<br class="">llvm-commits mailing list<br class=""><a href="mailto:llvm-commits@cs.uiuc.edu" class="">llvm-commits@cs.uiuc.edu</a><br class="">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits<br class=""></div></blockquote></div><br class=""></div></body></html>