[lld] r204830 - [core] add SectionGroup support

Shankar Easwaran shankarke at gmail.com
Wed Mar 26 09:37:14 PDT 2014


Author: shankare
Date: Wed Mar 26 11:37:13 2014
New Revision: 204830

URL: http://llvm.org/viewvc/llvm-project?rev=204830&view=rev
Log:
[core] add SectionGroup support

Review : http://llvm-reviews.chandlerc.com/D3182

Added:
    lld/trunk/test/core/sectiongroup-rearrange-resolve.objtxt
    lld/trunk/test/core/sectiongroup-remaining-undef.objtxt
    lld/trunk/test/core/sectiongroup-resolve.objtxt
    lld/trunk/test/core/sectiongroup-simple.objtxt
Modified:
    lld/trunk/docs/design.rst
    lld/trunk/include/lld/Core/DefinedAtom.h
    lld/trunk/include/lld/Core/Reference.h
    lld/trunk/include/lld/Core/Resolver.h
    lld/trunk/include/lld/Core/SymbolTable.h
    lld/trunk/lib/Core/DefinedAtom.cpp
    lld/trunk/lib/Core/Resolver.cpp
    lld/trunk/lib/Core/SymbolTable.cpp
    lld/trunk/lib/ReaderWriter/Native/WriterNative.cpp
    lld/trunk/lib/ReaderWriter/Reader.cpp
    lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp

Modified: lld/trunk/docs/design.rst
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/docs/design.rst?rev=204830&r1=204829&r2=204830&view=diff
==============================================================================
--- lld/trunk/docs/design.rst (original)
+++ lld/trunk/docs/design.rst Wed Mar 26 11:37:13 2014
@@ -150,6 +150,37 @@ into an Atom graph.  For instance, you m
 certain architectures.  The options class can be instantiated from command
 line options, or it can be subclassed and the ivars programmatically set.
 
+ELF Section Groups
+~~~~~~~~~~~~~~~~~~
+Reference : `ELF Section Groups <http://mentorembedded.github.io/cxx-abi/abi/prop-72-comdat.html>`_
+
+C++ has many situations where the compiler may need to emit code or data,
+but may not be able to identify a unique compilation unit where it should be
+emitted. The approach chosen by the C++ ABI group to deal with this problem, is
+to allow the compiler to emit the required information in multiple compilation
+units, in a form which allows the linker to remove all but one copy. This is
+essentially the feature called COMDAT in several existing implementations.
+
+The COMDAT sections in ELF are modeled by using '.group' sections in the input
+files. Each '.group' section is associated with a signature. The '.group'
+section has a list of members that are part of the the '.group' which the linker
+selects to appear in the input file(Whichever .group section appeared first
+in the link). References to any of the '.group' members can also appear from
+outside the '.group'.
+
+In lld the the '.group' sections with COMDAT are identified by contentType(
+typeGroupComdat). The '.group' members are identified by using
+**kindGroupChild** references. The group child members have a reference to the
+group section by using **kindGroupParent** references.
+
+The point to be noted here is the 'group child' members would need to be emitted
+in the output file **iff** the group was selected by the resolver.
+
+This is modeled in lld by removing the 'group child' members from the
+definedAtom List.
+
+Any reference to the group-child from **outside the group** is referenced using
+a 'undefined' atom.
 
 Resolving
 ~~~~~~~~~

Modified: lld/trunk/include/lld/Core/DefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=204830&r1=204829&r2=204830&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/DefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/DefinedAtom.h Wed Mar 26 11:37:13 2014
@@ -146,6 +146,7 @@ public:
     typeRONote,             // Identifies readonly note sections [ELF]
     typeRWNote,             // Identifies readwrite note sections [ELF]
     typeNoAlloc,            // Identifies non allocatable sections [ELF]
+    typeGroupComdat,        // Identifies a section group [ELF, COFF]
   };
 
   // Permission bits for atoms and segments. The order of these values are

Modified: lld/trunk/include/lld/Core/Reference.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Reference.h?rev=204830&r1=204829&r2=204830&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Reference.h (original)
+++ lld/trunk/include/lld/Core/Reference.h Wed Mar 26 11:37:13 2014
@@ -76,9 +76,11 @@ public:
 
   /// KindValues used with KindNamespace::all and KindArch::all.
   enum {
-    kindInGroup      = 1,
-    kindLayoutAfter  = 2,
-    kindLayoutBefore = 3
+    kindInGroup = 1,
+    kindLayoutAfter = 2,
+    kindLayoutBefore = 3,
+    kindGroupChild = 4,
+    kindGroupParent = 5
   };
 
   // A value to be added to the value of a target

