.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
=========================
class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
bool UseInitArray;
+ mutable unsigned NextUniqueID = 0;
public:
TargetLoweringObjectFileELF() : UseInitArray(false) {}
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;
}
};
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,
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();
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;
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 &&
/// 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.
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; }
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;
}
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()) {
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(
EmitUniqueSection |= GV->hasComdat();
return selectELFSectionForGlobal(getContext(), GV, Kind, Mang, TM,
- EmitUniqueSection, Flags);
+ EmitUniqueSection, Flags, &NextUniqueID);
}
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(
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);
}
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()) {
// 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;
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;
}
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;
}
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" ||
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");
}
}
}
}
const MCSection *ELFSection = getContext().getELFSection(
- SectionName, Type, Flags, Size, GroupName, Unique);
+ SectionName, Type, Flags, Size, GroupName, UniqueID);
getStreamer().SwitchSection(ELFSection, Subsection);
if (getContext().getGenDwarfForAssembly()) {
bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name,
const MCAsmInfo &MAI) const {
- if (Unique)
+ if (isUnique())
return false;
// FIXME: Does .section .bss/.data/.text work everywhere??
OS << ",comdat";
}
- if (Unique)
- OS << ",unique";
+ if (isUnique())
+ OS << ",unique " << UniqueID;
OS << '\n';
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");
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);
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
; 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
--- /dev/null
+// 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"
--- /dev/null
+// 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
--- /dev/null
+// 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
// 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 {