[lld] r192269 - [inputGraph] Associate Resolve state with appropriate nodes

Shankar Easwaran shankare at codeaurora.org
Tue Oct 8 20:40:30 PDT 2013


Author: shankare
Date: Tue Oct  8 22:40:29 2013
New Revision: 192269

URL: http://llvm.org/viewvc/llvm-project?rev=192269&view=rev
Log:
[inputGraph] Associate Resolve state with appropriate nodes

This associates resolveState to FileNodes. The control node derive
their resolution state from the inputElements that are contained in
it.

This makes --start-group/--end-group to work with ELF linking.

Added:
    lld/trunk/test/elf/X86_64/Inputs/group/
    lld/trunk/test/elf/X86_64/Inputs/group/1.c
    lld/trunk/test/elf/X86_64/Inputs/group/1.o
    lld/trunk/test/elf/X86_64/Inputs/group/fn.c
    lld/trunk/test/elf/X86_64/Inputs/group/fn.o
    lld/trunk/test/elf/X86_64/Inputs/group/fn1.c
    lld/trunk/test/elf/X86_64/Inputs/group/fn1.o
    lld/trunk/test/elf/X86_64/Inputs/group/fn2.c
    lld/trunk/test/elf/X86_64/Inputs/group/fn2.o
    lld/trunk/test/elf/X86_64/Inputs/group/group.sh
    lld/trunk/test/elf/X86_64/Inputs/group/libfn.a
    lld/trunk/test/elf/X86_64/Inputs/group/libfn1.a
    lld/trunk/test/elf/X86_64/startGroupEndGroup.test
Modified:
    lld/trunk/include/lld/Driver/GnuLdInputGraph.h
    lld/trunk/include/lld/Driver/InputGraph.h
    lld/trunk/lib/Core/LinkingContext.cpp
    lld/trunk/lib/Core/Resolver.cpp
    lld/trunk/lib/Driver/GnuLdDriver.cpp
    lld/trunk/lib/Driver/InputGraph.cpp

Modified: lld/trunk/include/lld/Driver/GnuLdInputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/GnuLdInputGraph.h?rev=192269&r1=192268&r2=192269&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/GnuLdInputGraph.h (original)
+++ lld/trunk/include/lld/Driver/GnuLdInputGraph.h Tue Oct  8 22:40:29 2013
@@ -114,10 +114,11 @@ public:
   /// to start processing files as part of the inputelement from beginning.
   /// reset the next file index to 0 only if the node is an archive library or
   /// a shared library
