Skip to content

Commit 6ab9daf

Browse files
authored
[clang] Implement #pragma clang section on COFF targets (llvm#112714)
This patch implements the directive #pragma clang section on COFF targets with the exact same features available on ELF and Mach-O.
1 parent 8a5f1ef commit 6ab9daf

File tree

5 files changed

+173
-32
lines changed

5 files changed

+173
-32
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5656,7 +5656,7 @@ The ``#pragma clang section`` directive obeys the following rules:
56565656
56575657
* The pragma clang section is enabled automatically, without need of any flags.
56585658
5659-
* This feature is only defined to work sensibly for ELF and Mach-O targets.
5659+
* This feature is only defined to work sensibly for ELF, Mach-O and COFF targets.
56605660
56615661
* If section name is specified through _attribute_((section("myname"))), then
56625662
the attribute name gains precedence.

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,8 @@ Windows Support
11241124
When `-fms-compatibility-version=18.00` or prior is set on the command line this Microsoft extension is still
11251125
allowed as VS2013 and prior allow it.
11261126

1127+
- Clang now supports the ``#pragma clang section`` directive for COFF targets.
1128+
11271129
LoongArch Support
11281130
^^^^^^^^^^^^^^^^^
11291131

clang/test/Sema/pragma-clang-section.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple arm-none-eabi
2+
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple arm64-windows-msvc
23
#pragma clang section bss = "mybss.1" data = "mydata.1" rodata = "myrodata.1" text = "mytext.1" // expected-note 2 {{#pragma entered here}}
34
#pragma clang section bss="" data="" rodata="" text=""
45
#pragma clang section

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -788,29 +788,35 @@ getGlobalObjectInfo(const GlobalObject *GO, const TargetMachine &TM) {
788788
return {Group, IsComdat, Flags};
789789
}
790790

