[core] support .gnu.linkonce sections

.gnu.linkonce sections are similar to section groups.

They were supported before section groups existed and provided a way
to resolve COMDAT sections using a different design.

There are few implementations that use .gnu.linkonce sections
to store simple floating point constants which doesnot require complex section
group support but need a way to store only one copy of the floating point
constant in a binary.

.gnu.linkonce based symbol resolution achieves that.

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

llvm-svn: 205280
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp
index 9555fef..f8bcfbc 100644
--- a/lld/lib/Core/Resolver.cpp
+++ b/lld/lib/Core/Resolver.cpp
@@ -184,11 +184,24 @@
 }
 
 /// \brief Add the section group and the group-child reference members.
-void Resolver::maybeAddSectionGroup(const DefinedAtom &atom) {
+bool Resolver::maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom) {
   // First time adding a group ?
   bool isFirstTime = _symbolTable.addGroup(atom);
-  if (!isFirstTime)
-    return;
+
+  if (!isFirstTime) {
+    // If duplicate symbols are allowed, select the first group.
+    if (_context.getAllowDuplicates())
+      return true;
+    const DefinedAtom *prevGroup =
+        llvm::dyn_cast<DefinedAtom>(_symbolTable.findGroup(atom.name()));
+    assert(prevGroup &&
+           "Internal Error: The group atom could only be a defined atom");
+    // The atoms should be of the same content type, reject invalid group
+    // resolution behaviors.
+    if (atom.contentType() != prevGroup->contentType())
+      return false;
+    return true;
+  }
 
   for (const Reference *r : atom) {
     if ((r->kindNamespace() == lld::Reference::KindNamespace::all) &&
@@ -200,6 +213,7 @@
       _symbolTable.add(*target);
     }
   }
+  return true;
 }
 
 // called on each atom when a file is added
@@ -229,10 +243,16 @@
   // add to list of known atoms
   _atoms.push_back(&atom);
 
-  if (atom.contentType() == DefinedAtom::typeGroupComdat)
-    maybeAddSectionGroup(atom);
-  else
+  if (atom.isGroupParent()) {
+    // Raise error if there exists a similar gnu linkonce section.
+    if (!maybeAddSectionGroupOrGnuLinkOnce(atom)) {
+      llvm::errs() << "SymbolTable: error while merging " << atom.name()
+                   << "\n";
+      llvm::report_fatal_error("duplicate symbol error");
+    }
+  } else {
     _symbolTable.add(atom);
+  }
 
   if (_context.deadStrip()) {
     // add to set of dead-strip-roots, all symbols that