-  virtual void resetNextFileIndex() {
+  virtual void resetNextIndex() {
     if ((!_isWholeArchive && (_files[0]->kind() == File::kindArchiveLibrary)) ||
         (_files[0]->kind() == File::kindSharedLibrary))
       _nextFileIndex = 0;
+    setResolveState(Resolver::StateNoChange);
     return;
   }
 
@@ -144,7 +145,8 @@ private:
 /// \brief Represents a ELF control node
 class ELFGroup : public Group {
 public:
-  ELFGroup(ELFLinkingContext &ctx) : Group(), _elfLinkingContext(ctx) {}
+  ELFGroup(ELFLinkingContext &ctx, int64_t ordinal)
+      : Group(ordinal), _elfLinkingContext(ctx) {}
 
   static inline bool classof(const InputElement *a) {
     return a->kind() == InputElement::Kind::Control;
@@ -167,42 +169,6 @@ public:
     return error_code::success();
   }
 
-  /// \brief Return the file that has to be processed by the resolver
-  /// to resolve atoms. This iterates over all the elements thats part
-  /// of this node.
-  virtual ErrorOr<File &> getNextFile() {
-    // Does the linker need to process the elements again ?
-    bool again = false;
-    // If there are no elements, move on to the next input element
-    if (_elements.size() == 0)
-      return make_error_code(InputGraphError::no_more_files);
-    // If we have processed all the elements as part of this node
-    // check the resolver status for each input element and if the status
-    // has not changed, move onto the next file.
-    if (_nextElementIndex == _elements.size()) {
-      for (auto &elem : _elements) {
-        if (elem->getResolverState() == Resolver::StateNoChange) {
-          again = true;
-          break;
-        }
-      }
-      if (!again)
-        return make_error_code(InputGraphError::no_more_files);
-      _nextElementIndex = 0;
-      // Reset the next file to be processed as part of each element
-      for (auto &elem : _elements)
-        elem->resetNextFileIndex();
-    }
-    auto file = _elements[_nextElementIndex]->getNextFile();
-    // Move on to the next element if we have finished processing all
-    // the files in the input element
-    if (error_code(file) == InputGraphError::no_more_files)
-      _nextElementIndex++;
-    else
-      return *file;
-    return getNextFile();
-  }
-
 private:
   const ELFLinkingContext &_elfLinkingContext;
 };

Modified: lld/trunk/include/lld/Driver/InputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/InputGraph.h?rev=192269&r1=192268&r2=192269&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/InputGraph.h (original)
+++ lld/trunk/include/lld/Driver/InputGraph.h Tue Oct  8 22:40:29 2013
@@ -173,21 +173,19 @@ public:
   /// Get the next file to be processed by the resolver
   virtual ErrorOr<File &> getNextFile() = 0;
 
-  /// \brief Set the resolver state for the element
-  virtual void setResolverState(int32_t state) { _resolveState = state; }
+  /// \brief Set the resolve state for the element
+  virtual void setResolveState(uint32_t state) = 0;
 
-  /// \brief Get the resolver state for the element
-  virtual int32_t getResolverState() const { return _resolveState; }
+  /// \brief Get the resolve state for the element
+  virtual uint32_t getResolveState() const = 0;
 
-  /// Process files again.
-  virtual void resetNextFileIndex() { _nextFileIndex = 0; }
+  /// \brief Reset the next index
+  virtual void resetNextIndex() = 0;
 
 protected:
   Kind _kind;              // The type of the Element
   int64_t _ordinal;        // The ordinal value
   int64_t _weight;         // Weight of the file
-  int32_t _resolveState;   // The resolve state
-  uint32_t _nextFileIndex; // The file that would be processed by the resolver
 };
 
 /// \brief The Control class represents a control node in the InputGraph
@@ -204,7 +202,8 @@ public:
                   ControlNode::ControlKind::Simple,
               int64_t _ordinal = -1)
       : InputElement(InputElement::Kind::Control, _ordinal),
-        _controlKind(controlKind), _nextElementIndex(0) {}
+        _controlKind(controlKind), _currentElementIndex(0),
+        _nextElementIndex(0) {}
 
   virtual ~ControlNode() {}
 
@@ -233,9 +232,20 @@ public:
   /// in the InputElement
   virtual void assignFileOrdinals(uint64_t &startOrdinal);
 
+  virtual void resetNextIndex() {
+    _currentElementIndex = _nextElementIndex = 0;
+    for (auto &elem : _elements)
+      elem->resetNextIndex();
+  }
+
+  virtual uint32_t getResolveState() const;
+
+  virtual void setResolveState(uint32_t);
+
 protected:
   ControlKind _controlKind;
   InputGraph::InputElementVectorT _elements;
+  uint32_t _currentElementIndex;
   uint32_t _nextElementIndex;
 };
 
