Support SHF_MERGE sections in COMDATs.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 25 Feb 2015 00:52:15 +0000 (00:52 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 25 Feb 2015 00:52:15 +0000 (00:52 +0000)
This patch unifies the comdat and non-comdat code paths. By doing this
it add missing features to the comdat side and removes the fixed
section assumptions from the non-comdat side.

In ELF there is no one true section for "4 byte mergeable" constants.
We are better off computing the required properties of the section
and asking the context for it.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230411 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/TargetLoweringObjectFileImpl.cpp
test/CodeGen/X86/global-sections-comdat.ll

index 49d0b091e317f24f0a6fc0cf518920cb7cae17a3..c1b34f7f55fda59662a5d00698ddd1d39e1068f4 100644 (file)
@@ -164,9 +164,7 @@ static unsigned getELFSectionType(StringRef Name, SectionKind K) {
   return ELF::SHT_PROGBITS;
 }
 
-
-static unsigned
-getELFSectionFlags(SectionKind K, bool InCOMDAT) {
+static unsigned getELFSectionFlags(SectionKind K) {
   unsigned Flags = 0;
 
   if (!K.isMetadata())
@@ -181,10 +179,7 @@ getELFSectionFlags(SectionKind K, bool InCOMDAT) {
   if (K.isThreadLocal())
     Flags |= ELF::SHF_TLS;
 
-  // FIXME: There is nothing in ELF preventing an SHF_MERGE from being
-  // in a comdat. We just avoid it for now because we don't print
-  // those .sections correctly.
-  if (!InCOMDAT && (K.isMergeableCString() || K.isMergeableConst()))
+  if (K.isMergeableCString() || K.isMergeableConst())
     Flags |= ELF::SHF_MERGE;
 
   if (K.isMergeableCString())
@@ -214,7 +209,7 @@ const MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
   Kind = getELFKindForNamedSection(SectionName, Kind);
 
   StringRef Group = "";
-  unsigned Flags = getELFSectionFlags(Kind, GV->hasComdat());
+  unsigned Flags = getELFSectionFlags(Kind);
   if (const Comdat *C = getELFComdat(GV)) {
     Group = C->getName();
     Flags |= ELF::SHF_GROUP;
@@ -249,97 +244,74 @@ static StringRef getSectionPrefixForGlobal(SectionKind Kind) {
   return ".data.rel.ro";
 }
 
-static const MCSection *
-getUniqueELFSection(MCContext &Ctx, const GlobalValue &GV, SectionKind Kind,
-                    Mangler &Mang, const TargetMachine &TM, unsigned Flags) {
-  StringRef Prefix = getSectionPrefixForGlobal(Kind);
-
-  SmallString<128> Name(Prefix);
-  bool UniqueSectionNames = TM.getUniqueSectionNames();
-  if (UniqueSectionNames) {
-    Name.push_back('.');
-    TM.getNameWithPrefix(Name, &GV, Mang, true);
-  }
-  StringRef Group = "";
-  if (const Comdat *C = getELFComdat(&GV)) {
-    Flags |= ELF::SHF_GROUP;
-    Group = C->getName();
-  }
-
-  return Ctx.getELFSection(Name, getELFSectionType(Name, Kind), Flags, 0, Group,
-                           !UniqueSectionNames);
-}
-
 const MCSection *TargetLoweringObjectFileELF::
 SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
                        Mangler &Mang, const TargetMachine &TM) const {
-  unsigned Flags = getELFSectionFlags(Kind, GV->hasComdat());
+  unsigned Flags = getELFSectionFlags(Kind);
 
   // If we have -ffunction-section or -fdata-section then we should emit the
   // global value to a uniqued section specifically for it.
-  bool EmitUniquedSection = false;
+  bool EmitUniqueSection = false;
   if (!(Flags & ELF::SHF_MERGE) && !Kind.isCommon()) {
     if (Kind.isText())
-      EmitUniquedSection = TM.getFunctionSections();
+      EmitUniqueSection = TM.getFunctionSections();
     else
-      EmitUniquedSection = TM.getDataSections();
+      EmitUniqueSection = TM.getDataSections();
   }
+  EmitUniqueSection |= GV->hasComdat();
 
-  if (EmitUniquedSection || GV->hasComdat())
-    return getUniqueELFSection(getContext(), *GV, Kind, Mang, TM, Flags);
+  unsigned EntrySize = 0;
+  if (Kind.isMergeableCString()) {
+    if (Kind.isMergeable2ByteCString()) {
+      EntrySize = 2;
+    } else if (Kind.isMergeable4ByteCString()) {
+      EntrySize = 4;
+    } else {
+      EntrySize = 1;
+      assert(Kind.isMergeable1ByteCString() && "unknown string width");
+    }
+  } else if (Kind.isMergeableConst()) {
+    if (Kind.isMergeableConst4()) {
+      EntrySize = 4;
+    } else if (Kind.isMergeableConst8()) {
+      EntrySize = 8;
+    } else {
+      assert(Kind.isMergeableConst16() && "unknown data width");
+      EntrySize = 16;
+    }
+  }
 
-  if (Kind.isText()) return TextSection;
+  StringRef Group = "";
+  if (const Comdat *C = getELFComdat(GV)) {
+    Flags |= ELF::SHF_GROUP;
+    Group = C->getName();
+  }
 
+  bool UniqueSectionNames = TM.getUniqueSectionNames();
+  SmallString<128> Name;
   if (Kind.isMergeableCString()) {
-
     // We also need alignment here.
     // FIXME: this is getting the alignment of the character, not the
     // alignment of the global!
     unsigned Align =
         TM.getDataLayout()->getPreferredAlignment(cast<GlobalVariable>(GV));
 
-    unsigned EntrySize = 1;
-    if (Kind.isMergeable2ByteCString())
-      EntrySize = 2;
-    else if (Kind.isMergeable4ByteCString())
-      EntrySize = 4;
-    else
-      assert(Kind.isMergeable1ByteCString() && "unknown string width");
-
     std::string SizeSpec = ".rodata.str" + utostr(EntrySize) + ".";
-    std::string Name = SizeSpec + utostr(Align);
-    return getContext().getELFSection(
-        Name, ELF::SHT_PROGBITS,
-        ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS, EntrySize, "");
+    Name = SizeSpec + utostr(Align);
+  } else if (Kind.isMergeableConst()) {
+    Name = ".rodata.cst";
+    Name += utostr(EntrySize);
+  } else {
+    Name = getSectionPrefixForGlobal(Kind);
   }
 
-  if (Kind.isMergeableConst()) {
-    if (Kind.isMergeableConst4() && MergeableConst4Section)
-      return MergeableConst4Section;
-    if (Kind.isMergeableConst8() && MergeableConst8Section)
-      return MergeableConst8Section;
-    if (Kind.isMergeableConst16() && MergeableConst16Section)
-      return MergeableConst16Section;
-    return ReadOnlySection;  // .const
+  if (EmitUniqueSection && UniqueSectionNames) {
+    Name.push_back('.');
+    TM.getNameWithPrefix(Name, GV, Mang, true);
   }
-
-  if (Kind.isReadOnly())             return ReadOnlySection;
-
-  if (Kind.isThreadData())           return TLSDataSection;
-  if (Kind.isThreadBSS())            return TLSBSSSection;
-
-  // Note: we claim that common symbols are put in BSSSection, but they are
-  // really emitted with the magic .comm directive, which creates a symbol table
-  // entry but not a section.
-  if (Kind.isBSS() || Kind.isCommon()) return BSSSection;
-
-  if (Kind.isDataNoRel())            return DataSection;
-  if (Kind.isDataRelLocal())         return DataRelLocalSection;
-  if (Kind.isDataRel())              return DataRelSection;
-  if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection;
-
-  assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
-  return DataRelROSection;
+  return getContext().getELFSection(Name, getELFSectionType(Name, Kind), Flags,
+                                    EntrySize, Group,
+                                    EmitUniqueSection && !UniqueSectionNames);
 }
 
 const MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
@@ -351,8 +323,7 @@ const MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
   if (!EmitUniqueSection)
     return ReadOnlySection;
 
-  return getUniqueELFSection(getContext(), F, SectionKind::getReadOnly(), Mang,
-                             TM, ELF::SHF_ALLOC);
+  return SelectSectionForGlobal(&F, SectionKind::getReadOnly(), Mang, TM);
 }
 
 bool TargetLoweringObjectFileELF::shouldPutJumpTableInFunctionSection(
index 7b4d74c2a33ea989d9d626273ca8f807124c9b2d..730050dda5f30ebaf969bbfd60b23a56531f98e6 100644 (file)
@@ -41,6 +41,6 @@ bb5:
 $G16 = comdat any
 @G16 = unnamed_addr constant i32 42, comdat
 
-; LINUX: .section      .rodata.G16,"aG",@progbits,G16,comdat
-; LINUX-SECTIONS: .section     .rodata.G16,"aG",@progbits,G16,comdat
-; LINUX-SECTIONS-SHORT: .section       .rodata,"aG",@progbits,G16,comdat
+; LINUX: .section      .rodata.cst4.G16,"aGM",@progbits,4,G16,comdat
+; LINUX-SECTIONS: .section     .rodata.cst4.G16,"aGM",@progbits,4,G16,comdat
+; LINUX-SECTIONS-SHORT: .section       .rodata.cst4,"aGM",@progbits,4,G16,comdat