[lld] r223330 - Rewrite InputGraph's Group

Rui Ueyama ruiu at google.com
Sun Dec 7 23:15:58 PST 2014


I'm having trouble to link LLD using LLD on Darwin. Could you help me
figure out what's wrong?

LLD aborts with the following error message

warning: ignoring unknown argument: -search_paths_first
warning: ignoring unknown argument: -headerpad_max_install_names
Failed to write file 'bin/lld': Exec format error

when I try to link LLD with the following command (../ld is stage 1 LLD
executable)

$ ../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"


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).

Nick said that the LLD is now able to self-host it on Darwin. Is it still
working?

On Fri, Dec 5, 2014 at 12:11 AM, Jean-Daniel Dupas <dev at xenonium.com> wrote:

> I think that change broke the Darwin linker.
>
> When trying to link executable using lld, I know have a lot of ‘undefined
> symbol’ error for symbols provided by (static) libraries.
>
> > Le 4 déc. 2014 à 02:09, Rui Ueyama <ruiu at google.com> a écrit :
> >
> > Author: ruiu
> > Date: Wed Dec  3 19:09:06 2014
> > New Revision: 223330
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=223330&view=rev
> > 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputGraph.h?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/LinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/DarwinInputGraph.h?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/WinLinkInputGraph.h?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinInputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Driver.cpp?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdInputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/DriverTest.h?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/InputGraphTest.cpp?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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:
> http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=223330&r1=223329&r2=223330&view=diff
> >
> ==============================================================================
> > --- 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 list
> > llvm-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141208/35b870b6/attachment.html>


More information about the llvm-commits mailing list