[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