Skip to content

Commit

Permalink
[MC][NFCI] Factor out ELF section unique ID calculation
Browse files Browse the repository at this point in the history
Precursor to D100944. The logic for determining the unique ID had become
quite difficult to reason about, so I have factored this out into a
separate function.

Differential Revision: https://reviews.llvm.org/D102336
  • Loading branch information
tmatheson-arm committed May 26, 2021
1 parent a2d6ef5 commit e79e804
Showing 1 changed file with 78 additions and 61 deletions.
139 changes: 78 additions & 61 deletions llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Expand Up @@ -653,6 +653,81 @@ class LoweringDiagnosticInfo : public DiagnosticInfo {
};
}

/// Calculate an appropriate unique ID for a section, and update Flags,
/// EntrySize and NextUniqueID where appropriate.
static unsigned
calcUniqueIDUpdateFlagsAndSize(const GlobalObject *GO, StringRef SectionName,
SectionKind Kind, const TargetMachine &TM,
MCContext &Ctx, Mangler &Mang, unsigned &Flags,
unsigned &EntrySize, unsigned &NextUniqueID,
const bool Retain, const bool ForceUnique) {
// Increment uniqueID if we are forced to emit a unique section.
// This works perfectly fine with section attribute or pragma section as the
// sections with the same name are grouped together by the assembler.
if (ForceUnique)
return NextUniqueID++;

// A section can have at most one associated section. Put each global with
// MD_associated in a unique section.
const bool Associated = GO->getMetadata(LLVMContext::MD_associated);
if (Associated) {
Flags |= ELF::SHF_LINK_ORDER;
return NextUniqueID++;
}

if (Retain) {
if (Ctx.getAsmInfo()->useIntegratedAssembler() ||
Ctx.getAsmInfo()->binutilsIsAtLeast(2, 36))
Flags |= ELF::SHF_GNU_RETAIN;
return NextUniqueID++;
}

// If two symbols with differing sizes end up in the same mergeable section
// that section can be assigned an incorrect entry size. To avoid this we
// usually put symbols of the same size into distinct mergeable sections with
// the same name. Doing so relies on the ",unique ," assembly feature. This
// feature is not avalible until bintuils version 2.35
// (https://sourceware.org/bugzilla/show_bug.cgi?id=25380).
const bool SupportsUnique = Ctx.getAsmInfo()->useIntegratedAssembler() ||
Ctx.getAsmInfo()->binutilsIsAtLeast(2, 35);
if (!SupportsUnique) {
Flags &= ~ELF::SHF_MERGE;
EntrySize = 0;
return MCContext::GenericSectionID;
}

const bool SymbolMergeable = Flags & ELF::SHF_MERGE;
const bool SeenSectionNameBefore =
Ctx.isELFGenericMergeableSection(SectionName);
// If this is the first ocurrence of this section name, treat it as the
// generic section
if (!SymbolMergeable && !SeenSectionNameBefore)
return MCContext::GenericSectionID;

// Symbols must be placed into sections with compatible entry sizes. Generate
// unique sections for symbols that have not been assigned to compatible
// sections.
const auto PreviousID =
Ctx.getELFUniqueIDForEntsize(SectionName, Flags, EntrySize);
if (PreviousID)
return *PreviousID;

// If the user has specified the same section name as would be created
// implicitly for this symbol e.g. .rodata.str1.1, then we don't need
// to unique the section as the entry size for this symbol will be
// compatible with implicitly created sections.
SmallString<128> ImplicitSectionNameStem =
getELFSectionNameForGlobal(GO, Kind, Mang, TM, EntrySize, false);
if (SymbolMergeable &&
Ctx.isELFImplicitMergeableSectionNamePrefix(SectionName) &&
SectionName.startswith(ImplicitSectionNameStem))
return MCContext::GenericSectionID;

// We have seen this section name before, but with different flags or entity
// size. Create a new unique ID.
return NextUniqueID++;
}

static MCSection *selectExplicitSectionGlobal(
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM,
MCContext &Ctx, Mangler &Mang, unsigned &NextUniqueID,
Expand Down Expand Up @@ -693,69 +768,11 @@ static MCSection *selectExplicitSectionGlobal(
}

unsigned EntrySize = getEntrySizeForKind(Kind);
const unsigned UniqueID = calcUniqueIDUpdateFlagsAndSize(
GO, SectionName, Kind, TM, Ctx, Mang, Flags, EntrySize, NextUniqueID,
Retain, ForceUnique);

// A section can have at most one associated section. Put each global with
// MD_associated in a unique section.
unsigned UniqueID = MCContext::GenericSectionID;
const MCSymbolELF *LinkedToSym = getLinkedToSymbol(GO, TM);
const bool Associated = GO->getMetadata(LLVMContext::MD_associated);
if (Associated || Retain) {
UniqueID = NextUniqueID++;
if (Associated)
Flags |= ELF::SHF_LINK_ORDER;
if (Retain && (Ctx.getAsmInfo()->useIntegratedAssembler() ||
Ctx.getAsmInfo()->binutilsIsAtLeast(2, 36)))
Flags |= ELF::SHF_GNU_RETAIN;
} else {
if (Ctx.getAsmInfo()->useIntegratedAssembler() ||
Ctx.getAsmInfo()->binutilsIsAtLeast(2, 35)) {
// Symbols must be placed into sections with compatible entry
// sizes. Generate unique sections for symbols that have not
// been assigned to compatible sections.
if (Flags & ELF::SHF_MERGE) {
auto maybeID = Ctx.getELFUniqueIDForEntsize(SectionName, Flags,
EntrySize);
if (maybeID)
UniqueID = *maybeID;
else {
// If the user has specified the same section name as would be created
// implicitly for this symbol e.g. .rodata.str1.1, then we don't need
// to unique the section as the entry size for this symbol will be
// compatible with implicitly created sections.
SmallString<128> ImplicitSectionNameStem = getELFSectionNameForGlobal(
GO, Kind, Mang, TM, EntrySize, false);
if (!(Ctx.isELFImplicitMergeableSectionNamePrefix(SectionName) &&
SectionName.startswith(ImplicitSectionNameStem)))
UniqueID = NextUniqueID++;
}
} else {
// We need to unique the section if the user has explicity
// assigned a non-mergeable symbol to a section name for
// a generic mergeable section.
if (Ctx.isELFGenericMergeableSection(SectionName)) {
auto maybeID = Ctx.getELFUniqueIDForEntsize(
SectionName, Flags, EntrySize);
UniqueID = maybeID ? *maybeID : NextUniqueID++;
}
}
} else {
// If two symbols with differing sizes end up in the same mergeable
// section that section can be assigned an incorrect entry size. To avoid
// this we usually put symbols of the same size into distinct mergeable
// sections with the same name. Doing so relies on the ",unique ,"
// assembly feature. This feature is not avalible until bintuils
// version 2.35 (https://sourceware.org/bugzilla/show_bug.cgi?id=25380).
Flags &= ~ELF::SHF_MERGE;
EntrySize = 0;
}
}

// Increment uniqueID if we are forced to emit a unique section.
// This works perfectly fine with section attribute or pragma section as the
// sections with the same name are grouped together by the assembler.
if (ForceUnique && UniqueID == MCContext::GenericSectionID)
UniqueID = NextUniqueID++;

MCSectionELF *Section = Ctx.getELFSection(
SectionName, getELFSectionType(SectionName, Kind), Flags, EntrySize,
Group, IsComdat, UniqueID, LinkedToSym);
Expand Down

0 comments on commit e79e804

Please sign in to comment.