Author: Vinicius Tadeu Zein Date: 2025-01-21T16:12:58-08:00 New Revision: 6ab9dafec807a64a4e940bfaecc815e23454dfe8
URL: https://github.com/llvm/llvm-project/commit/6ab9dafec807a64a4e940bfaecc815e23454dfe8 DIFF: https://github.com/llvm/llvm-project/commit/6ab9dafec807a64a4e940bfaecc815e23454dfe8.diff LOG: [clang] Implement #pragma clang section on COFF targets (#112714) This patch implements the directive #pragma clang section on COFF targets with the exact same features available on ELF and Mach-O. Added: llvm/test/CodeGen/X86/clang-section-coff.ll Modified: clang/docs/LanguageExtensions.rst clang/docs/ReleaseNotes.rst clang/test/Sema/pragma-clang-section.c llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp Removed: ################################################################################ diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index bbeeefe82282b9..c42b88015e2695 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -5656,7 +5656,7 @@ The ``#pragma clang section`` directive obeys the following rules: * The pragma clang section is enabled automatically, without need of any flags. -* This feature is only defined to work sensibly for ELF and Mach-O targets. +* This feature is only defined to work sensibly for ELF, Mach-O and COFF targets. * If section name is specified through _attribute_((section("myname"))), then the attribute name gains precedence. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index da9569759a4081..f19be0446d3fec 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1124,6 +1124,8 @@ Windows Support When `-fms-compatibility-version=18.00` or prior is set on the command line this Microsoft extension is still allowed as VS2013 and prior allow it. +- Clang now supports the ``#pragma clang section`` directive for COFF targets. + LoongArch Support ^^^^^^^^^^^^^^^^^ diff --git a/clang/test/Sema/pragma-clang-section.c b/clang/test/Sema/pragma-clang-section.c index 458c91c2cf31cd..e33e1dfe8cbef7 100644 --- a/clang/test/Sema/pragma-clang-section.c +++ b/clang/test/Sema/pragma-clang-section.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -triple arm-none-eabi +// RUN: %clang_cc1 -fsyntax-only -verify %s -triple arm64-windows-msvc #pragma clang section bss = "mybss.1" data = "mydata.1" rodata = "myrodata.1" text = "mytext.1" // expected-note 2 {{#pragma entered here}} #pragma clang section bss="" data="" rodata="" text="" #pragma clang section diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index be243c0e74e9db..7db949ffde7883 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -788,29 +788,35 @@ getGlobalObjectInfo(const GlobalObject *GO, const TargetMachine &TM) { return {Group, IsComdat, Flags}; } -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(); - +static StringRef handlePragmaClangSection(const GlobalObject *GO, + SectionKind Kind) { // Check if '#pragma clang section' name is applicable. // Note that pragma directive overrides -ffunction-section, -fdata-section // and so section name is exactly as user specified and not uniqued. const GlobalVariable *GV = dyn_cast<GlobalVariable>(GO); if (GV && GV->hasImplicitSection()) { auto Attrs = GV->getAttributes(); - if (Attrs.hasAttribute("bss-section") && Kind.isBSS()) { - SectionName = Attrs.getAttribute("bss-section").getValueAsString(); - } else if (Attrs.hasAttribute("rodata-section") && Kind.isReadOnly()) { - SectionName = Attrs.getAttribute("rodata-section").getValueAsString(); - } else if (Attrs.hasAttribute("relro-section") && Kind.isReadOnlyWithRel()) { - SectionName = Attrs.getAttribute("relro-section").getValueAsString(); - } else if (Attrs.hasAttribute("data-section") && Kind.isData()) { - SectionName = Attrs.getAttribute("data-section").getValueAsString(); - } + if (Attrs.hasAttribute("bss-section") && Kind.isBSS()) + return Attrs.getAttribute("bss-section").getValueAsString(); + else if (Attrs.hasAttribute("rodata-section") && Kind.isReadOnly()) + return Attrs.getAttribute("rodata-section").getValueAsString(); + else if (Attrs.hasAttribute("relro-section") && Kind.isReadOnlyWithRel()) + return Attrs.getAttribute("relro-section").getValueAsString(); + else if (Attrs.hasAttribute("data-section") && Kind.isData()) + return Attrs.getAttribute("data-section").getValueAsString(); } + return GO->getSection(); +} + +static MCSection *selectExplicitSectionGlobal(const GlobalObject *GO, + SectionKind Kind, + const TargetMachine &TM, + MCContext &Ctx, Mangler &Mang, + unsigned &NextUniqueID, + bool Retain, bool ForceUnique) { + StringRef SectionName = handlePragmaClangSection(GO, Kind); + // Infer section flags from the section name if we can. Kind = getELFKindForNamedSection(SectionName, Kind); @@ -1291,21 +1297,7 @@ static void checkMachOComdat(const GlobalValue *GV) { MCSection *TargetLoweringObjectFileMachO::getExplicitSectionGlobal( const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { - StringRef SectionName = GO->getSection(); - - const GlobalVariable *GV = dyn_cast<GlobalVariable>(GO); - if (GV && GV->hasImplicitSection()) { - auto Attrs = GV->getAttributes(); - if (Attrs.hasAttribute("bss-section") && Kind.isBSS()) { - SectionName = Attrs.getAttribute("bss-section").getValueAsString(); - } else if (Attrs.hasAttribute("rodata-section") && Kind.isReadOnly()) { - SectionName = Attrs.getAttribute("rodata-section").getValueAsString(); - } else if (Attrs.hasAttribute("relro-section") && Kind.isReadOnlyWithRel()) { - SectionName = Attrs.getAttribute("relro-section").getValueAsString(); - } else if (Attrs.hasAttribute("data-section") && Kind.isData()) { - SectionName = Attrs.getAttribute("data-section").getValueAsString(); - } - } + StringRef SectionName = handlePragmaClangSection(GO, Kind); // Parse the section specifier and create it if valid. StringRef Segment, Section; @@ -1674,7 +1666,7 @@ static int getSelectionForCOFF(const GlobalValue *GV) { MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal( const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { - StringRef Name = GO->getSection(); + StringRef Name = handlePragmaClangSection(GO, Kind); if (Name == getInstrProfSectionName(IPSK_covmap, Triple::COFF, /*AddSegmentInfo=*/false) || Name == getInstrProfSectionName(IPSK_covfun, Triple::COFF, diff --git a/llvm/test/CodeGen/X86/clang-section-coff.ll b/llvm/test/CodeGen/X86/clang-section-coff.ll new file mode 100644 index 00000000000000..02381fd256aaa1 --- /dev/null +++ b/llvm/test/CodeGen/X86/clang-section-coff.ll @@ -0,0 +1,146 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +;RUN: llc -mtriple=x86_64-windows-msvc %s -o - | FileCheck %s +;Test that global variables and functions are assigned to correct sections. + +@a = global i32 0, align 4 #0 +@b = global i32 1, align 4 #0 +@c = global [4 x i32] zeroinitializer, align 4 #0 +@d = global [5 x i16] zeroinitializer, align 2 #0 +@e = global [6 x i16] [i16 0, i16 0, i16 1, i16 0, i16 0, i16 0], align 2 #0 +@f = constant i32 2, align 4 #0 +@h = global i32 0, align 4 #1 +@i = global i32 0, align 4 #2 +@j = constant i32 4, align 4 #2 +@k = global i32 0, align 4 #2 +@_ZZ3gooE7lstat_h = internal global i32 0, align 4 #2 +@_ZL1g = internal global [2 x i32] zeroinitializer, align 4 #0 +@l = global i32 5, align 4 #3 +@m = constant i32 6, align 4 #3 +@n = global i32 0, align 4 +@o = global i32 6, align 4 +@p = constant i32 7, align 4 + +declare i32 @zoo(ptr, ptr) #6 + +; Function Attrs: noinline nounwind +define i32 @hoo() #7 { +; CHECK-LABEL: hoo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movl b(%rip), %eax +; CHECK-NEXT: retq +entry: + %0 = load i32, ptr @b, align 4 + ret i32 %0 +} + +attributes #0 = { "bss-section"="my_bss.1" "data-section"="my_data.1" "rodata-section"="my_rodata.1" } +attributes #1 = { "data-section"="my_data.1" "rodata-section"="my_rodata.1" } +attributes #2 = { "bss-section"="my_bss.2" "rodata-section"="my_rodata.1" } +attributes #3 = { "bss-section"="my_bss.2" "data-section"="my_data.2" "rodata-section"="my_rodata.2" } +attributes #6 = { "correctly-rounded-divide-sqrt-fp-math"="false" "denormal-fp-math"="preserve-sign,preserve-sign" "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #7 = { noinline nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "denormal-fp-math"="preserve-sign,preserve-sign" "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="true" "no-jump-tables"="false" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.module.flags = !{!0, !1, !2, !3} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"static_rwdata", i32 1} +!2 = !{i32 1, !"enumsize_buildattr", i32 2} +!3 = !{i32 1, !"armlib_unavailable", i32 0} + +;CHECK: .section my_bss.1,"bw" +;CHECK: .globl a # @a +;CHECK: .p2align 2, 0x0 +;CHECK: a: +;CHECK: .long 0 # 0x0 + +;CHECK: .section my_data.1,"dw" +;CHECK: .globl b # @b +;CHECK: .p2align 2, 0x0 +;CHECK: b: +;CHECK: .long 1 # 0x1 + +;CHECK: .section my_bss.1,"bw" +;CHECK: .globl c # @c +;CHECK: .p2align 2, 0x0 +;CHECK: c: +;CHECK: .zero 16 +;CHECK: .globl d # @d +;CHECK: .p2align 1, 0x0 +;CHECK: d: +;CHECK: .zero 10 + +;CHECK: .section my_data.1,"dw" +;CHECK: .globl e # @e +;CHECK: .p2align 1, 0x0 +;CHECK: e: +;CHECK: .short 0 # 0x0 +;CHECK: .short 0 # 0x0 +;CHECK: .short 1 # 0x1 +;CHECK: .short 0 # 0x0 +;CHECK: .short 0 # 0x0 +;CHECK: .short 0 # 0x0 + +;CHECK: .section my_rodata.1,"dr" +;CHECK: .globl f # @f +;CHECK: .p2align 2, 0x0 +;CHECK: f: +;CHECK: .long 2 # 0x2 +;CHECK: .bss +;CHECK: .globl h # @h +;CHECK: .p2align 2, 0x0 +;CHECK: h: +;CHECK: .long 0 # 0x0 + +;CHECK: .section my_bss.2,"bw" +;CHECK: .globl i # @i +;CHECK: .p2align 2, 0x0 +;CHECK: i: +;CHECK: .long 0 # 0x0 + +;CHECK: .section my_rodata.1,"dr" +;CHECK: .globl j # @j +;CHECK: .p2align 2, 0x0 +;CHECK: j: +;CHECK: .long 4 # 0x4 + +;CHECK: .section my_bss.2,"bw" +;CHECK: .globl k # @k +;CHECK: .p2align 2, 0x0 +;CHECK: k: +;CHECK: .long 0 # 0x0 +;CHECK: .p2align 2, 0x0 # @_ZZ3gooE7lstat_h +;CHECK: _ZZ3gooE7lstat_h: +;CHECK: .long 0 # 0x0 + +;CHECK: .section my_bss.1,"bw" +;CHECK: .p2align 2, 0x0 # @_ZL1g +;CHECK: _ZL1g: +;CHECK: .zero 8 + +;CHECK: .section my_data.2,"dw" +;CHECK: .globl l # @l +;CHECK: .p2align 2, 0x0 +;CHECK: l: +;CHECK: .long 5 # 0x5 + +;CHECK: .section my_rodata.2,"dr" +;CHECK: .globl m # @m +;CHECK: .p2align 2, 0x0 +;CHECK: m: +;CHECK: .long 6 # 0x6 +;CHECK: .bss +;CHECK: .globl n # @n +;CHECK: .p2align 2, 0x0 +;CHECK: n: +;CHECK: .long 0 # 0x0 +;CHECK: .data +;CHECK: .globl o # @o +;CHECK: .p2align 2, 0x0 +;CHECK: o: +;CHECK: .long 6 # 0x6 + +;CHECK: .section .rdata,"dr" +;CHECK: .globl p # @p +;CHECK: .p2align 2, 0x0 +;CHECK: p: +;CHECK: .long 7 # 0x7 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits