};
}
-MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
- const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
+static MCSection *selectExplicitSectionGlobal(
+ const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM,
+ MCContext &Ctx, Mangler &Mang, unsigned &NextUniqueID,
+ bool Retain, bool ForceUnique) {
StringRef SectionName = GO->getSection();
// Check if '#pragma clang section' name is applicable.
unsigned UniqueID = MCContext::GenericSectionID;
const MCSymbolELF *LinkedToSym = getLinkedToSymbol(GO, TM);
const bool Associated = GO->getMetadata(LLVMContext::MD_associated);
- const bool Retain = Used.count(GO);
if (Associated || Retain) {
UniqueID = NextUniqueID++;
if (Associated)
Flags |= ELF::SHF_LINK_ORDER;
- if (Retain && (getContext().getAsmInfo()->useIntegratedAssembler() ||
- getContext().getAsmInfo()->binutilsIsAtLeast(2, 36)))
+ if (Retain && (Ctx.getAsmInfo()->useIntegratedAssembler() ||
+ Ctx.getAsmInfo()->binutilsIsAtLeast(2, 36)))
Flags |= ELF::SHF_GNU_RETAIN;
} else {
- if (getContext().getAsmInfo()->useIntegratedAssembler() ||
- getContext().getAsmInfo()->binutilsIsAtLeast(2, 35)) {
+ 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 = getContext().getELFUniqueIDForEntsize(SectionName, Flags,
- EntrySize);
+ auto maybeID = Ctx.getELFUniqueIDForEntsize(SectionName, Flags,
+ EntrySize);
if (maybeID)
UniqueID = *maybeID;
else {
// to unique the section as the entry size for this symbol will be
// compatible with implicitly created sections.
SmallString<128> ImplicitSectionNameStem = getELFSectionNameForGlobal(
- GO, Kind, getMangler(), TM, EntrySize, false);
- if (!(getContext().isELFImplicitMergeableSectionNamePrefix(
- SectionName) &&
+ GO, Kind, Mang, TM, EntrySize, false);
+ if (!(Ctx.isELFImplicitMergeableSectionNamePrefix(SectionName) &&
SectionName.startswith(ImplicitSectionNameStem)))
UniqueID = NextUniqueID++;
}
// 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 (getContext().isELFGenericMergeableSection(SectionName)) {
- auto maybeID = getContext().getELFUniqueIDForEntsize(
+ if (Ctx.isELFGenericMergeableSection(SectionName)) {
+ auto maybeID = Ctx.getELFUniqueIDForEntsize(
SectionName, Flags, EntrySize);
UniqueID = maybeID ? *maybeID : NextUniqueID++;
}
}
}
- MCSectionELF *Section = getContext().getELFSection(
+ // 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);
// Make sure that we did not get some other section with incompatible sh_link.
assert(Section->getLinkedToSymbol() == LinkedToSym &&
"Associated symbol mismatch between sections");
- if (!(getContext().getAsmInfo()->useIntegratedAssembler() ||
- getContext().getAsmInfo()->binutilsIsAtLeast(2, 35))) {
+ if (!(Ctx.getAsmInfo()->useIntegratedAssembler() ||
+ Ctx.getAsmInfo()->binutilsIsAtLeast(2, 35))) {
// If we are using GNU as before 2.35, then this symbol might have
// been placed in an incompatible mergeable section. Emit an error if this
// is the case to avoid creating broken output.
return Section;
}
+MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
+ const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
+ return selectExplicitSectionGlobal(GO, Kind, TM, getContext(), getMangler(),
+ NextUniqueID, Used.count(GO),
+ /* ForceUnique = */false);
+}
+
static MCSectionELF *selectELFSectionForGlobal(
MCContext &Ctx, const GlobalObject *GO, SectionKind Kind, Mangler &Mang,
const TargetMachine &TM, bool EmitUniqueSection, unsigned Flags,
const Function &F, const TargetMachine &TM) const {
SectionKind Kind = SectionKind::getText();
unsigned Flags = getELFSectionFlags(Kind);
- return selectELFSectionForGlobal(
- getContext(), &F, Kind, getMangler(), TM, Used.count(&F),
- /*EmitUniqueSection=*/true, Flags, &NextUniqueID);
+ // If the function's section names is pre-determined via pragma or a
+ // section attribute, call selectExplicitSectionGlobal.
+ if (F.hasSection() || F.hasFnAttribute("implicit-section-name"))
+ return selectExplicitSectionGlobal(
+ &F, Kind, TM, getContext(), getMangler(), NextUniqueID,
+ Used.count(&F), /* ForceUnique = */true);
+ else
+ return selectELFSectionForGlobal(
+ getContext(), &F, Kind, getMangler(), TM, Used.count(&F),
+ /*EmitUniqueSection=*/true, Flags, &NextUniqueID);
}
MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
--- /dev/null
+; RUN: llc < %s -mtriple=x86_64-pc-linux -basic-block-sections=all | FileCheck %s
+; RUN: llc < %s -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=all | FileCheck %s
+; RUN: echo "!_Z3fooi" > %t.order.txt
+; RUN: echo "!!2" >> %t.order.txt
+; RUN: llc < %s -mtriple=x86_64-pc-linux -basic-block-sections=%t.order.txt | FileCheck %s --check-prefix=LIST
+; RUN: llc < %s -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t.order.txt | FileCheck %s --check-prefix=LIST
+
+; CHECK: .section foo_section,"ax",@progbits,unique,1
+; CHECK-LABEL: _Z3fooi:
+; CHECK: .section foo_section,"ax",@progbits,unique,2
+; CHECK-NEXT: _Z3fooi.__part.1:
+; CHECK: .section foo_section,"ax",@progbits,unique,3
+; CHECK-NEXT: _Z3fooi.__part.2:
+
+; LIST: .section foo_section,"ax",@progbits,unique,1
+; LIST-LABEL: _Z3fooi:
+; LIST: .section foo_section,"ax",@progbits,unique,2
+; LIST-NEXT: _Z3fooi.__part.0:
+; LIST-NOT: .section foo_section,"ax",@progbits,unique,3
+
+;; Source to generate the IR:
+;; __attribute__((section("foo_section")))
+;; int foo(int n) {
+;; if (n < 0)
+;; exit(-1);
+;; return 0;
+;; }
+
+define dso_local i32 @_Z3fooi(i32 %n) local_unnamed_addr section "foo_section" {
+entry:
+ %cmp = icmp slt i32 %n, 0
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @exit(i32 -1) #2
+ unreachable
+
+if.end: ; preds = %entry
+ ret i32 0
+}
+
+declare dso_local void @exit(i32) local_unnamed_addr
--- /dev/null
+; RUN: llc < %s -mtriple=x86_64-pc-linux -basic-block-sections=all | FileCheck %s
+; RUN: llc < %s -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=all | FileCheck %s
+; RUN: echo "!_Z3fooi" > %t.list.txt
+; RUN: echo "!!2" >> %t.list.txt
+; RUN: llc < %s -mtriple=x86_64-pc-linux -basic-block-sections=%t.list.txt | FileCheck %s --check-prefix=LIST
+; RUN: llc < %s -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t.list.txt | FileCheck %s --check-prefix=LIST
+
+; CHECK: .section foo_section,"ax",@progbits,unique,1
+; CHECK-LABEL: _Z3fooi:
+; CHECK: .section foo_section,"ax",@progbits,unique,2
+; CHECK-NEXT: _Z3fooi.__part.1:
+; CHECK: .section foo_section,"ax",@progbits,unique,3
+; CHECK-NEXT: _Z3fooi.__part.2:
+
+; LIST: .section foo_section,"ax",@progbits,unique,1
+; LIST-LABEL: _Z3fooi:
+; LIST: .section foo_section,"ax",@progbits,unique,2
+; LIST-NEXT: _Z3fooi.__part.0:
+; LIST-NOT: .section foo_section,"ax",@progbits,unique,3
+
+;; Source to generate the IR:
+;; #pragma clang section text = "foo_section"
+;; int foo(int n) {
+;; if (n < 0)
+;; exit(-1);
+;; return 0;
+;; }
+
+define dso_local i32 @_Z3fooi(i32 %n) local_unnamed_addr #0 {
+entry:
+ %cmp = icmp slt i32 %n, 0
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @exit(i32 -1) #2
+ unreachable
+
+if.end: ; preds = %entry
+ ret i32 0
+}
+
+declare dso_local void @exit(i32) local_unnamed_addr
+
+attributes #0 = {"implicit-section-name"="foo_section" }