Modified: lld/trunk/include/lld/Core/Resolver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=204830&r1=204829&r2=204830&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Resolver.h (original)
+++ lld/trunk/include/lld/Core/Resolver.h Wed Mar 26 11:37:13 2014
@@ -67,6 +67,9 @@ public:
 private:
   typedef std::function<void(StringRef, bool)> UndefCallback;
 
+  /// \brief Add section group if it does not exist previously.
+  void maybeAddSectionGroup(const DefinedAtom &atom);
+
   /// \brief The main function that iterates over the files to resolve
   bool resolveUndefines();
   void updateReferences();

Modified: lld/trunk/include/lld/Core/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/SymbolTable.h?rev=204830&r1=204829&r2=204830&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/SymbolTable.h (original)
+++ lld/trunk/include/lld/Core/SymbolTable.h Wed Mar 26 11:37:13 2014
@@ -72,6 +72,13 @@ public:
   /// @brief if atom has been coalesced away, return replacement, else return atom
   const Atom *replacement(const Atom *);
 
+  /// @brief Find a group atom.
+  const Atom *findGroup(StringRef name);
+
+  /// @brief Add a group atom and returns true/false depending on whether the
+  /// previously existed.
+  bool addGroup(const DefinedAtom &da);
+
 private:
   typedef llvm::DenseMap<const Atom *, const Atom *> AtomToAtom;
 
@@ -101,6 +108,7 @@ private:
   const LinkingContext &_context;
   AtomToAtom _replacedAtoms;
   NameToAtom _nameTable;
+  NameToAtom _groupTable;
   AtomContentSet _contentTable;
 };
 

Modified: lld/trunk/lib/Core/DefinedAtom.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/DefinedAtom.cpp?rev=204830&r1=204829&r2=204830&view=diff
==============================================================================
--- lld/trunk/lib/Core/DefinedAtom.cpp (original)
+++ lld/trunk/lib/Core/DefinedAtom.cpp Wed Mar 26 11:37:13 2014
@@ -71,6 +71,7 @@ DefinedAtom::ContentPermissions DefinedA
   case typeThreadZeroFill:
     return permRW_L;
 
+  case typeGroupComdat:
   case typeUnknown:
   case typeTempLTO:
     return permUnknown;

Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=204830&r1=204829&r2=204830&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Wed Mar 26 11:37:13 2014
@@ -183,6 +183,25 @@ void Resolver::doUndefinedAtom(const Und
   _symbolTable.add(atom);
 }
 