@@ -246,8 +256,7 @@ protected:
 /// directly.
 class FileNode : public InputElement {
 public:
-  FileNode(StringRef path, int64_t ordinal = -1)
-      : InputElement(InputElement::Kind::File, ordinal), _path(path) {}
+  FileNode(StringRef path, int64_t ordinal = -1);
 
   virtual ErrorOr<StringRef> getPath(const LinkingContext &) const {
     return _path;
@@ -301,13 +310,29 @@ public:
   /// in the InputElement
   virtual void assignFileOrdinals(uint64_t &startOrdinal);
 
+  /// \brief Reset the file index if the resolver needs to process
+  /// the node again.
+  virtual void resetNextIndex();
+
+  /// \brief Set the resolve state for the FileNode.
+  virtual void setResolveState(uint32_t resolveState) {
+    _resolveState = resolveState;
+  }
+
+  /// \brief Retrieve the resolve state of the FileNode.
+  virtual uint32_t getResolveState() const { return _resolveState; }
+
 protected:
   /// \brief Read the file into _buffer.
   error_code readFile(const LinkingContext &ctx, raw_ostream &diagnostics);
 
-  StringRef _path;
-  InputGraph::FileVectorT _files;
-  std::unique_ptr<llvm::MemoryBuffer> _buffer;
+  StringRef _path;                             // The path of the Input file
+  InputGraph::FileVectorT _files;              // A vector of lld File objects
+  std::unique_ptr<llvm::MemoryBuffer> _buffer; // Memory buffer to actual
+                                               // contents
+  uint32_t _resolveState;                      // The resolve state of the file
+  uint32_t _nextFileIndex; // The next file that would be processed by the
+                           // resolver
 };
 
 /// \brief A Control node which contains a group of InputElements
@@ -316,23 +341,26 @@ protected:
 /// follow the group
 class Group : public ControlNode {
 public:
-  Group() : ControlNode(ControlNode::ControlKind::Group) {}
+  Group(int64_t ordinal)
+      : ControlNode(ControlNode::ControlKind::Group, ordinal) {}
 
   static inline bool classof(const InputElement *a) {
     return a->kind() == InputElement::Kind::Control;
   }
 
+  /// \brief Process input element and add it to the group
   virtual bool processInputElement(std::unique_ptr<InputElement> element) {
     _elements.push_back(std::move(element));
     return true;
   }
+
+  virtual ErrorOr<File &> getNextFile();
 };
 
 /// \brief Represents Internal Input files
 class SimpleFileNode : public InputElement {
 public:
-  SimpleFileNode(StringRef path, int64_t ordinal = -1)
-      : InputElement(InputElement::Kind::SimpleFile, ordinal), _path(path) {}
+  SimpleFileNode(StringRef path, int64_t ordinal = -1);
 
   virtual llvm::ErrorOr<StringRef> path(const LinkingContext &) const {
     return _path;
@@ -379,22 +407,35 @@ public:
     return error_code::success();
   }
 
+  /// \brief Return the next File thats part of this node to the
+  /// resolver.
   virtual ErrorOr<File &> getNextFile() {
     if (_nextFileIndex == _files.size())
       return make_error_code(InputGraphError::no_more_files);
     return *_files[_nextFileIndex++];
   }
 
+  /// \brief Set the resolver state.
+  virtual void setResolveState(uint32_t resolveState) {
+    _resolveState = resolveState;
+  }
+
+  /// \brief Retrieve the resolve state.
+  virtual uint32_t getResolveState() const { return _resolveState; }
+
   // Do nothing here.
-  virtual void resetNextFileIndex() {}
+  virtual void resetNextIndex() {}
 
   /// \brief Assign File ordinals for files contained
   /// in the InputElement
   virtual void assignFileOrdinals(uint64_t &startOrdinal);
 
 protected:
-  StringRef _path;
-  InputGraph::FileVectorT _files;
+  StringRef _path;                // A string associated with this file.
+  InputGraph::FileVectorT _files; // Vector of lld::File objects
+  uint32_t _nextFileIndex; // The next file that would be processed by the
+                           // resolver
+  uint32_t _resolveState;  // The resolve state associated with this Node
 };
 } // namespace lld
 

