Implement unique sections with an unique ID.
authorRafael Espindola <rafael.espindola@gmail.com>
Sat, 4 Apr 2015 18:02:01 +0000 (18:02 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Sat, 4 Apr 2015 18:02:01 +0000 (18:02 +0000)
This allows the compiler/assembly programmer to switch back to a
section. This in turn fixes the bootstrap failure on powerpc (tested
on gcc110) without changing the ppc codegen at all.

I will try to cleanup the various getELFSection overloads in a  followup patch.
Just using a default argument now would lead to ambiguities.

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

18 files changed:
docs/Extensions.rst
include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
include/llvm/MC/MCContext.h
include/llvm/MC/MCSection.h
include/llvm/MC/MCSectionCOFF.h
include/llvm/MC/MCSectionELF.h
lib/CodeGen/TargetLoweringObjectFileImpl.cpp
lib/MC/MCContext.cpp
lib/MC/MCParser/ELFAsmParser.cpp
lib/MC/MCSectionELF.cpp
lib/MC/MCSectionMachO.cpp
lib/MC/MCStreamer.cpp
lib/Target/NVPTX/NVPTXSection.h
test/CodeGen/X86/global-sections-comdat.ll
test/MC/ELF/section-unique-err1.s [new file with mode: 0644]
test/MC/ELF/section-unique-err2.s [new file with mode: 0644]
test/MC/ELF/section-unique-err3.s [new file with mode: 0644]
test/MC/ELF/section-unique.s

index 271c08598b3f24b5bdcc87244ef88a2a6227c30a..12eac5e0ed8878e00cd8ca4c747e9c48c2df2791 100644 (file)
@@ -165,6 +165,29 @@ and ``.bar`` is associated to ``.foo``.
        .section        .foo,"bw",discard, "sym"
        .section        .bar,"rd",associative, "sym"
 
+
+ELF-Dependent
+-------------
+
+``.section`` Directive
+^^^^^^^^^^^^^^^^^^^^^^
+
+In order to support creating multiple sections with the same name and comdat,
+it is possible to add an unique number at the end of the ``.seciton`` directive.
+For example, the following code creates two sections named ``.text``.
+
+.. code-block:: gas
+
+       .section        .text,"ax",@progbits,unique 1
+        nop
+
+       .section        .text,"ax",@progbits,unique 2
+        nop
+
+
+The unique number is not present in the resulting object at all. It is just used
+in the assembler to differentiate the sections.
+
 Target Specific Behaviour
 =========================
 
index 75920a3fea4f9e98d06face06872778a62987314..232678ef1f8c41c9aefda25a880e37cc8b02d33f 100644 (file)
@@ -34,6 +34,7 @@ namespace llvm {
 
 class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
   bool UseInitArray;
+  mutable unsigned NextUniqueID = 0;
 
 public:
   TargetLoweringObjectFileELF() : UseInitArray(false) {}
index 63faeceec9df3a76d88f26c23d483a03b7a58f61..e06886445755080ca8b8f88b2879c577788924e8 100644 (file)
@@ -165,12 +165,17 @@ namespace llvm {
     struct ELFSectionKey {
       std::string SectionName;
       StringRef GroupName;
-      ELFSectionKey(StringRef SectionName, StringRef GroupName)
-          : SectionName(SectionName), GroupName(GroupName) {}
+      unsigned UniqueID;
+      ELFSectionKey(StringRef SectionName, StringRef GroupName,
+                    unsigned UniqueID)
+          : SectionName(SectionName), GroupName(GroupName), UniqueID(UniqueID) {
+      }
       bool operator<(const ELFSectionKey &Other) const {
         if (SectionName != Other.SectionName)
           return SectionName < Other.SectionName;
-        return GroupName < Other.GroupName;
+        if (GroupName != Other.GroupName)
+          return GroupName < Other.GroupName;
+        return UniqueID < Other.UniqueID;
       }
     };
 
@@ -303,7 +308,7 @@ namespace llvm {
 
     const MCSectionELF *getELFSection(StringRef Section, unsigned Type,
                                       unsigned Flags, unsigned EntrySize,
-                                      StringRef Group, bool Unique,
+                                      StringRef Group, unsigned UniqueID,
                                       const char *BeginSymName = nullptr);
 
     const MCSectionELF *createELFRelSection(StringRef Name, unsigned Type,
index fc0fc7bc8ffa2f5cd8235d7e38cef6f654c7a4e1..ab8968ef2baf0a4e6918b6d2a25f253fb38bccb0 100644 (file)
@@ -39,11 +39,10 @@ private:
   mutable MCSymbol *End;
 
 protected:
-  MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin, bool Unique)
-      : Begin(Begin), End(nullptr), Variant(V), Kind(K), Unique(Unique) {}
+  MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin)
+      : Begin(Begin), End(nullptr), Variant(V), Kind(K) {}
   SectionVariant Variant;
   SectionKind Kind;
-  bool Unique;
 
 public:
   virtual ~MCSection();
@@ -55,7 +54,6 @@ public:
   MCSymbol *getBeginSymbol() const { return Begin; }
   MCSymbol *getEndSymbol(MCContext &Ctx) const;
   bool hasEnded() const;
-  bool isUnique() const { return Unique; }
 
   virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS,
                                     const MCExpr *Subsection) const = 0;
index 201c4fae294027bedc0cf1962dc18b17ae37e3a7..b6ec1d852d4f6c3c47f71ff7915d208cbf9e3643 100644 (file)
@@ -47,7 +47,7 @@ class MCSymbol;
     MCSectionCOFF(StringRef Section, unsigned Characteristics,
                   MCSymbol *COMDATSymbol, int Selection, SectionKind K,
                   MCSymbol *Begin)
-        : MCSection(SV_COFF, K, Begin, /*Unique*/ false), SectionName(Section),
+        : MCSection(SV_COFF, K, Begin), SectionName(Section),
           Characteristics(Characteristics), COMDATSymbol(COMDATSymbol),
           Selection(Selection) {
       assert ((Characteristics & 0x00F00000) == 0 &&
index 2bbc81fd79b7c5143421c2a1f20c532375fce7d2..cd15741fe20ee3a4d167a23d43a07543e19690f0 100644 (file)
@@ -39,6 +39,8 @@ class MCSectionELF : public MCSection {
   /// below.
   unsigned Flags;
 
+  unsigned UniqueID;
+
   /// EntrySize - The size of each entry in this section. This size only
   /// makes sense for sections that contain fixed-sized entries. If a
   /// section does not contain fixed-sized entries 'EntrySize' will be 0.
@@ -49,10 +51,10 @@ class MCSectionELF : public MCSection {
 private:
   friend class MCContext;
   MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K,
-               unsigned entrySize, const MCSymbol *group, bool Unique,
+               unsigned entrySize, const MCSymbol *group, unsigned UniqueID,
                MCSymbol *Begin)
-      : MCSection(SV_ELF, K, Begin, Unique), SectionName(Section), Type(type),
-        Flags(flags), EntrySize(entrySize), Group(group) {}
+      : MCSection(SV_ELF, K, Begin), SectionName(Section), Type(type),
+        Flags(flags), UniqueID(UniqueID), EntrySize(entrySize), Group(group) {}
   ~MCSectionELF();
 
   void setSectionName(StringRef Name) { SectionName = Name; }
@@ -74,6 +76,9 @@ public:
   bool UseCodeAlign() const override;
   bool isVirtualSection() const override;
 
+  bool isUnique() const { return UniqueID != ~0U; }
+  unsigned getUniqueID() const { return UniqueID; }
+
   static bool classof(const MCSection *S) {
     return S->getVariant() == SV_ELF;
   }
index bcf2aa72c4bbd4a99fce6f9a7f6c574527f0c0f4..5b795e4b37be4f4dadebfd4c705f127557c5b086 100644 (file)
@@ -245,9 +245,11 @@ static StringRef getSectionPrefixForGlobal(SectionKind Kind) {
   return ".data.rel.ro";
 }
 
-static const MCSectionELF *selectELFSectionForGlobal(
-    MCContext &Ctx, const GlobalValue *GV, SectionKind Kind, Mangler &Mang,
-    const TargetMachine &TM, bool EmitUniqueSection, unsigned Flags) {
+static const MCSectionELF *
+selectELFSectionForGlobal(MCContext &Ctx, const GlobalValue *GV,
+                          SectionKind Kind, Mangler &Mang,
+                          const TargetMachine &TM, bool EmitUniqueSection,
+                          unsigned Flags, unsigned *NextUniqueID) {
   unsigned EntrySize = 0;
   if (Kind.isMergeableCString()) {
     if (Kind.isMergeable2ByteCString()) {
@@ -297,9 +299,13 @@ static const MCSectionELF *selectELFSectionForGlobal(
     Name.push_back('.');
     TM.getNameWithPrefix(Name, GV, Mang, true);
   }
+  unsigned UniqueID = ~0;
+  if (EmitUniqueSection && !UniqueSectionNames) {
+    UniqueID = *NextUniqueID;
+    (*NextUniqueID)++;
+  }
   return Ctx.getELFSection(Name, getELFSectionType(Name, Kind), Flags,
-                           EntrySize, Group,
-                           EmitUniqueSection && !UniqueSectionNames);
+                           EntrySize, Group, UniqueID);
 }
 
 const MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal(
@@ -319,7 +325,7 @@ const MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal(
   EmitUniqueSection |= GV->hasComdat();
 
   return selectELFSectionForGlobal(getContext(), GV, Kind, Mang, TM,
-                                   EmitUniqueSection, Flags);
+                                   EmitUniqueSection, Flags, &NextUniqueID);
 }
 
 const MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
@@ -332,7 +338,8 @@ const MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
     return ReadOnlySection;
 
   return selectELFSectionForGlobal(getContext(), &F, SectionKind::getReadOnly(),
-                                   Mang, TM, EmitUniqueSection, ELF::SHF_ALLOC);
+                                   Mang, TM, EmitUniqueSection, ELF::SHF_ALLOC,
+                                   &NextUniqueID);
 }
 
 bool TargetLoweringObjectFileELF::shouldPutJumpTableInFunctionSection(
index 6e7a3bc4db7f06ed6c91f8352de7d495c2d1c1c8..4443fc00fe0421566b99dbba3530ce13cc73ef9c 100644 (file)
@@ -273,9 +273,12 @@ void MCContext::renameELFSection(const MCSectionELF *Section, StringRef Name) {
   if (const MCSymbol *Group = Section->getGroup())
     GroupName = Group->getName();
 
-  ELFUniquingMap.erase(ELFSectionKey{Section->getSectionName(), GroupName});
-  auto I = ELFUniquingMap.insert(std::make_pair(ELFSectionKey{Name, GroupName},
-                                                Section)).first;
+  unsigned UniqueID = Section->getUniqueID();
+  ELFUniquingMap.erase(
+      ELFSectionKey{Section->getSectionName(), GroupName, UniqueID});
+  auto I = ELFUniquingMap.insert(std::make_pair(
+                                     ELFSectionKey{Name, GroupName, UniqueID},
+                                     Section)).first;
   StringRef CachedName = I->first.SectionName;
   const_cast<MCSectionELF*>(Section)->setSectionName(CachedName);
 }
@@ -294,7 +297,7 @@ MCContext::createELFRelSection(StringRef Name, unsigned Type, unsigned Flags,
 
 const MCSectionELF *MCContext::getELFSection(StringRef Section, unsigned Type,
                                              unsigned Flags, unsigned EntrySize,
-                                             StringRef Group, bool Unique,
+                                             StringRef Group, unsigned UniqueID,
                                              const char *BeginSymName) {
   MCSymbol *GroupSym = nullptr;
   if (!Group.empty()) {
@@ -304,9 +307,9 @@ const MCSectionELF *MCContext::getELFSection(StringRef Section, unsigned Type,
 
   // Do the lookup, if we have a hit, return it.
   auto IterBool = ELFUniquingMap.insert(
-      std::make_pair(ELFSectionKey{Section, Group}, nullptr));
+      std::make_pair(ELFSectionKey{Section, Group, UniqueID}, nullptr));
   auto &Entry = *IterBool.first;
-  if (!IterBool.second && !Unique)
+  if (!IterBool.second)
     return Entry.second;
 
   StringRef CachedName = Entry.first.SectionName;
@@ -322,9 +325,8 @@ const MCSectionELF *MCContext::getELFSection(StringRef Section, unsigned Type,
     Begin = createTempSymbol(BeginSymName, false);
 
   MCSectionELF *Result = new (*this) MCSectionELF(
-      CachedName, Type, Flags, Kind, EntrySize, GroupSym, Unique, Begin);
-  if (!Unique)
-    Entry.second = Result;
+      CachedName, Type, Flags, Kind, EntrySize, GroupSym, UniqueID, Begin);
+  Entry.second = Result;
   return Result;
 }
 
@@ -332,14 +334,14 @@ const MCSectionELF *MCContext::getELFSection(StringRef Section, unsigned Type,
                                              unsigned Flags, unsigned EntrySize,
                                              StringRef Group,
                                              const char *BeginSymName) {
-  return getELFSection(Section, Type, Flags, EntrySize, Group, false,
+  return getELFSection(Section, Type, Flags, EntrySize, Group, ~0,
                        BeginSymName);
 }
 
 const MCSectionELF *MCContext::CreateELFGroupSection() {
   MCSectionELF *Result = new (*this)
       MCSectionELF(".group", ELF::SHT_GROUP, 0, SectionKind::getReadOnly(), 4,
-                   nullptr, false, nullptr);
+                   nullptr, ~0, nullptr);
   return Result;
 }
 
index 7a120a105d2bd96d507c9e635dbae2aed83c36e9..4cb3dfe93089251534ed8ba6123c190903ea1e75 100644 (file)
@@ -379,7 +379,7 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
   const MCExpr *Subsection = nullptr;
   bool UseLastGroup = false;
   StringRef UniqueStr;
-  bool Unique = false;
+  int64_t UniqueID = ~0;
 
   // Set the defaults first.
   if (SectionName == ".fini" || SectionName == ".init" ||
@@ -470,7 +470,12 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
           return TokError("expected identifier in directive");
         if (UniqueStr != "unique")
           return TokError("expected 'unique'");
-        Unique = true;
+        if (getParser().parseAbsoluteExpression(UniqueID))
+          return true;
+        if (UniqueID < 0)
+          return TokError("unique id must be positive");
+        if (!isUInt<32>(UniqueID) || UniqueID == ~0U)
+          return TokError("unique id is too large");
       }
     }
   }
@@ -520,7 +525,7 @@ EndStmt:
   }
 
   const MCSection *ELFSection = getContext().getELFSection(
-      SectionName, Type, Flags, Size, GroupName, Unique);
+      SectionName, Type, Flags, Size, GroupName, UniqueID);
   getStreamer().SwitchSection(ELFSection, Subsection);
 
   if (getContext().getGenDwarfForAssembly()) {
index da3868273a7759a1ab8e318f430b67a567aedff1..2b9b8c630071dcb59f3db3d43b1b2df3cd15da37 100644 (file)
@@ -24,7 +24,7 @@ MCSectionELF::~MCSectionELF() {} // anchor.
 bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name,
                                               const MCAsmInfo &MAI) const {
 
-  if (Unique)
+  if (isUnique())
     return false;
 
   // FIXME: Does .section .bss/.data/.text work everywhere??
@@ -148,8 +148,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
     OS << ",comdat";
   }
 
-  if (Unique)
-    OS << ",unique";
+  if (isUnique())
+    OS << ",unique " << UniqueID;
 
   OS << '\n';
 
index 606d074752830898fb215b130005c3457578d021..c9f15914e4b17d60be7108366510d7eb0cee4562 100644 (file)
@@ -72,7 +72,7 @@ ENTRY(nullptr /*FIXME*/,     S_ATTR_LOC_RELOC)
 MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section,
                                unsigned TAA, unsigned reserved2, SectionKind K,
                                MCSymbol *Begin)
-    : MCSection(SV_MachO, K, Begin, /*Unique*/ false), TypeAndAttributes(TAA),
+    : MCSection(SV_MachO, K, Begin), TypeAndAttributes(TAA),
       Reserved2(reserved2) {
   assert(Segment.size() <= 16 && Section.size() <= 16 &&
          "Segment or section string too long");
index 3db2345540424791eeb09f95f83b8da1aed92194..27d0355bb1175882fa552e186cbe964ad6deb465 100644 (file)
@@ -669,12 +669,6 @@ void MCStreamer::SwitchSection(const MCSection *Section,
   MCSectionSubPair curSection = SectionStack.back().first;
   SectionStack.back().second = curSection;
   if (MCSectionSubPair(Section, Subsection) != curSection) {
-    const MCSection *CurSec = curSection.first;
-    if (CurSec && CurSec->isUnique()) {
-      MCSymbol *Sym = curSection.first->getEndSymbol(Context);
-      if (!Sym->isInSection())
-        EmitLabel(Sym);
-    }
     SectionStack.back().first = MCSectionSubPair(Section, Subsection);
     assert(!Section->hasEnded() && "Section already ended");
     ChangeSection(Section, Subsection);
index eb6194a23ee4e665420835dc1b1bc19d9bbed14a..0d2627d62ebdd3dbfa373f73a0340a69827ee8d9 100644 (file)
@@ -26,8 +26,7 @@ namespace llvm {
 class NVPTXSection : public MCSection {
   virtual void anchor();
 public:
-  NVPTXSection(SectionVariant V, SectionKind K)
-      : MCSection(V, K, nullptr, /*Unique*/ false) {}
+  NVPTXSection(SectionVariant V, SectionKind K) : MCSection(V, K, nullptr) {}
   virtual ~NVPTXSection() {}
 
   /// Override this as NVPTX has its own way of printing switching
index 46188e7153bea6175f515e1225511fb58417144f..730050dda5f30ebaf969bbfd60b23a56531f98e6 100644 (file)
@@ -36,7 +36,6 @@ bb5:
 ; LINUX-SECTIONS-SHORT: .section        .text,"axG",@progbits,F1,comdat
 ; LINUX-SECTIONS-SHORT: .size   F1,
 ; LINUX-SECTIONS-SHORT-NEXT: .cfi_endproc
-; LINUX-SECTIONS-SHORT-NEXT: .Lsec_end0:
 ; LINUX-SECTIONS-SHORT-NEXT: .section        .rodata,"aG",@progbits,F1,comdat
 
 $G16 = comdat any
diff --git a/test/MC/ELF/section-unique-err1.s b/test/MC/ELF/section-unique-err1.s
new file mode 100644 (file)
index 0000000..0b4985b
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: not llvm-mc -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s
+
+// CHECK:  error: expected absolute expression
+
+        .section       .text,"ax",@progbits,unique "abc"
diff --git a/test/MC/ELF/section-unique-err2.s b/test/MC/ELF/section-unique-err2.s
new file mode 100644 (file)
index 0000000..b2ac4f8
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: not llvm-mc -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s
+
+// CHECK:  error: unique id must be positive
+
+        .section       .text,"ax",@progbits,unique -1
diff --git a/test/MC/ELF/section-unique-err3.s b/test/MC/ELF/section-unique-err3.s
new file mode 100644 (file)
index 0000000..67e962b
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: not llvm-mc -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s
+
+// CHECK:  error: unique id is too large
+
+        .section       .text,"ax",@progbits,unique 4294967295
index b482af3d1010480ed7842dd886670d8f9f3f87b7..ffd11d944c5a7ade7091942ddaa94f98db73264a 100644 (file)
@@ -1,22 +1,22 @@
 // RUN: llvm-mc -triple x86_64-pc-linux-gnu %s -o - | FileCheck %s
 // RUN: llvm-mc -triple x86_64-pc-linux-gnu %s -filetype=obj -o - | llvm-readobj -t | FileCheck %s --check-prefix=OBJ
 
-       .section        .text,"ax",@progbits,unique
+       .section        .text,"ax",@progbits,unique 4294967293
         .globl f
 f:
         nop
 
-       .section        .text,"ax",@progbits,unique
+       .section        .text,"ax",@progbits,unique 4294967294
         .globl g
 g:
         nop
 
 // test that f and g are in different sections.
 
-// CHECK: .section     .text,"ax",@progbits,unique
+// CHECK: .section     .text,"ax",@progbits,unique 4294967293
 // CHECK: f:
 
-// CHECK: .section     .text,"ax",@progbits,unique
+// CHECK: .section     .text,"ax",@progbits,unique 4294967294
 // CHECK: g:
 
 // OBJ: Symbol {