aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2021-02-26 16:38:44 -0800
committerFangrui Song <i@maskray.me>2021-02-26 16:38:44 -0800
commit47c5576d7d586624c38f76bd3168e05f6ef1f838 (patch)
treeb8d955f1c3f64e7cf994818939be3b8e1dbbaa3a /llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
parent8afdacba9dcd36fc838eb86fca86f7f903040030 (diff)
downloadllvm-47c5576d7d586624c38f76bd3168e05f6ef1f838.zip
llvm-47c5576d7d586624c38f76bd3168e05f6ef1f838.tar.gz
llvm-47c5576d7d586624c38f76bd3168e05f6ef1f838.tar.bz2
ELF: Create unique SHF_GNU_RETAIN sections for llvm.used global objects
If a global object is listed in `@llvm.used`, place it in a unique section with the `SHF_GNU_RETAIN` flag. The section is a GC root under `ld --gc-sections` with LLD>=13 or GNU ld>=2.36. For front ends which do not expect to see multiple sections of the same name, consider emitting `@llvm.compiler.used` instead of `@llvm.used`. SHF_GNU_RETAIN is restricted to ELFOSABI_GNU and ELFOSABI_FREEBSD in binutils. We don't do the restriction - see the rationale in D95749. The integrated assembler has supported SHF_GNU_RETAIN since D95730. GNU as>=2.36 supports section flag 'R'. We don't need to worry about GNU ld support because older GNU ld just ignores the unknown SHF_GNU_RETAIN. With this change, `__attribute__((retain))` functions/variables emitted by clang will get the SHF_GNU_RETAIN flag. Differential Revision: https://reviews.llvm.org/D97448
Diffstat (limited to 'llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp')
-rw-r--r--llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp36
1 files changed, 28 insertions, 8 deletions
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 8f74866..f1729d1 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -293,6 +293,14 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx,
}
}
+void TargetLoweringObjectFileELF::getModuleMetadata(Module &M) {
+ SmallVector<GlobalValue *, 4> Vec;
+ collectUsedGlobalVariables(M, Vec, false);
+ for (GlobalValue *GV : Vec)
+ if (auto *GO = dyn_cast<GlobalObject>(GV))
+ Used.insert(GO);
+}
+
void TargetLoweringObjectFileELF::emitModuleMetadata(MCStreamer &Streamer,
Module &M) const {
auto &C = getContext();
@@ -687,9 +695,15 @@ MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
// MD_associated in a unique section.
unsigned UniqueID = MCContext::GenericSectionID;
const MCSymbolELF *LinkedToSym = getLinkedToSymbol(GO, TM);
- if (GO->getMetadata(LLVMContext::MD_associated)) {
+ const bool Associated = GO->getMetadata(LLVMContext::MD_associated);
+ const bool Retain = Used.count(GO);
+ if (Associated || Retain) {
UniqueID = NextUniqueID++;
- Flags |= ELF::SHF_LINK_ORDER;
+ if (Associated)
+ Flags |= ELF::SHF_LINK_ORDER;
+ if (Retain && (getContext().getAsmInfo()->useIntegratedAssembler() ||
+ getContext().getAsmInfo()->binutilsIsAtLeast(2, 36)))
+ Flags |= ELF::SHF_GNU_RETAIN;
} else {
if (getContext().getAsmInfo()->useIntegratedAssembler() ||
getContext().getAsmInfo()->binutilsIsAtLeast(2, 35)) {
@@ -802,13 +816,18 @@ static MCSectionELF *selectELFSectionForGlobal(
static MCSection *selectELFSectionForGlobal(
MCContext &Ctx, const GlobalObject *GO, SectionKind Kind, Mangler &Mang,
- const TargetMachine &TM, bool EmitUniqueSection, unsigned Flags,
- unsigned *NextUniqueID) {
+ const TargetMachine &TM, bool Retain, bool EmitUniqueSection,
+ unsigned Flags, unsigned *NextUniqueID) {
const MCSymbolELF *LinkedToSym = getLinkedToSymbol(GO, TM);
if (LinkedToSym) {
EmitUniqueSection = true;
Flags |= ELF::SHF_LINK_ORDER;
}
+ if (Retain && (Ctx.getAsmInfo()->useIntegratedAssembler() ||
+ Ctx.getAsmInfo()->binutilsIsAtLeast(2, 36))) {
+ EmitUniqueSection = true;
+ Flags |= ELF::SHF_GNU_RETAIN;
+ }
MCSectionELF *Section = selectELFSectionForGlobal(
Ctx, GO, Kind, Mang, TM, EmitUniqueSection, Flags,
@@ -832,16 +851,17 @@ MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal(
}
EmitUniqueSection |= GO->hasComdat();
return selectELFSectionForGlobal(getContext(), GO, Kind, getMangler(), TM,
- EmitUniqueSection, Flags, &NextUniqueID);
+ Used.count(GO), EmitUniqueSection, Flags,
+ &NextUniqueID);
}
MCSection *TargetLoweringObjectFileELF::getUniqueSectionForFunction(
const Function &F, const TargetMachine &TM) const {
SectionKind Kind = SectionKind::getText();
unsigned Flags = getELFSectionFlags(Kind);
- return selectELFSectionForGlobal(getContext(), &F, Kind, getMangler(), TM,
- /* EmitUniqueSection = */ true, Flags,
- &NextUniqueID);
+ return selectELFSectionForGlobal(
+ getContext(), &F, Kind, getMangler(), TM, Used.count(&F),
+ /*EmitUniqueSection=*/true, Flags, &NextUniqueID);
}
MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(