Implement unique sections with an unique ID.

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.

llvm-svn: 234099
This commit is contained in:
Rafael Espindola 2015-04-04 18:02:01 +00:00
parent ecc59396d1
commit 8ca44f0b5c
18 changed files with 103 additions and 50 deletions

View 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
=========================

View File

@ -34,6 +34,7 @@ namespace llvm {
class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
bool UseInitArray;
mutable unsigned NextUniqueID = 0;
public:
TargetLoweringObjectFileELF() : UseInitArray(false) {}

View 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,

View 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;

View 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 &&

View 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;
}

View 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(

View 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;
}

View 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()) {

View 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';

View 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");

View 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);

View 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

View 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

View File

@ -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"

View File

@ -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

View File

@ -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

View 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 {