return C;
}
+static const MCSymbolELF *getAssociatedSymbol(const GlobalObject *GO,
+ const TargetMachine &TM) {
+ MDNode *MD = GO->getMetadata(LLVMContext::MD_associated);
+ if (!MD)
+ return nullptr;
+
+ auto *VM = dyn_cast<ValueAsMetadata>(MD->getOperand(0));
+ if (!VM)
+ report_fatal_error("MD_associated operand is not ValueAsMetadata");
+
+ GlobalObject *OtherGO = dyn_cast<GlobalObject>(VM->getValue());
+ return OtherGO ? dyn_cast<MCSymbolELF>(TM.getSymbol(OtherGO)) : nullptr;
+}
+
MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
StringRef SectionName = GO->getSection();
Group = C->getName();
Flags |= ELF::SHF_GROUP;
}
- return getContext().getELFSection(SectionName,
- getELFSectionType(SectionName, Kind), Flags,
- /*EntrySize=*/0, Group);
+
+ // 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 *AssociatedSymbol = getAssociatedSymbol(GO, TM);
+ if (AssociatedSymbol) {
+ UniqueID = NextUniqueID++;
+ Flags |= ELF::SHF_LINK_ORDER;
+ }
+
+ MCSectionELF *Section = getContext().getELFSection(
+ SectionName, getELFSectionType(SectionName, Kind), Flags,
+ /*EntrySize=*/0, Group, UniqueID, AssociatedSymbol);
+ // Make sure that we did not get some other section with incompatible sh_link.
+ // This should not be possible due to UniqueID code above.
+ assert(Section->getAssociatedSymbol() == AssociatedSymbol);
+ return Section;
}
/// Return the section prefix name used by options FunctionsSections and
return ".data.rel.ro";
}
-static MCSectionELF *
-selectELFSectionForGlobal(MCContext &Ctx, const GlobalObject *GO,
- SectionKind Kind, Mangler &Mang,
- const TargetMachine &TM, bool EmitUniqueSection,
- unsigned Flags, unsigned *NextUniqueID) {
+static MCSectionELF *selectELFSectionForGlobal(
+ MCContext &Ctx, const GlobalObject *GO, SectionKind Kind, Mangler &Mang,
+ const TargetMachine &TM, bool EmitUniqueSection, unsigned Flags,
+ unsigned *NextUniqueID, const MCSymbolELF *AssociatedSymbol) {
unsigned EntrySize = 0;
if (Kind.isMergeableCString()) {
if (Kind.isMergeable2ByteCString()) {
if (Kind.isExecuteOnly())
UniqueID = 0;
return Ctx.getELFSection(Name, getELFSectionType(Name, Kind), Flags,
- EntrySize, Group, UniqueID);
+ EntrySize, Group, UniqueID, AssociatedSymbol);
}
MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal(
}
EmitUniqueSection |= GO->hasComdat();
- return selectELFSectionForGlobal(getContext(), GO, Kind, getMangler(), TM,
- EmitUniqueSection, Flags, &NextUniqueID);
+ const MCSymbolELF *AssociatedSymbol = getAssociatedSymbol(GO, TM);
+ if (AssociatedSymbol) {
+ EmitUniqueSection = true;
+ Flags |= ELF::SHF_LINK_ORDER;
+ }
+
+ MCSectionELF *Section = selectELFSectionForGlobal(
+ getContext(), GO, Kind, getMangler(), TM, EmitUniqueSection, Flags,
+ &NextUniqueID, AssociatedSymbol);
+ assert(Section->getAssociatedSymbol() == AssociatedSymbol);
+ return Section;
}
MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
return ReadOnlySection;
return selectELFSectionForGlobal(getContext(), &F, SectionKind::getReadOnly(),
- getMangler(), TM, EmitUniqueSection, ELF::SHF_ALLOC,
- &NextUniqueID);
+ getMangler(), TM, EmitUniqueSection,
+ ELF::SHF_ALLOC, &NextUniqueID,
+ /* AssociatedSymbol */ nullptr);
}
bool TargetLoweringObjectFileELF::shouldPutJumpTableInFunctionSection(
--- /dev/null
+; RUN: llc -data-sections=1 -mtriple x86_64-pc-linux-gnu < %s | FileCheck %s
+; RUN: llc -data-sections=0 -mtriple x86_64-pc-linux-gnu < %s | FileCheck %s
+
+@a = global i32 1
+@b = global i32 2, !associated !0
+!0 = !{i32* @a}
+; CHECK-DAG: .section .data.b,"awm",@progbits,a
+
+; Loop is OK. Also, normally -data-sections=0 would place @c and @d in the same section. !associated prevents that.
+@c = global i32 2, !associated !2
+@d = global i32 2, !associated !1
+!1 = !{i32* @c}
+!2 = !{i32* @d}
+; CHECK-DAG: .section .data.c,"awm",@progbits,d
+; CHECK-DAG: .section .data.d,"awm",@progbits,c
+
+; BSS is OK.
+@e = global i32 0
+@f = global i32 0, !associated !3
+@g = global i32 1, !associated !3
+!3 = !{i32* @e}
+; CHECK-DAG: .section .bss.f,"awm",@nobits,e
+; CHECK-DAG: .section .data.g,"awm",@progbits,e
+
+; Explicit sections.
+@h = global i32 1, section "aaa"
+@i = global i32 1, section "bbb", !associated !4
+@j = global i32 1, section "bbb", !associated !4
+@k = global i32 1, !associated !4
+!4 = !{i32* @h}
+; CHECK-DAG: .section aaa,"aw",@progbits
+; CHECK-DAG: .section bbb,"awm",@progbits,h,unique,1
+; CHECK-DAG: .section bbb,"awm",@progbits,h,unique,2
+; CHECK-DAG: .section .data.k,"awm",@progbits,h
+
+; Non-GlobalObject metadata.
+@l = global i32 1, section "ccc", !associated !5
+!5 = !{i32* null}
+; CHECK-DAG: .section ccc,"aw",@progbits