+/// \brief Add the section group and the group-child reference members.
+void Resolver::maybeAddSectionGroup(const DefinedAtom &atom) {
+  // First time adding a group ?
+  bool isFirstTime = _symbolTable.addGroup(atom);
+  if (!isFirstTime)
+    return;
+
+  for (const Reference *r : atom) {
+    if ((r->kindNamespace() == lld::Reference::KindNamespace::all) &&
+        (r->kindValue() == lld::Reference::kindGroupChild)) {
+      const DefinedAtom *target = llvm::dyn_cast<DefinedAtom>(r->target());
+      assert(target && "Internal Error: kindGroupChild references need to "
+                       "be associated with Defined Atoms only");
+      _atoms.push_back(target);
+      _symbolTable.add(*target);
+    }
+  }
+}
+
 // called on each atom when a file is added
 void Resolver::doDefinedAtom(const DefinedAtom &atom) {
   DEBUG_WITH_TYPE("resolver", llvm::dbgs()
@@ -210,8 +229,10 @@ void Resolver::doDefinedAtom(const Defin
   // add to list of known atoms
   _atoms.push_back(&atom);
 
-  // tell symbol table
-  _symbolTable.add(atom);
+  if (atom.contentType() == DefinedAtom::typeGroupComdat)
+    maybeAddSectionGroup(atom);
+  else
+    _symbolTable.add(atom);
 
   if (_context.deadStrip()) {
     // add to set of dead-strip-roots, all symbols that

Modified: lld/trunk/lib/Core/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/SymbolTable.cpp?rev=204830&r1=204829&r2=204830&view=diff
==============================================================================
--- lld/trunk/lib/Core/SymbolTable.cpp (original)
+++ lld/trunk/lib/Core/SymbolTable.cpp Wed Mar 26 11:37:13 2014
@@ -32,17 +32,11 @@
 namespace lld {
 SymbolTable::SymbolTable(const LinkingContext &context) : _context(context) {}
 
-void SymbolTable::add(const UndefinedAtom &atom) {
-  this->addByName(atom);
-}
+void SymbolTable::add(const UndefinedAtom &atom) { addByName(atom); }
 
-void SymbolTable::add(const SharedLibraryAtom &atom) {
-  this->addByName(atom);
-}
+void SymbolTable::add(const SharedLibraryAtom &atom) { addByName(atom); }
 
-void SymbolTable::add(const AbsoluteAtom &atom) {
-  this->addByName(atom);
-}
+void SymbolTable::add(const AbsoluteAtom &atom) { addByName(atom); }
 
 void SymbolTable::add(const DefinedAtom &atom) {
   if (!atom.name().empty() &&
@@ -50,14 +44,33 @@ void SymbolTable::add(const DefinedAtom
     // Named atoms cannot be merged by content.
     assert(atom.merge() != DefinedAtom::mergeByContent);
     // Track named atoms that are not scoped to file (static).
-    this->addByName(atom);
+    addByName(atom);
     return;
   }
   if (atom.merge() == DefinedAtom::mergeByContent) {
     // Named atoms cannot be merged by content.
     assert(atom.name().empty());
-    this->addByContent(atom);
+    addByContent(atom);
+  }
+}
+
+const Atom *SymbolTable::findGroup(StringRef sym) {
+  NameToAtom::iterator pos = _groupTable.find(sym);
+  if (pos == _groupTable.end())
+    return nullptr;
+  return pos->second;
+}
+
+bool SymbolTable::addGroup(const DefinedAtom &da) {
+  StringRef name = da.name();
+  assert(!name.empty());
+  const Atom *existing = findGroup(name);
+  if (existing == nullptr) {
+    _groupTable[name] = &da;
+    return true;
   }
+  _replacedAtoms[&da] = existing;
+  return false;
 }
 
 enum NameCollisionResolution {
@@ -149,7 +162,7 @@ static uint64_t sectionSize(const Define
 void SymbolTable::addByName(const Atom &newAtom) {
   StringRef name = newAtom.name();
   assert(!name.empty());
-  const Atom *existing = this->findByName(name);
+  const Atom *existing = findByName(name);
   if (existing == nullptr) {
     // Name is not in symbol table yet, add it associate with this atom.
     _nameTable[name] = &newAtom;
@@ -351,7 +364,7 @@ const Atom *SymbolTable::findByName(Stri
 }
 
 bool SymbolTable::isDefined(StringRef sym) {
-  const Atom *atom = this->findByName(sym);
+  const Atom *atom = findByName(sym);
   if (atom == nullptr)
     return false;
   return atom->definition() != Atom::definitionUndefined;
@@ -367,7 +380,7 @@ const Atom *SymbolTable::replacement(con
   if (pos == _replacedAtoms.end())
     return atom;
   // might be chain, recurse to end
-  return this->replacement(pos->second);
+  return replacement(pos->second);
 }
 
 unsigned int SymbolTable::size() {

Modified: lld/trunk/lib/ReaderWriter/Native/WriterNative.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/Native/WriterNative.cpp?rev=204830&r1=204829&r2=204830&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/Native/WriterNative.cpp (original)
+++ lld/trunk/lib/ReaderWriter/Native/WriterNative.cpp Wed Mar 26 11:37:13 2014
@@ -38,6 +38,22 @@ public:
     // visit all atoms
     for ( const DefinedAtom *defAtom : file.defined() ) {
       this->addIVarsForDefinedAtom(*defAtom);
+      // We are trying to process all atoms, but the defined() iterator does not
+      // return group children. So, when a group parent is found, we need to
+      // handle each child atom.
+      if (defAtom->contentType() == DefinedAtom::typeGroupComdat) {
+        for (const Reference *r : *defAtom) {
+          if (r->kindNamespace() != lld::Reference::KindNamespace::all)
+            continue;
+          if (r->kindValue() == lld::Reference::kindGroupChild) {
+            const DefinedAtom *target =
+                llvm::dyn_cast<DefinedAtom>(r->target());
+            assert(target && "Internal Error: kindGroupChild references need "
+                             "to be associated with Defined Atoms only");
+            this->addIVarsForDefinedAtom(*target);
+          }
+        }
+      }
     }
     for ( const UndefinedAtom *undefAtom : file.undefined() ) {
       this->addIVarsForUndefinedAtom(*undefAtom);

Modified: lld/trunk/lib/ReaderWriter/Reader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/Reader.cpp?rev=204830&r1=204829&r2=204830&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/Reader.cpp (original)
+++ lld/trunk/lib/ReaderWriter/Reader.cpp Wed Mar 26 11:37:13 2014
@@ -54,11 +54,12 @@ Registry::parseFile(std::unique_ptr<Memo
 }
 
 static const Registry::KindStrings kindStrings[] = {
-  { Reference::kindInGroup,      "in-group" },
-  { Reference::kindLayoutAfter,  "layout-after" },
-  { Reference::kindLayoutBefore, "layout-before" },
-  LLD_KIND_STRING_END
-};
+    {Reference::kindInGroup, "in-group"},
+    {Reference::kindLayoutAfter, "layout-after"},
+    {Reference::kindLayoutBefore, "layout-before"},
+    {Reference::kindGroupChild, "group-child"},
+    {Reference::kindGroupParent, "group-parent"},
+    LLD_KIND_STRING_END};
 
 Registry::Registry() {
   addKindTable(Reference::KindNamespace::all, Reference::KindArch::all,

Modified: lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp?rev=204830&r1=204829&r2=204830&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp (original)
+++ lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp Wed Mar 26 11:37:13 2014
@@ -71,6 +71,15 @@ public:
       if (!atom->name().empty())
         buildDuplicateNameMap(*atom);
 
+      if (atom->contentType() == DefinedAtom::typeGroupComdat) {
+        for (const lld::Reference *ref : *atom) {
+          if (ref->kindNamespace() != lld::Reference::KindNamespace::all)
+            continue;
+          if (ref->kindValue() == lld::Reference::kindGroupChild)
+            buildDuplicateNameMap(*ref->target());
+        }
+      }
+
       // Find references to unnamed atoms and create ref-names for them.
       for (const lld::Reference *ref : *atom) {
         // create refname for any unnamed reference target
@@ -176,16 +185,59 @@ public:
     NameToAtom::const_iterator pos = _nameMap.find(name);
     if (pos != _nameMap.end()) {
       return pos->second;
+    } else if ((pos = _groupChild.find(name)) != _groupChild.end()) {
+      return pos->second;
     } else {
       _io.setError(Twine("no such atom name: ") + name);
       return nullptr;
     }
   }
 
+  /// \brief Lookup a group parent when there is a reference of type
+  /// kindGroupParent. If there was no group-parent produce an appropriate
+  /// error.
+  const lld::Atom *lookupGroupParent(StringRef name) const {
+    NameToAtom::const_iterator pos = _groupMap.find(name);
+    if (pos != _groupMap.end())
+      return pos->second;
+    _io.setError(Twine("no such group name: ") + name);
+    return nullptr;
+  }
+
+  /// \brief Lookup a group child when there is a reference of type
+  /// kindGroupChild. If there was no group-child produce an appropriate
+  /// error.
+  const lld::Atom *lookupGroupChild(StringRef name) const {
+    NameToAtom::const_iterator pos = _groupChild.find(name);
+    if (pos != _groupChild.end())
+      return pos->second;
+    _io.setError(Twine("no such group child: ") + name);
+    return nullptr;
+  }
+
 private:
   typedef llvm::StringMap<const lld::Atom *> NameToAtom;
 
-  void add(StringRef name, const lld::Atom *atom) {
+  void add(StringRef name, const lld::Atom *atom, bool isGroupChild = false) {
+    if (isGroupChild) {
+      if (_groupChild.count(name)) {
+        _io.setError(Twine("duplicate group child: ") + name);
+      } else {
+        _groupChild[name] = atom;
+      }
+      return;
+    }
+
+    if (const lld::DefinedAtom *da = dyn_cast<DefinedAtom>(atom)) {
+      if (da->contentType() == DefinedAtom::typeGroupComdat) {
+        if (_groupMap.count(name)) {
+          _io.setError(Twine("duplicate group name: ") + name);
+        } else {
+          _groupMap[name] = atom;
+        }
+        return;
+      }
+    }
     if (_nameMap.count(name)) {
       _io.setError(Twine("duplicate atom name: ") + name);
     } else {
@@ -195,6 +247,8 @@ private:
 
   IO &_io;
   NameToAtom _nameMap;
+  NameToAtom _groupMap;
+  NameToAtom _groupChild;
 };
 
 // Used in NormalizedFile to hold the atoms lists.
@@ -422,6 +476,7 @@ template <> struct ScalarEnumerationTrai
     io.enumCase(value, "ro-note",         DefinedAtom::typeRONote);
     io.enumCase(value, "rw-note",         DefinedAtom::typeRWNote);
     io.enumCase(value, "no-alloc",        DefinedAtom::typeNoAlloc);
+    io.enumCase(value, "group-comdat", DefinedAtom::typeGroupComdat);
   }
 };
 
@@ -761,7 +816,7 @@ template <> struct MappingTraits<const l
   public:
     NormalizedAtom(IO &io)
         : _file(fileFromContext(io)), _name(), _refName(), _contentType(),
-          _alignment(0), _content(), _references() {
+          _alignment(0), _content(), _references(), _isGroupChild(false) {
       static uint32_t ordinalCounter = 1;
       _ordinal = ordinalCounter++;
     }
@@ -774,8 +829,15 @@ template <> struct MappingTraits<const l
           _deadStrip(atom->deadStrip()), _dynamicExport(atom->dynamicExport()),
           _permissions(atom->permissions()), _size(atom->size()),
           _sectionName(atom->customSectionName()) {
-      for (const lld::Reference *r : *atom)
+      for (const lld::Reference *r : *atom) {
+        // If this is not a group child as yet, lets keep looking
+        // at all the references.
+        if (!_isGroupChild &&
+            r->kindNamespace() == lld::Reference::KindNamespace::all &&
+            r->kindValue() == lld::Reference::kindGroupParent)
+          _isGroupChild = true;
         _references.push_back(r);
+      }
       if (!atom->occupiesDiskSpace())
         return;
       ArrayRef<uint8_t> cont = atom->rawContent();
@@ -824,6 +886,7 @@ template <> struct MappingTraits<const l
     DynamicExport dynamicExport() const override { return _dynamicExport; }
     ContentPermissions permissions() const override { return _permissions; }
     bool isAlias() const override { return false; }
+    bool isGroupChild() const { return _isGroupChild; }
     ArrayRef<uint8_t> rawContent() const override {
       if (!occupiesDiskSpace())
         return ArrayRef<uint8_t>();
@@ -872,6 +935,7 @@ template <> struct MappingTraits<const l
     uint64_t                            _size;
     StringRef                           _sectionName;
     std::vector<const lld::Reference *> _references;
+    bool _isGroupChild;
   };
 
   static void mapping(IO &io, const lld::DefinedAtom *&atom) {
@@ -917,6 +981,16 @@ template <> struct MappingTraits<const l
                                          DefinedAtom::permissions(
                                                           keys->_contentType));
     io.mapOptional("references",       keys->_references);
+    for (const lld::Reference *r : keys->_references) {
+      // If this is not a group child as yet, lets keep looking
+      // at all the references.
+      if (!keys->_isGroupChild &&
+          r->kindNamespace() == lld::Reference::KindNamespace::all &&
+          r->kindValue() == lld::Reference::kindGroupParent) {
+        keys->_isGroupChild = true;
+        break;
+      }
+    }
   }
 };
 
@@ -1121,9 +1195,9 @@ RefNameResolver::RefNameResolver(const l
   for (const lld::DefinedAtom *a : file->defined()) {
     NormalizedAtom *na = (NormalizedAtom *)a;
     if (!na->_refName.empty())
-      add(na->_refName, a);
+      add(na->_refName, a, na->isGroupChild());
     else if (!na->_name.empty())
-      add(na->_name, a);
+      add(na->_name, a, na->isGroupChild());
   }
 
   for (const lld::UndefinedAtom *a : file->undefined())
@@ -1153,6 +1227,14 @@ MappingTraits<const lld::File *>::Normal
     NormalizedAtom *normAtom = (NormalizedAtom *)a;
     normAtom->bind(nameResolver);
   }
+
+  _definedAtoms._atoms.erase(std::remove_if(_definedAtoms._atoms.begin(),
+                                            _definedAtoms._atoms.end(),
+                                            [](const DefinedAtom *a) {
+                               return ((NormalizedAtom *)a)->isGroupChild();
+                             }),
+                             _definedAtoms._atoms.end());
+
   return this;
 }
 
@@ -1168,6 +1250,16 @@ inline void MappingTraits<const lld::Def
 
 inline void MappingTraits<const lld::Reference *>::NormalizedReference::bind(
     const RefNameResolver &resolver) {
+  if (_mappedKind.ns == lld::Reference::KindNamespace::all) {
+    if (_mappedKind.value == lld::Reference::kindGroupParent) {
+      _target = resolver.lookupGroupParent(_targetName);
+      return;
+    }
+    if (_mappedKind.value == lld::Reference::kindGroupChild) {
+      _target = resolver.lookupGroupChild(_targetName);
+      return;
+    }
+  }
   _target = resolver.lookup(_targetName);
 }
 

Added: lld/trunk/test/core/sectiongroup-rearrange-resolve.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/core/sectiongroup-rearrange-resolve.objtxt?rev=204830&view=auto
==============================================================================
--- lld/trunk/test/core/sectiongroup-rearrange-resolve.objtxt (added)
+++ lld/trunk/test/core/sectiongroup-rearrange-resolve.objtxt Wed Mar 26 11:37:13 2014
@@ -0,0 +1,115 @@
+# RUN: lld -core %s | FileCheck %s
+
+#
+# Test that section groups are parsed and the first group selected for symbol
+# resolution
+#
+
+---
+defined-atoms:
+  - name:            g1
+    scope:           global
+    type:            group-comdat
+    references:
+      - kind:            group-child
+        target:          f1
+      - kind:            group-child
+        target:          f2
+      - kind:            group-child
+        target:          g1
+      - kind:            group-child
+        target:          d1
+  - name:            f1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            f2
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            g1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            d1
+    scope:           global
+    type:            data
+    references:
+      - kind:            group-parent
+        target:          g1
+---
+defined-atoms:
+  - name:            g1
+    scope:           global
+    type:            group-comdat
+    references:
+      - kind:            group-child
+        target:          f1
+      - kind:            group-child
+        target:          f2
+      - kind:            group-child
+        target:          g1
+      - kind:            group-child
+        target:          d1
+  - name:            f1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            f2
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            g1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            d1
+    scope:           global
+    type:            data
+    references:
+      - kind:            group-parent
+        target:          g1
+...
+
+# CHECK: defined-atoms:
+# CHECK:   - name:            g1
+# CHECK:     ref-name:        [[PARENT:[a-zA-Z\.0-9_]+]]
+# CHECK:     type:            group-comdat
+# CHECK:     references:
+# CHECK:       - kind:            group-child
+# CHECK:         target:          f1
+# CHECK:       - kind:            group-child
+# CHECK:         target:          f2
+# CHECK:       - kind:            group-child
+# CHECK:         target:          [[CHILD:[a-zA-Z\.0-9_]+]]
+# CHECK:       - kind:            group-child
+# CHECK:         target:          d1
+# CHECK:   - name:            f1
+# CHECK:     references:
+# CHECK:       - kind:            group-parent
+# CHECK:         target:          [[PARENT]]
+# CHECK:   - name:            f2
+# CHECK:     references:
+# CHECK:       - kind:            group-parent
+# CHECK:         target:          [[PARENT]]
+# CHECK:   - name:            g1
+# CHECK:     ref-name:        [[CHILD]]
+# CHECK:     references:
+# CHECK:       - kind:            group-parent
+# CHECK:         target:          [[PARENT]]
+# CHECK:   - name:            d1
+# CHECK:     references:
+# CHECK:       - kind:            group-parent
+# CHECK:         target:          [[PARENT]]

Added: lld/trunk/test/core/sectiongroup-remaining-undef.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/core/sectiongroup-remaining-undef.objtxt?rev=204830&view=auto
==============================================================================
--- lld/trunk/test/core/sectiongroup-remaining-undef.objtxt (added)
+++ lld/trunk/test/core/sectiongroup-remaining-undef.objtxt Wed Mar 26 11:37:13 2014
@@ -0,0 +1,113 @@
+# RUN: lld -core %s | FileCheck %s
+
+#
+# Test that section groups are parsed and the first group selected for symbol
+# resolution. The second file which has the same group has a unresolved
+# undefined symbol. lets make sure that the symbol is kept around in the final
+# link and remains undefined.
+#
+
+---
+defined-atoms:
+  - name:            f1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            f2
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            g1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            d1
+    scope:           global
+    type:            data
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            g1
+    scope:           global
+    type:            group-comdat
+    references:
+      - kind:            group-child
+        target:          f1
+      - kind:            group-child
+        target:          f2
+      - kind:            group-child
+        target:          g1
+      - kind:            group-child
+        target:          d1
+---
+defined-atoms:
+  - name:            anotherfunction
+    scope:           global
+    type:            data
+    references:
+      - kind:            layout-before
+        target:          f3
+  - name:            f1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            f2
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            f3
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            g1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            d1
+    scope:           global
+    type:            data
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            g1
+    scope:           global
+    type:            group-comdat
+    references:
+      - kind:            group-child
+        target:          f1
+      - kind:            group-child
+        target:          f2
+      - kind:            group-child
+        target:          f3
+      - kind:            group-child
+        target:          g1
+      - kind:            group-child
+        target:          d1
+undefined-atoms:
+    - name:              f3
+      can-be-null:       never
+...
+
+#CHECK:   - name:            anotherfunction
+#CHECK:     scope:           global
+#CHECK:     type:            data
+#CHECK:     references:
+#CHECK:       - kind:            layout-before
+#CHECK:         offset:          0
+#CHECK:         target:          f3
+#CHECK: undefined-atoms:
+#CHECK:   - name:            f3

Added: lld/trunk/test/core/sectiongroup-resolve.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/core/sectiongroup-resolve.objtxt?rev=204830&view=auto
==============================================================================
--- lld/trunk/test/core/sectiongroup-resolve.objtxt (added)
+++ lld/trunk/test/core/sectiongroup-resolve.objtxt Wed Mar 26 11:37:13 2014
@@ -0,0 +1,133 @@
+# RUN: lld -core %s | FileCheck %s
+
+#
+# Test that section groups are parsed and the first group selected for symbol
+# resolution
+#
+
+---
+defined-atoms:
+  - name:            f1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            f2
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            g1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            d1
+    scope:           global
+    type:            data
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            g1
+    scope:           global
+    type:            group-comdat
+    references:
+      - kind:            group-child
+        target:          f1
+      - kind:            group-child
+        target:          f2
+      - kind:            group-child
+        target:          g1
+      - kind:            group-child
+        target:          d1
+---
+defined-atoms:
+  - name:            f1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            f2
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            g1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            d1
+    scope:           global
+    type:            data
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            g1
+    scope:           global
+    type:            group-comdat
+    references:
+      - kind:            group-child
+        target:          f1
+      - kind:            group-child
+        target:          f2
+      - kind:            group-child
+        target:          g1
+      - kind:            group-child
+        target:          d1
+...
+
+#CHECK: defined-atoms:
+#CHECK:   - name:            g1
+#CHECK:     ref-name:        [[PARENT:[a-zA-Z\.0-9_]+]]
+#CHECK:     scope:           global
+#CHECK:     type:            group-comdat
+#CHECK:     references:
+#CHECK:       - kind:            group-child
+#CHECK:         offset:          0
+#CHECK:         target:          [[GCHILDONE:[a-zA-Z\.0-9_]+]]
+#CHECK:       - kind:            group-child
+#CHECK:         offset:          0
+#CHECK:         target:          [[GCHILDTWO:[a-zA-Z\.0-9_]+]]
+#CHECK:       - kind:            group-child
+#CHECK:         offset:          0
+#CHECK:         target:          [[GCHILDTHREE:[a-zA-Z\.0-9_]+]]
+#CHECK:       - kind:            group-child
+#CHECK:         offset:          0
+#CHECK:         target:          [[GCHILDFOUR:[a-zA-Z\.0-9_]+]]
+#CHECK:   - name:            f1
+#CHECK:     ref-name:        [[GCHILDONE]]
+#CHECK:     scope:           global
+#CHECK:     references:
+#CHECK:       - kind:            group-parent
+#CHECK:         offset:          0
+#CHECK:         target:          [[PARENT]]
+#CHECK:   - name:            f2
+#CHECK:     ref-name:        [[GCHILDTWO]]
+#CHECK:     scope:           global
+#CHECK:     references:
+#CHECK:       - kind:            group-parent
+#CHECK:         offset:          0
+#CHECK:         target:          [[PARENT]]
+#CHECK:   - name:            g1
+#CHECK:     ref-name:        [[GCHILDTHREE]]
+#CHECK:     scope:           global
+#CHECK:     references:
+#CHECK:       - kind:            group-parent
+#CHECK:         offset:          0
+#CHECK:         target:          [[PARENT]]
+#CHECK:   - name:            d1
+#CHECK:     ref-name:        [[GCHILDFOUR]]
+#CHECK:     scope:           global
+#CHECK:     type:            data
+#CHECK:     references:
+#CHECK:       - kind:            group-parent
+#CHECK:         offset:          0
+#CHECK:         target:          [[PARENT]]
+#CHECK: ...

Added: lld/trunk/test/core/sectiongroup-simple.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/core/sectiongroup-simple.objtxt?rev=204830&view=auto
==============================================================================
--- lld/trunk/test/core/sectiongroup-simple.objtxt (added)
+++ lld/trunk/test/core/sectiongroup-simple.objtxt Wed Mar 26 11:37:13 2014
@@ -0,0 +1,112 @@
+# RUN: lld -core %s | FileCheck %s
+
+#
+# Test that section groups are parsed properly when there is a reference to a
+# group atom from outside a group.
+#
+
+---
+defined-atoms:
+  - name:            f1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            f2
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            g1
+    scope:           global
+    type:            code
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            d1
+    scope:           global
+    type:            data
+    references:
+      - kind:            group-parent
+        target:          g1
+  - name:            g1
+    scope:           global
+    type:            group-comdat
+    references:
+      - kind:            group-child
+        target:          f1
+      - kind:            group-child
+        target:          f2
+      - kind:            group-child
+        target:          d1
+      - kind:            group-child
+        target:          g1
+  - name:            anotherfunction
+    scope:           global
+    type:            data
+    references:
+      - kind:            layout-before
+        target:          f1
+
+undefined-atoms:
+    - name:              f1
+      can-be-null:       never
+...
+
+#CHECK: defined-atoms:
+#CHECK:   - name:            g1
+#CHECK:     ref-name:        [[PARENT:[a-zA-Z\.0-9_]+]]
+#CHECK:     scope:           global
+#CHECK:     type:            group-comdat
+#CHECK:     references:
+#CHECK:       - kind:            group-child
+#CHECK:         offset:          0
+#CHECK:         target:          [[GCHILDONE:[a-zA-Z\.0-9_]+]]
+#CHECK:       - kind:            group-child
+#CHECK:         offset:          0
+#CHECK:         target:          [[GCHILDTWO:[a-zA-Z\.0-9_]+]]
+#CHECK:       - kind:            group-child
+#CHECK:         offset:          0
+#CHECK:         target:          [[GCHILDTHREE:[a-zA-Z\.0-9_]+]]
+#CHECK:       - kind:            group-child
+#CHECK:         offset:          0
+#CHECK:         target:          [[GCHILDFOUR:[a-zA-Z\.0-9_]+]]
+#CHECK:   - name:            f1
+#CHECK:     ref-name:        [[GCHILDONE]]
+#CHECK:     scope:           global
+#CHECK:     references:
+#CHECK:       - kind:            group-parent
+#CHECK:         offset:          0
+#CHECK:         target:          [[PARENT]]
+#CHECK:   - name:            f2
+#CHECK:     ref-name:        [[GCHILDTWO]]
+#CHECK:     scope:           global
+#CHECK:     references:
+#CHECK:       - kind:            group-parent
+#CHECK:         offset:          0
+#CHECK:         target:          [[PARENT]]
+#CHECK:   - name:            d1
+#CHECK:     ref-name:        [[GCHILDTHREE]]
+#CHECK:     scope:           global
+#CHECK:     type:            data
+#CHECK:     references:
+#CHECK:       - kind:            group-parent
+#CHECK:         offset:          0
+#CHECK:         target:          [[PARENT]]
+#CHECK:   - name:            g1
+#CHECK:     ref-name:        [[GCHILDFOUR]]
+#CHECK:     scope:           global
+#CHECK:     references:
+#CHECK:       - kind:            group-parent
+#CHECK:         offset:          0
+#CHECK:         target:          [[PARENT]]
+#CHECK:   - name:            anotherfunction
+#CHECK:     scope:           global
+#CHECK:     type:            data
+#CHECK:     references:
+#CHECK:       - kind:            layout-before
+#CHECK:         offset:          0
+#CHECK:         target:          [[GCHILDONE]]
+#CHECK: ...





More information about the llvm-commits mailing list