791-
static MCSection *selectExplicitSectionGlobal(
792-
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM,
793-
MCContext &Ctx, Mangler &Mang, unsigned &NextUniqueID,
794-
bool Retain, bool ForceUnique) {
795-
StringRef SectionName = GO->getSection();
796-
791+
static StringRef handlePragmaClangSection(const GlobalObject *GO,
792+
SectionKind Kind) {
797793
// Check if '#pragma clang section' name is applicable.
798794
// Note that pragma directive overrides -ffunction-section, -fdata-section
799795
// and so section name is exactly as user specified and not uniqued.
800796
const GlobalVariable *GV = dyn_cast<GlobalVariable>(GO);
801797
if (GV && GV->hasImplicitSection()) {
802798
auto Attrs = GV->getAttributes();
803-
if (Attrs.hasAttribute("bss-section") && Kind.isBSS()) {
804-
SectionName = Attrs.getAttribute("bss-section").getValueAsString();
805-
} else if (Attrs.hasAttribute("rodata-section") && Kind.isReadOnly()) {
806-
SectionName = Attrs.getAttribute("rodata-section").getValueAsString();
807-
} else if (Attrs.hasAttribute("relro-section") && Kind.isReadOnlyWithRel()) {
808-
SectionName = Attrs.getAttribute("relro-section").getValueAsString();
809-
} else if (Attrs.hasAttribute("data-section") && Kind.isData()) {
810-
SectionName = Attrs.getAttribute("data-section").getValueAsString();
811-
}
799+
if (Attrs.hasAttribute("bss-section") && Kind.isBSS())
800+
return Attrs.getAttribute("bss-section").getValueAsString();
801+
else if (Attrs.hasAttribute("rodata-section") && Kind.isReadOnly())
802+
return Attrs.getAttribute("rodata-section").getValueAsString();
803+
else if (Attrs.hasAttribute("relro-section") && Kind.isReadOnlyWithRel())
804+
return Attrs.getAttribute("relro-section").getValueAsString();
805+
else if (Attrs.hasAttribute("data-section") && Kind.isData())
806+
return Attrs.getAttribute("data-section").getValueAsString();
812807
}
813808

809+
return GO->getSection();
810+
}
811+
812+
static MCSection *selectExplicitSectionGlobal(const GlobalObject *GO,
813+
SectionKind Kind,
814+
const TargetMachine &TM,
815+
MCContext &Ctx, Mangler &Mang,
816+
unsigned &NextUniqueID,
817+
bool Retain, bool ForceUnique) {
818+
StringRef SectionName = handlePragmaClangSection(GO, Kind);
819+
814820
// Infer section flags from the section name if we can.
815821
Kind = getELFKindForNamedSection(SectionName, Kind);
816822

@@ -1291,21 +1297,7 @@ static void checkMachOComdat(const GlobalValue *GV) {
12911297
MCSection *TargetLoweringObjectFileMachO::getExplicitSectionGlobal(
12921298
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
12931299

1294-
StringRef SectionName = GO->getSection();
1295-
1296-
const GlobalVariable *GV = dyn_cast<GlobalVariable>(GO);
1297-
if (GV && GV->hasImplicitSection()) {
1298-
auto Attrs = GV->getAttributes();
1299-
if (Attrs.hasAttribute("bss-section") && Kind.isBSS()) {
1300-
SectionName = Attrs.getAttribute("bss-section").getValueAsString();
1301-
} else if (Attrs.hasAttribute("rodata-section") && Kind.isReadOnly()) {
1302-
SectionName = Attrs.getAttribute("rodata-section").getValueAsString();
1303-
} else if (Attrs.hasAttribute("relro-section") && Kind.isReadOnlyWithRel()) {
1304-
SectionName = Attrs.getAttribute("relro-section").getValueAsString();
1305-
} else if (Attrs.hasAttribute("data-section") && Kind.isData()) {
1306-
SectionName = Attrs.getAttribute("data-section").getValueAsString();
1307-
}
1308-
}
1300+
StringRef SectionName = handlePragmaClangSection(GO, Kind);
13091301

13101302
// Parse the section specifier and create it if valid.
13111303
StringRef Segment, Section;
@@ -1674,7 +1666,7 @@ static int getSelectionForCOFF(const GlobalValue *GV) {
16741666

16751667
MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal(
16761668
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
1677-
StringRef Name = GO->getSection();
1669+
StringRef Name = handlePragmaClangSection(GO, Kind);
16781670
if (Name == getInstrProfSectionName(IPSK_covmap, Triple::COFF,
16791671
/*AddSegmentInfo=*/false) ||
16801672
Name == getInstrProfSectionName(IPSK_covfun, Triple::COFF,
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
;RUN: llc -mtriple=x86_64-windows-msvc %s -o - | FileCheck %s
3+
;Test that global variables and functions are assigned to correct sections.
4+
5+
@a = global i32 0, align 4 #0
6+
@b = global i32 1, align 4 #0
7+
@c = global [4 x i32] zeroinitializer, align 4 #0
8+
@d = global [5 x i16] zeroinitializer, align 2 #0
9+
@e = global [6 x i16] [i16 0, i16 0, i16 1, i16 0, i16 0, i16 0], align 2 #0
10+
@f = constant i32 2, align 4 #0
11+
@h = global i32 0, align 4 #1
12+
@i = global i32 0, align 4 #2
13+
@j = constant i32 4, align 4 #2
14+
@k = global i32 0, align 4 #2
15+
@_ZZ3gooE7lstat_h = internal global i32 0, align 4 #2
16+
@_ZL1g = internal global [2 x i32] zeroinitializer, align 4 #0
17+
@l = global i32 5, align 4 #3
18+
@m = constant i32 6, align 4 #3
19+
@n = global i32 0, align 4
20+
@o = global i32 6, align 4
21+
@p = constant i32 7, align 4
22+
23+
declare i32 @zoo(ptr, ptr) #6
24+
25+
; Function Attrs: noinline nounwind
26+
define i32 @hoo() #7 {
27+
; CHECK-LABEL: hoo:
28+
; CHECK: # %bb.0: # %entry
29+
; CHECK-NEXT: movl b(%rip), %eax
30+
; CHECK-NEXT: retq
31+
entry:
32+
%0 = load i32, ptr @b, align 4
33+
ret i32 %0
34+
}
35+
36+
attributes #0 = { "bss-section"="my_bss.1" "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
37+
attributes #1 = { "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
38+
attributes #2 = { "bss-section"="my_bss.2" "rodata-section"="my_rodata.1" }
39+
attributes #3 = { "bss-section"="my_bss.2" "data-section"="my_data.2" "rodata-section"="my_rodata.2" }
40+
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" }
41+
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" }
42+
43+
!llvm.module.flags = !{!0, !1, !2, !3}
44+
45+
!0 = !{i32 1, !"wchar_size", i32 4}
46+
!1 = !{i32 1, !"static_rwdata", i32 1}
47+
!2 = !{i32 1, !"enumsize_buildattr", i32 2}
48+
!3 = !{i32 1, !"armlib_unavailable", i32 0}
49+
50+
;CHECK: .section my_bss.1,"bw"
51+
;CHECK: .globl a # @a
52+
;CHECK: .p2align 2, 0x0
53+
;CHECK: a:
54+
;CHECK: .long 0 # 0x0
55+
56+
;CHECK: .section my_data.1,"dw"
57+
;CHECK: .globl b # @b
58+
;CHECK: .p2align 2, 0x0
59+
;CHECK: b:
60+
;CHECK: .long 1 # 0x1
61+
62+
;CHECK: .section my_bss.1,"bw"
63+
;CHECK: .globl c # @c
64+
;CHECK: .p2align 2, 0x0
65+
;CHECK: c:
66+
;CHECK: .zero 16
67+
;CHECK: .globl d # @d
68+
;CHECK: .p2align 1, 0x0
69+
;CHECK: d:
70+
;CHECK: .zero 10
71+
72+
;CHECK: .section my_data.1,"dw"
73+
;CHECK: .globl e # @e
74+
;CHECK: .p2align 1, 0x0
75+
;CHECK: e:
76+
;CHECK: .short 0 # 0x0
77+
;CHECK: .short 0 # 0x0
78+
;CHECK: .short 1 # 0x1
79+
;CHECK: .short 0 # 0x0
80+
;CHECK: .short 0 # 0x0
81+
;CHECK: .short 0 # 0x0
82+
83+
;CHECK: .section my_rodata.1,"dr"
84+
;CHECK: .globl f # @f
85+
;CHECK: .p2align 2, 0x0
86+
;CHECK: f:
87+
;CHECK: .long 2 # 0x2
88+
;CHECK: .bss
89+
;CHECK: .globl h # @h
90+
;CHECK: .p2align 2, 0x0
91+
;CHECK: h:
92+
;CHECK: .long 0 # 0x0
93+
94+
;CHECK: .section my_bss.2,"bw"
95+
;CHECK: .globl i # @i
96+
;CHECK: .p2align 2, 0x0
97+
;CHECK: i:
98+
;CHECK: .long 0 # 0x0
99+
100+
;CHECK: .section my_rodata.1,"dr"
101+
;CHECK: .globl j # @j
102+
;CHECK: .p2align 2, 0x0
103+
;CHECK: j:
104+
;CHECK: .long 4 # 0x4
105+
106+
;CHECK: .section my_bss.2,"bw"
107+
;CHECK: .globl k # @k
108+
;CHECK: .p2align 2, 0x0
109+
;CHECK: k:
110+
;CHECK: .long 0 # 0x0
111+
;CHECK: .p2align 2, 0x0 # @_ZZ3gooE7lstat_h
112+
;CHECK: _ZZ3gooE7lstat_h:
113+
;CHECK: .long 0 # 0x0
114+
115+
;CHECK: .section my_bss.1,"bw"
116+
;CHECK: .p2align 2, 0x0 # @_ZL1g
117+
;CHECK: _ZL1g:
118+
;CHECK: .zero 8
119+
120+
;CHECK: .section my_data.2,"dw"
121+
;CHECK: .globl l # @l
122+
;CHECK: .p2align 2, 0x0
123+
;CHECK: l:
124+
;CHECK: .long 5 # 0x5
125+
126+
;CHECK: .section my_rodata.2,"dr"
127+
;CHECK: .globl m # @m
128+
;CHECK: .p2align 2, 0x0
129+
;CHECK: m:
130+
;CHECK: .long 6 # 0x6
131+
;CHECK: .bss
132+
;CHECK: .globl n # @n
133+
;CHECK: .p2align 2, 0x0
134+
;CHECK: n:
135+
;CHECK: .long 0 # 0x0
136+
;CHECK: .data
137+
;CHECK: .globl o # @o
138+
;CHECK: .p2align 2, 0x0
139+
;CHECK: o:
140+
;CHECK: .long 6 # 0x6
141+
142+
;CHECK: .section .rdata,"dr"
143+
;CHECK: .globl p # @p
144+
;CHECK: .p2align 2, 0x0
145+
;CHECK: p:
146+
;CHECK: .long 7 # 0x7

0 commit comments

Comments
 (0)