Modified: lld/trunk/lib/Core/LinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/LinkingContext.cpp?rev=192269&r1=192268&r2=192269&view=diff
==============================================================================
--- lld/trunk/lib/Core/LinkingContext.cpp (original)
+++ lld/trunk/lib/Core/LinkingContext.cpp Tue Oct  8 22:40:29 2013
@@ -77,7 +77,7 @@ bool LinkingContext::createInternalFiles
 }
 
 void LinkingContext::setResolverState(uint32_t state) {
-  _currentInputElement->setResolverState(state);
+  _currentInputElement->setResolveState(state);
 }
 
 ErrorOr<File &> LinkingContext::nextFile() {

Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=192269&r1=192268&r2=192269&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Tue Oct  8 22:40:29 2013
@@ -292,6 +292,7 @@ void Resolver::resolveUndefines() {
   ScopedTask task(getDefaultDomain(), "resolveUndefines");
 
   while (ErrorOr<File &> nextFile = _context.nextFile()) {
+    _context.setResolverState(Resolver::StateNoChange);
     if (error_code(nextFile) == InputGraphError::no_more_files)
       break;
     if (nextFile->kind() == File::kindObject)

Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=192269&r1=192268&r2=192269&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdDriver.cpp Tue Oct  8 22:40:29 2013
@@ -254,7 +254,7 @@ bool GnuLdDriver::parse(int argc, const
       break;
 
     case OPT_start_group: {
-      std::unique_ptr<InputElement> controlStart(new ELFGroup(*ctx));
+      std::unique_ptr<InputElement> controlStart(new ELFGroup(*ctx, index++));
       controlNodeStack.push(controlStart.get());
       (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
           ->processControlEnter();
@@ -266,13 +266,13 @@ bool GnuLdDriver::parse(int argc, const
       (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
           ->processControlExit();
       controlNodeStack.pop();
-      return true;
+      break;
 
     case OPT_INPUT:
     case OPT_l: {
       std::unique_ptr<InputElement> inputFile =
           std::move(std::unique_ptr<InputElement>(new ELFFileNode(
-              *ctx, inputArg->getValue(), searchPath, index, isWholeArchive,
+              *ctx, inputArg->getValue(), searchPath, index++, isWholeArchive,
               asNeeded, inputArg->getOption().getID() == OPT_l)));
       if (controlNodeStack.empty())
         inputGraph->addInputElement(std::move(inputFile));

Modified: lld/trunk/lib/Driver/InputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/InputGraph.cpp?rev=192269&r1=192268&r2=192269&view=diff
==============================================================================
--- lld/trunk/lib/Driver/InputGraph.cpp (original)
+++ lld/trunk/lib/Driver/InputGraph.cpp Tue Oct  8 22:40:29 2013
@@ -53,6 +53,7 @@ bool InputGraph::dump(raw_ostream &diagn
   return true;
 }
 
+/// \brief Insert element at position
 void InputGraph::insertElementsAt(
     std::vector<std::unique_ptr<InputElement> > inputElements,
     Position position, size_t pos) {
@@ -95,7 +96,11 @@ ErrorOr<void> InputGraph::setNextElement
 /// is initially set to -1, if the user wants to override its ordinal,
 /// let the user do it
 InputElement::InputElement(Kind type, int64_t ordinal)
-    : _kind(type), _ordinal(ordinal), _weight(0),
+    : _kind(type), _ordinal(ordinal), _weight(0) {}
+
+/// FileNode
+FileNode::FileNode(StringRef path, int64_t ordinal)
+    : InputElement(InputElement::Kind::File, ordinal), _path(path),
       _resolveState(Resolver::StateNoChange), _nextFileIndex(0) {}
 
 /// \brief Assign File ordinals for files contained
@@ -133,6 +138,14 @@ FileNode::readFile(const LinkingContext
   return error_code::success();
 }
 
+// Reset the next file that would be be processed by the resolver.
+// Reset the resolve state too.
+void FileNode::resetNextIndex() {
+  _nextFileIndex = 0;
+  setResolveState(Resolver::StateNoChange);
+}
+
+/// ControlNode
 
 /// \brief Assign File ordinals for files contained
 /// in the InputElement
@@ -141,9 +154,61 @@ void ControlNode::assignFileOrdinals(uin
     elem->assignFileOrdinals(startOrdinal);
 }
 
+/// \brief Get the resolver State. The return value of the resolve
+/// state for a control node is the or'ed value of the resolve states
+/// contained in it.
+uint32_t ControlNode::getResolveState() const {
+  uint32_t resolveState = Resolver::StateNoChange;
+  for (auto &elem : _elements)
+    resolveState |= elem->getResolveState();
+  return resolveState;
+}
+
+/// \brief Set the resolve state for the current element
+/// thats processed by the resolver.
+void ControlNode::setResolveState(uint32_t resolveState) {
+  if (_elements.size() == 0)
+    return;
+  _elements[_currentElementIndex]->setResolveState(resolveState);
+}
+
+/// SimpleFileNode
+
+SimpleFileNode::SimpleFileNode(StringRef path, int64_t ordinal)
+    : InputElement(InputElement::Kind::SimpleFile, ordinal), _path(path),
+      _nextFileIndex(0), _resolveState(Resolver::StateNoChange) {}
+
 /// \brief Assign File ordinals for files contained
 /// in the InputElement
 void SimpleFileNode::assignFileOrdinals(uint64_t &startOrdinal) {
   for (auto &file : _files)
     file->setOrdinalAndIncrement(startOrdinal);
 }
+
+/// Group
+
+/// \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.size() == 0)
+    return make_error_code(InputGraphError::no_more_files);
+  // If we have processed all the elements as part of this node
+  // check the resolver status for each input element and if the status
+  // has not changed, move onto the next file.
+  if (_nextElementIndex == _elements.size()) {
+    if (getResolveState() == Resolver::StateNoChange)
+      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 (error_code(file) == InputGraphError::no_more_files)
+    _nextElementIndex++;
+  else
+    return *file;
+  return getNextFile();
+}

Added: lld/trunk/test/elf/X86_64/Inputs/group/1.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/group/1.c?rev=192269&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/Inputs/group/1.c (added)
+++ lld/trunk/test/elf/X86_64/Inputs/group/1.c Tue Oct  8 22:40:29 2013
@@ -0,0 +1,8 @@
+int _start() {
+  return 0;
+}
+
+int main() {
+fn();
+return 0;
+}

Added: lld/trunk/test/elf/X86_64/Inputs/group/1.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/group/1.o?rev=192269&view=auto
==============================================================================
Binary files lld/trunk/test/elf/X86_64/Inputs/group/1.o (added) and lld/trunk/test/elf/X86_64/Inputs/group/1.o Tue Oct  8 22:40:29 2013 differ

Added: lld/trunk/test/elf/X86_64/Inputs/group/fn.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/group/fn.c?rev=192269&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/Inputs/group/fn.c (added)
+++ lld/trunk/test/elf/X86_64/Inputs/group/fn.c Tue Oct  8 22:40:29 2013
@@ -0,0 +1,4 @@
+int fn() {
+fn1();
+return 0;
+}

Added: lld/trunk/test/elf/X86_64/Inputs/group/fn.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/group/fn.o?rev=192269&view=auto
==============================================================================
Binary files lld/trunk/test/elf/X86_64/Inputs/group/fn.o (added) and lld/trunk/test/elf/X86_64/Inputs/group/fn.o Tue Oct  8 22:40:29 2013 differ

Added: lld/trunk/test/elf/X86_64/Inputs/group/fn1.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/group/fn1.c?rev=192269&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/Inputs/group/fn1.c (added)
+++ lld/trunk/test/elf/X86_64/Inputs/group/fn1.c Tue Oct  8 22:40:29 2013
@@ -0,0 +1,3 @@
+int fn1() {
+fn2();
+}

Added: lld/trunk/test/elf/X86_64/Inputs/group/fn1.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/group/fn1.o?rev=192269&view=auto
==============================================================================
Binary files lld/trunk/test/elf/X86_64/Inputs/group/fn1.o (added) and lld/trunk/test/elf/X86_64/Inputs/group/fn1.o Tue Oct  8 22:40:29 2013 differ

Added: lld/trunk/test/elf/X86_64/Inputs/group/fn2.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/group/fn2.c?rev=192269&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/Inputs/group/fn2.c (added)
+++ lld/trunk/test/elf/X86_64/Inputs/group/fn2.c Tue Oct  8 22:40:29 2013
@@ -0,0 +1,3 @@
+int fn2() {
+return 0;
+}

Added: lld/trunk/test/elf/X86_64/Inputs/group/fn2.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/group/fn2.o?rev=192269&view=auto
==============================================================================
Binary files lld/trunk/test/elf/X86_64/Inputs/group/fn2.o (added) and lld/trunk/test/elf/X86_64/Inputs/group/fn2.o Tue Oct  8 22:40:29 2013 differ

Added: lld/trunk/test/elf/X86_64/Inputs/group/group.sh
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/group/group.sh?rev=192269&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/Inputs/group/group.sh (added)
+++ lld/trunk/test/elf/X86_64/Inputs/group/group.sh Tue Oct  8 22:40:29 2013
@@ -0,0 +1,37 @@
+cat > 1.c << \!
+int _start() {
+  return 0;
+}
+
+int main() {
+fn();
+return 0;
+}
+!
+
+cat > fn.c << \!
+int fn() {
+fn1();
+return 0;
+}
+!
+
+cat > fn2.c << \!
+int fn2() {
+return 0;
+}
+!
+
+cat > fn1.c << \!
+int fn1() {
+fn2();
+}
+!
+
+gcc -c 1.c fn.c fn2.c fn1.c
+ar cr libfn.a fn.o fn2.o
+ar cr libfn1.a fn1.o
+lld -flavor gnu -target x86_64 1.o libfn.a libfn1.a -o x
+lld -flavor gnu -target x86_64 1.o --start-group libfn.a libfn1.a --end-group -o x
+lld -flavor gnu -target x86_64 1.o --start-group fn.o fn2.o fn1.o --end-group -o x
+lld -flavor gnu -target x86_64 1.o --start-group --whole-archive libfn.a --no-whole-archive libfn1.a --end-group -o x

Added: lld/trunk/test/elf/X86_64/Inputs/group/libfn.a
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/group/libfn.a?rev=192269&view=auto
==============================================================================
Binary files lld/trunk/test/elf/X86_64/Inputs/group/libfn.a (added) and lld/trunk/test/elf/X86_64/Inputs/group/libfn.a Tue Oct  8 22:40:29 2013 differ

Added: lld/trunk/test/elf/X86_64/Inputs/group/libfn1.a
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/group/libfn1.a?rev=192269&view=auto
==============================================================================
Binary files lld/trunk/test/elf/X86_64/Inputs/group/libfn1.a (added) and lld/trunk/test/elf/X86_64/Inputs/group/libfn1.a Tue Oct  8 22:40:29 2013 differ

Added: lld/trunk/test/elf/X86_64/startGroupEndGroup.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/startGroupEndGroup.test?rev=192269&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/startGroupEndGroup.test (added)
+++ lld/trunk/test/elf/X86_64/startGroupEndGroup.test Tue Oct  8 22:40:29 2013
@@ -0,0 +1,27 @@
+# This tests functionality of --start-group, --end-group
+
+# This link should fail with unresolve symbol
+RUN: not lld -flavor gnu -target x86_64 %p/Inputs/group/1.o %p/Inputs/group/libfn.a \
+RUN: %p/Inputs/group/libfn1.a -o x 2> %t.err
+
+# Test group
+RUN: lld -flavor gnu -target x86_64 %p/Inputs/group/1.o --start-group \
+RUN: %p/Inputs/group/libfn.a %p/Inputs/group/libfn1.a --end-group -o %t1
+
+# Mix object files in group
+RUN: lld -flavor gnu -target x86_64 %p/Inputs/group/1.o --start-group \
+RUN: %p/Inputs/group/fn.o %p/Inputs/group/fn2.o \
+RUN: %p/Inputs/group/fn1.o --end-group -o %t2
+
+# Mix Whole archive input, the group should not iterate the file libfn.a
+RUN: lld -flavor gnu -target x86_64 %p/Inputs/group/1.o --start-group \
+RUN: --whole-archive %p/Inputs/group/libfn.a --no-whole-archive %p/Inputs/group/libfn1.a --end-group -o %t3
+
+RUN: FileCheck --check-prefix=UNRESOLVED %s < %t.err
+RUN: llvm-nm %t1 | FileCheck -check-prefix=RESOLVEDEXTERNAL %s
+RUN: llvm-nm %t2 | FileCheck -check-prefix=RESOLVEDEXTERNAL %s
+RUN: llvm-nm %t3 | FileCheck -check-prefix=RESOLVEDEXTERNAL %s
+
+UNRESOLVED: Undefined Symbol: {{[\/0-9A-Za-z_]+}}libfn1.a(fn1.o) : fn2
+
+RESOLVEDEXTERNAL: {{[0-9a-z]+}} T fn2





More information about the llvm-commits mailing list