[llvm] cf3a327 - IR: Introduce !elf_section_properties for setting section properties.
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 29 16:08:17 PDT 2026
Author: Peter Collingbourne
Date: 2026-04-29T16:08:13-07:00
New Revision: cf3a327372f09815d78aa9066c19424f5a41f550
URL: https://github.com/llvm/llvm-project/commit/cf3a327372f09815d78aa9066c19424f5a41f550
DIFF: https://github.com/llvm/llvm-project/commit/cf3a327372f09815d78aa9066c19424f5a41f550.diff
LOG: IR: Introduce !elf_section_properties for setting section properties.
This new metadata type may be used to set sh_type and sh_entsize on a
global's section. The intent is that it will be used to mark up
CFI jump table sections.
Reviewers: fmayer, MaskRay, nikic, efriedma-quic
Reviewed By: fmayer
Pull Request: https://github.com/llvm/llvm-project/pull/149260
Added:
llvm/test/CodeGen/X86/elf-section-properties.ll
llvm/test/Verifier/elf-section-properties.ll
Modified:
llvm/docs/LangRef.rst
llvm/include/llvm/IR/FixedMetadataKinds.def
llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
llvm/lib/IR/Verifier.cpp
Removed:
################################################################################
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index be4b1d8a166de..5a7e9401fb1e0 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -8905,6 +8905,25 @@ function that has had all calls to it inlined.
!0 = !{ptr @bar, null, ptr @baz}
+'``elf_section_properties``' Metadata
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The '``elf_section_properties``' metadata is attached to a function or
+global variable and is used when writing an object file in ELF format to
+specify the values of the global's section type (`sh_type`) and entry
+size (`sh_entsize`) fields. The first operand specifies the type, and
+the second operand specifies the entry size.
+
+Example:
+
+.. code-block:: llvm
+
+ @global = global i32 1, !elf_section_properties !{i32 1879002126, i32 8}
+
+This defines a global with type ``SHT_LLVM_CFI_JUMP_TABLE`` and entry
+size 8.
+
+
Module Flags Metadata
=====================
diff --git a/llvm/include/llvm/IR/FixedMetadataKinds.def b/llvm/include/llvm/IR/FixedMetadataKinds.def
index 6d74aff4ae250..47c221fd60fc5 100644
--- a/llvm/include/llvm/IR/FixedMetadataKinds.def
+++ b/llvm/include/llvm/IR/FixedMetadataKinds.def
@@ -61,3 +61,4 @@ LLVM_FIXED_MD_KIND(MD_implicit_ref, "implicit.ref", 46)
LLVM_FIXED_MD_KIND(MD_nofpclass, "nofpclass", 47)
LLVM_FIXED_MD_KIND(MD_call_target, "call_target", 48)
LLVM_FIXED_MD_KIND(MD_inline_history, "inline_history", 49)
+LLVM_FIXED_MD_KIND(MD_elf_section_properties, "elf_section_properties", 50)
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 715b8977048fa..211d13c19e459 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -634,10 +634,11 @@ static StringRef getSectionPrefixForGlobal(SectionKind Kind, bool IsLarge) {
static SmallString<128>
getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,
Mangler &Mang, const TargetMachine &TM,
- unsigned EntrySize, bool UniqueSectionName,
+ bool UniqueSectionName,
const MachineJumpTableEntry *JTE) {
SmallString<128> Name =
getSectionPrefixForGlobal(Kind, TM.isLargeGlobalValue(GO));
+ unsigned EntrySize = getEntrySizeForKind(Kind);
if (Kind.isMergeableCString()) {
// We also need alignment here.
// FIXME: this is getting the alignment of the character, not the
@@ -771,8 +772,8 @@ calcUniqueIDUpdateFlagsAndSize(const GlobalObject *GO, StringRef SectionName,
// 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, /*MJTE=*/nullptr);
+ SmallString<128> ImplicitSectionNameStem =
+ getELFSectionNameForGlobal(GO, Kind, Mang, TM, false, /*MJTE=*/nullptr);
if (SymbolMergeable &&
Ctx.isELFImplicitMergeableSectionNamePrefix(SectionName) &&
SectionName.starts_with(ImplicitSectionNameStem))
@@ -783,8 +784,9 @@ calcUniqueIDUpdateFlagsAndSize(const GlobalObject *GO, StringRef SectionName,
return NextUniqueID++;
}
-static std::tuple<StringRef, bool, unsigned>
-getGlobalObjectInfo(const GlobalObject *GO, const TargetMachine &TM) {
+static std::tuple<StringRef, bool, unsigned, unsigned, unsigned>
+getGlobalObjectInfo(const GlobalObject *GO, const TargetMachine &TM,
+ StringRef SectionName, SectionKind Kind) {
StringRef Group = "";
bool IsComdat = false;
unsigned Flags = 0;
@@ -795,7 +797,23 @@ getGlobalObjectInfo(const GlobalObject *GO, const TargetMachine &TM) {
}
if (TM.isLargeGlobalValue(GO))
Flags |= ELF::SHF_X86_64_LARGE;
- return {Group, IsComdat, Flags};
+
+ unsigned Type, EntrySize;
+ if (MDNode *MD = GO->getMetadata(LLVMContext::MD_elf_section_properties)) {
+ Type = cast<ConstantAsMetadata>(MD->getOperand(0))
+ ->getValue()
+ ->getUniqueInteger()
+ .getZExtValue();
+ EntrySize = cast<ConstantAsMetadata>(MD->getOperand(1))
+ ->getValue()
+ ->getUniqueInteger()
+ .getZExtValue();
+ } else {
+ Type = getELFSectionType(SectionName, Kind);
+ EntrySize = getEntrySizeForKind(Kind);
+ }
+
+ return {Group, IsComdat, Flags, Type, EntrySize};
}
static StringRef handlePragmaClangSection(const GlobalObject *GO,
@@ -831,18 +849,18 @@ static MCSection *selectExplicitSectionGlobal(const GlobalObject *GO,
Kind = getELFKindForNamedSection(SectionName, Kind);
unsigned Flags = getELFSectionFlags(Kind, TM.getTargetTriple());
- auto [Group, IsComdat, ExtraFlags] = getGlobalObjectInfo(GO, TM);
+ auto [Group, IsComdat, ExtraFlags, Type, EntrySize] =
+ getGlobalObjectInfo(GO, TM, SectionName, Kind);
Flags |= ExtraFlags;
- unsigned EntrySize = getEntrySizeForKind(Kind);
const unsigned UniqueID = calcUniqueIDUpdateFlagsAndSize(
GO, SectionName, Kind, TM, Ctx, Mang, Flags, EntrySize, NextUniqueID,
Retain, ForceUnique);
const MCSymbolELF *LinkedToSym = getLinkedToSymbol(GO, TM);
- MCSectionELF *Section = Ctx.getELFSection(
- SectionName, getELFSectionType(SectionName, Kind), Flags, EntrySize,
- Group, IsComdat, UniqueID, LinkedToSym);
+ MCSectionELF *Section =
+ Ctx.getELFSection(SectionName, Type, Flags, EntrySize, Group, IsComdat,
+ UniqueID, LinkedToSym);
// 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->getLinkedToSymbol() == LinkedToSym &&
@@ -880,13 +898,6 @@ static MCSectionELF *selectELFSectionForGlobal(
const TargetMachine &TM, bool EmitUniqueSection, unsigned Flags,
unsigned *NextUniqueID, const MCSymbolELF *AssociatedSymbol,
const MachineJumpTableEntry *MJTE = nullptr) {
-
- auto [Group, IsComdat, ExtraFlags] = getGlobalObjectInfo(GO, TM);
- Flags |= ExtraFlags;
-
- // Get the section entry size based on the kind.
- unsigned EntrySize = getEntrySizeForKind(Kind);
-
bool UniqueSectionName = false;
unsigned UniqueID = MCSection::NonUniqueID;
if (EmitUniqueSection) {
@@ -897,15 +908,18 @@ static MCSectionELF *selectELFSectionForGlobal(
(*NextUniqueID)++;
}
}
- SmallString<128> Name = getELFSectionNameForGlobal(
- GO, Kind, Mang, TM, EntrySize, UniqueSectionName, MJTE);
+ SmallString<128> Name =
+ getELFSectionNameForGlobal(GO, Kind, Mang, TM, UniqueSectionName, MJTE);
+
+ auto [Group, IsComdat, ExtraFlags, Type, EntrySize] =
+ getGlobalObjectInfo(GO, TM, Name, Kind);
+ Flags |= ExtraFlags;
// Use 0 as the unique ID for execute-only text.
if (Kind.isExecuteOnly())
UniqueID = 0;
- return Ctx.getELFSection(Name, getELFSectionType(Name, Kind), Flags,
- EntrySize, Group, IsComdat, UniqueID,
- AssociatedSymbol);
+ return Ctx.getELFSection(Name, Type, Flags, EntrySize, Group, IsComdat,
+ UniqueID, AssociatedSymbol);
}
static MCSection *selectELFSectionForGlobal(
@@ -927,6 +941,8 @@ static MCSection *selectELFSectionForGlobal(
Flags |= ELF::SHF_GNU_RETAIN;
}
}
+ if (GO->hasMetadata(LLVMContext::MD_elf_section_properties))
+ EmitUniqueSection = true;
MCSectionELF *Section = selectELFSectionForGlobal(
Ctx, GO, Kind, Mang, TM, EmitUniqueSection, Flags,
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index fe1854384e693..ec467e8b85739 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -803,6 +803,23 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) {
}
}
}
+
+ if (auto *Props = GO->getMetadata(LLVMContext::MD_elf_section_properties)) {
+ Check(Props->getNumOperands() == 2,
+ "elf_section_properties metadata must have two operands", GO,
+ Props);
+ if (Props->getNumOperands() == 2) {
+ auto *Type = dyn_cast<ConstantAsMetadata>(Props->getOperand(0));
+ Check(Type, "type field must be ConstantAsMetadata", GO, Props);
+ auto *TypeInt = dyn_cast<ConstantInt>(Type->getValue());
+ Check(TypeInt, "type field must be ConstantInt", GO, Props);
+
+ auto *Entsize = dyn_cast<ConstantAsMetadata>(Props->getOperand(1));
+ Check(Entsize, "entsize field must be ConstantAsMetadata", GO, Props);
+ auto *EntsizeInt = dyn_cast<ConstantInt>(Entsize->getValue());
+ Check(EntsizeInt, "entsize field must be ConstantInt", GO, Props);
+ }
+ }
}
Check(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV),
diff --git a/llvm/test/CodeGen/X86/elf-section-properties.ll b/llvm/test/CodeGen/X86/elf-section-properties.ll
new file mode 100644
index 0000000000000..071fdffd2ed6c
--- /dev/null
+++ b/llvm/test/CodeGen/X86/elf-section-properties.ll
@@ -0,0 +1,25 @@
+; RUN: llc < %s | FileCheck %s
+; RUN: llc -function-sections -data-sections < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: .section .text.implicit_section_func,"ax", at llvm_cfi_jump_table,2
+define void @implicit_section_func() !elf_section_properties !{i32 1879002126, i32 2} {
+ ret void
+}
+; CHECK: .section foo,"ax", at llvm_cfi_jump_table,4
+define void @explicit_section_func() section "foo" !elf_section_properties !{i32 1879002126, i32 4} {
+ ret void
+}
+; CHECK: .section foo,"ax", at llvm_cfi_jump_table,8,unique,1
+define void @explicit_section_func2() section "foo" !elf_section_properties !{i32 1879002126, i32 8} {
+ ret void
+}
+
+; CHECK: .section .data.implicit_section_global,"aw", at llvm_cfi_jump_table,8
+ at implicit_section_global = global i32 1, !elf_section_properties !{i32 1879002126, i32 8}
+; CHECK: .section bar,"aw", at llvm_cfi_jump_table,16
+ at explicit_section_global = global i32 1, !elf_section_properties !{i32 1879002126, i32 16}, section "bar"
+; CHECK: .section bar,"aw", at llvm_cfi_jump_table,32,unique,2
+ at explicit_section_global2 = global i32 1, !elf_section_properties !{i32 1879002126, i32 32}, section "bar"
diff --git a/llvm/test/Verifier/elf-section-properties.ll b/llvm/test/Verifier/elf-section-properties.ll
new file mode 100644
index 0000000000000..70e50655fc2f8
--- /dev/null
+++ b/llvm/test/Verifier/elf-section-properties.ll
@@ -0,0 +1,12 @@
+; RUN: not llvm-as -disable-output < %s 2>&1 | FileCheck %s
+
+; CHECK: elf_section_properties metadata must have two operands
+ at g1 = global i32 0, !elf_section_properties !{i32 0}
+; CHECK: type field must be ConstantAsMetadata
+ at g2 = global i32 0, !elf_section_properties !{!{}, i32 0}
+; CHECK: entsize field must be ConstantAsMetadata
+ at g3 = global i32 0, !elf_section_properties !{i32 0, !{}}
+; CHECK: type field must be ConstantInt
+ at g4 = global i32 0, !elf_section_properties !{float 0.0, i32 0}
+; CHECK: entsize field must be ConstantInt
+ at g5 = global i32 0, !elf_section_properties !{i32 0, float 0.0}
More information about the llvm-commits
mailing list