Skip to content

Commit e092165

Browse files
committed
[AIX] Implement AIX special bitfield related alignment rules
1.[bool, char, short] bitfields have the same alignment as unsigned int 2.Adjust alignment on typedef field decls/honor align attribute 3.Fix alignment for scoped enum class 4.Long long bitfield has 4bytes alignment and StorageUnitSize under 32 bit compile mode Differential Revision: https://reviews.llvm.org/D87029
1 parent ab5ff15 commit e092165

File tree

3 files changed

+301
-2
lines changed

3 files changed

+301
-2
lines changed

clang/lib/AST/RecordLayoutBuilder.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,12 +1528,17 @@ void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
15281528
UpdateAlignment(TypeAlign);
15291529
}
15301530

1531+
static bool isAIXLayout(const ASTContext &Context) {
1532+
return Context.getTargetInfo().getTriple().getOS() == llvm::Triple::AIX;
1533+
}
1534+
15311535
void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
15321536
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
15331537
uint64_t FieldSize = D->getBitWidthValue(Context);
15341538
TypeInfo FieldInfo = Context.getTypeInfo(D->getType());
15351539
uint64_t StorageUnitSize = FieldInfo.Width;
15361540
unsigned FieldAlign = FieldInfo.Align;
1541+
bool AlignIsRequired = FieldInfo.AlignIsRequired;
15371542

15381543
// UnfilledBitsInLastUnit is the difference between the end of the
15391544
// last allocated bitfield (i.e. the first bit offset available for
@@ -1611,9 +1616,33 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
16111616
}
16121617
}
16131618

1619+
if (isAIXLayout(Context)) {
1620+
if (StorageUnitSize < Context.getTypeSize(Context.UnsignedIntTy)) {
1621+
// On AIX, [bool, char, short] bitfields have the same alignment
1622+
// as [unsigned].
1623+
StorageUnitSize = Context.getTypeSize(Context.UnsignedIntTy);
1624+
} else if (StorageUnitSize > Context.getTypeSize(Context.UnsignedIntTy) &&
1625+
Context.getTargetInfo().getTriple().isArch32Bit() &&
1626+
FieldSize <= 32) {
1627+
// Under 32-bit compile mode, the bitcontainer is 32 bits if a single
1628+
// long long bitfield has length no greater than 32 bits.
1629+
StorageUnitSize = 32;
1630+
1631+
if (!AlignIsRequired)
1632+
FieldAlign = 32;
1633+
}
1634+
1635+
if (FieldAlign < StorageUnitSize) {
1636+
// The bitfield alignment should always be greater than or equal to
1637+
// bitcontainer size.
1638+
FieldAlign = StorageUnitSize;
1639+
}
1640+
}
1641+
16141642
// If the field is wider than its declared type, it follows
1615-
// different rules in all cases.
1616-
if (FieldSize > StorageUnitSize) {
1643+
// different rules in all cases, except on AIX.
1644+
// On AIX, wide bitfield follows the same rules as normal bitfield.
1645+
if (FieldSize > StorageUnitSize && !isAIXLayout(Context)) {
16171646
LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked, D);
16181647
return;
16191648
}
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \
2+
// RUN: -fsyntax-only -fxl-pragma-pack -x c %s | \
3+
// RUN: FileCheck --check-prefixes=CHECK,CHECK32 %s
4+
// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \
5+
// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | \
6+
// RUN: FileCheck --check-prefixes=CHECK,CHECK32 %s
7+
8+
// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
9+
// RUN: -fsyntax-only -fxl-pragma-pack -x c %s | \
10+
// RUN: FileCheck --check-prefixes=CHECK,CHECK64 %s
11+
// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
12+
// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | \
13+
// RUN: FileCheck --check-prefixes=CHECK,CHECK64 %s
14+
15+
struct A {
16+
unsigned char c : 2;
17+
} A;
18+
19+
int a = sizeof(A);
20+
21+
// CHECK: *** Dumping AST Record Layout
22+
// CHECK-NEXT: 0 | struct A
23+
// CHECK-NEXT: 0:0-1 | unsigned char c
24+
// CHECK-NEXT: sizeof=4, {{(dsize=4, )?}}align=4, preferredalign=4
25+
26+
struct B {
27+
char c;
28+
int : 0;
29+
} B;
30+
31+
int b = sizeof(B);
32+
33+
// CHECK: *** Dumping AST Record Layout
34+
// CHECK-NEXT: 0 | struct B
35+
// CHECK-NEXT: 0 | char c
36+
// CHECK-NEXT: 4:- | int
37+
// CHECK-NEXT: sizeof=4, {{(dsize=4, )?}}align=4, preferredalign=4
38+
39+
struct C {
40+
signed int a1 : 6;
41+
signed char a2 : 4;
42+
short int a3 : 2;
43+
int a4 : 2;
44+
signed long a5 : 5;
45+
long long int a6 : 6;
46+
unsigned long a7 : 8;
47+
} C;
48+
49+
int c = sizeof(C);
50+
51+
// CHECK: *** Dumping AST Record Layout
52+
// CHECK-NEXT: 0 | struct C
53+
// CHECK-NEXT: 0:0-5 | int a1
54+
// CHECK-NEXT: 0:6-9 | signed char a2
55+
// CHECK-NEXT: 1:2-3 | short a3
56+
// CHECK-NEXT: 1:4-5 | int a4
57+
// CHECK-NEXT: 1:6-10 | long a5
58+
// CHECK-NEXT: 2:3-8 | long long a6
59+
// CHECK32: 4:0-7 | unsigned long a7
60+
// CHECK32: sizeof=8, {{(dsize=8, )?}}align=4, preferredalign=4
61+
// CHECK64: 3:1-8 | unsigned long a7
62+
// CHECK64: sizeof=8, {{(dsize=8, )?}}align=8, preferredalign=8
63+
64+
#pragma align(packed)
65+
struct C1 {
66+
signed int a1 : 6;
67+
signed char a2 : 4;
68+
short int a3 : 2;
69+
int a4 : 2;
70+
signed long a5 : 5;
71+
long long int a6 : 6;
72+
unsigned long a7 : 8;
73+
} C1;
74+
#pragma align(reset)
75+
76+
int c1 = sizeof(C1);
77+
78+
// CHECK: *** Dumping AST Record Layout
79+
// CHECK-NEXT: 0 | struct C1
80+
// CHECK-NEXT: 0:0-5 | int a1
81+
// CHECK-NEXT: 0:6-9 | signed char a2
82+
// CHECK-NEXT: 1:2-3 | short a3
83+
// CHECK-NEXT: 1:4-5 | int a4
84+
// CHECK-NEXT: 1:6-10 | long a5
85+
// CHECK-NEXT: 2:3-8 | long long a6
86+
// CHECK-NEXT: 3:1-8 | unsigned long a7
87+
// CHECK-NEXT: sizeof=5, {{(dsize=5, )?}}align=1, preferredalign=1
88+
89+
#pragma pack(4)
90+
struct C2 {
91+
signed int a1 : 6;
92+
signed char a2 : 4;
93+
short int a3 : 2;
94+
int a4 : 2;
95+
signed long a5 : 5;
96+
long long int a6 : 6;
97+
unsigned long a7 : 8;
98+
} C2;
99+
#pragma pack(pop)
100+
101+
int c2 = sizeof(C2);
102+
103+
// CHECK: *** Dumping AST Record Layout
104+
// CHECK-NEXT: 0 | struct C2
105+
// CHECK-NEXT: 0:0-5 | int a1
106+
// CHECK-NEXT: 0:6-9 | signed char a2
107+
// CHECK-NEXT: 1:2-3 | short a3
108+
// CHECK-NEXT: 1:4-5 | int a4
109+
// CHECK-NEXT: 1:6-10 | long a5
110+
// CHECK-NEXT: 2:3-8 | long long a6
111+
// CHECK-NEXT: 3:1-8 | unsigned long a7
112+
// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=4, preferredalign=4
113+
114+
typedef __attribute__((aligned(32))) short mySHORT;
115+
struct D {
116+
char c : 8;
117+
mySHORT : 0;
118+
} D;
119+
120+
int d = sizeof(D);
121+
122+
// CHECK: *** Dumping AST Record Layout
123+
// CHECK-NEXT: 0 | struct D
124+
// CHECK-NEXT: 0:0-7 | char c
125+
// CHECK-NEXT: 32:- | mySHORT
126+
// CHECK-NEXT: sizeof=32, {{(dsize=32, )?}}align=32, preferredalign=32
127+
128+
typedef __attribute__((aligned(32))) long myLONG;
129+
struct D11 {
130+
char c : 8;
131+
myLONG : 0;
132+
} D11;
133+
134+
int d11 = sizeof(D11);
135+
136+
// CHECK: *** Dumping AST Record Layout
137+
// CHECK-NEXT: 0 | struct D11
138+
// CHECK-NEXT: 0:0-7 | char c
139+
// CHECK-NEXT: 32:- | myLONG
140+
// CHECK-NEXT: sizeof=32, {{(dsize=32, )?}}align=32, preferredalign=32
141+
142+
typedef __attribute__((aligned(2))) long myLONG2;
143+
struct D12 {
144+
char c : 8;
145+
myLONG2 : 0;
146+
} D12;
147+
148+
int d12 = sizeof(D12);
149+
150+
// CHECK: *** Dumping AST Record Layout
151+
// CHECK-NEXT: 0 | struct D12
152+
// CHECK-NEXT: 0:0-7 | char c
153+
// CHECK32: 4:- | myLONG2
154+
// CHECK32: sizeof=4, {{(dsize=4, )?}}align=4, preferredalign=4
155+
// CHECK64: 8:- | myLONG2
156+
// CHECK64: sizeof=8, {{(dsize=8, )?}}align=8, preferredalign=8
157+
158+
typedef __attribute__((aligned(32))) long long myLONGLONG;
159+
struct D21 {
160+
char c : 8;
161+
myLONGLONG : 0;
162+
} D21;
163+
164+
int d21 = sizeof(D21);
165+
166+
// CHECK: *** Dumping AST Record Layout
167+
// CHECK-NEXT: 0 | struct D21
168+
// CHECK-NEXT: 0:0-7 | char c
169+
// CHECK-NEXT: 32:- | myLONGLONG
170+
// CHECK-NEXT: sizeof=32, {{(dsize=32, )?}}align=32, preferredalign=32
171+
172+
typedef __attribute__((aligned(2))) long long myLONGLONG2;
173+
struct D22 {
174+
char c : 8;
175+
myLONGLONG2 : 0;
176+
} D22;
177+
178+
int d22 = sizeof(D22);
179+
180+
// CHECK: *** Dumping AST Record Layout
181+
// CHECK-NEXT: 0 | struct D22
182+
// CHECK-NEXT: 0:0-7 | char c
183+
// CHECK32: 4:- | myLONGLONG2
184+
// CHECK32: sizeof=4, {{(dsize=4, )?}}align=4, preferredalign=4
185+
// CHECK64: 8:- | myLONGLONG2
186+
// CHECK64: sizeof=8, {{(dsize=8, )?}}align=8, preferredalign=8
187+
188+
enum LL : unsigned long long { val = 1 };
189+
190+
struct E {
191+
enum LL e : 32;
192+
} E;
193+
194+
int e = sizeof(E);
195+
196+
// CHECK: *** Dumping AST Record Layout
197+
// CHECK-NEXT: 0 | struct E
198+
// CHECK-NEXT: 0:0-31 | enum LL e
199+
// CHECK32-NEXT: sizeof=4, {{(dsize=4, )?}}align=4, preferredalign=4
200+
// CHECK64-NEXT: sizeof=8, {{(dsize=8, )?}}align=8, preferredalign=8
201+
202+
enum LL1 : unsigned long long { val1 = 1 } __attribute__((aligned(16)));
203+
struct E1 {
204+
enum LL1 e : 32;
205+
} E1;
206+
207+
int e1 = sizeof(E1);
208+
209+
// CHECK: *** Dumping AST Record Layout
210+
// CHECK-NEXT: 0 | struct E1
211+
// CHECK-NEXT: 0:0-31 | enum LL1 e
212+
// CHECK-NEXT: sizeof=16, {{(dsize=16, )?}}align=16, preferredalign=16
213+
214+
struct F {
215+
long long l : 32 __attribute__((aligned(16)));
216+
} F;
217+
218+
int f = sizeof(F);
219+
220+
// CHECK: *** Dumping AST Record Layout
221+
// CHECK-NEXT: 0 | struct F
222+
// CHECK-NEXT: 0:0-31 | long long l
223+
// CHECK-NEXT: sizeof=16, {{(dsize=16, )?}}align=16, preferredalign=16
224+
225+
struct G {
226+
long long ll : 45;
227+
} G;
228+
229+
int s = sizeof(G);
230+
231+
// CHECK: *** Dumping AST Record Layout
232+
// CHECK-NEXT: 0 | struct G
233+
// CHECK-NEXT: 0:0-44 | long long ll
234+
// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=8, preferredalign=8
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \
2+
// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | \
3+
// RUN: FileCheck --check-prefixes=CHECK %s
4+
5+
// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
6+
// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | \
7+
// RUN: FileCheck --check-prefixes=CHECK %s
8+
9+
struct A {
10+
bool b : 3;
11+
};
12+
13+
int a = sizeof(A);
14+
15+
// CHECK: *** Dumping AST Record Layout
16+
// CHECK-NEXT: 0 | struct A
17+
// CHECK-NEXT: 0:0-2 | _Bool b
18+
// CHECK-NEXT: | [sizeof=4, dsize=4, align=4, preferredalign=4,
19+
// CHECK-NEXT: | nvsize=4, nvalign=4, preferrednvalign=4]
20+
21+
enum class Bool : bool { False = 0,
22+
True = 1 };
23+
24+
struct B {
25+
Bool b : 1;
26+
};
27+
28+
int b = sizeof(B);
29+
30+
// CHECK: *** Dumping AST Record Layout
31+
// CHECK-NEXT: 0 | struct B
32+
// CHECK-NEXT: 0:0-0 | enum Bool b
33+
// CHECK-NEXT: | [sizeof=4, dsize=4, align=4, preferredalign=4,
34+
// CHECK-NEXT: | nvsize=4, nvalign=4, preferrednvalign=4]
35+
36+
enum LL : unsigned long long { val = 1 };

0 commit comments

Comments
 (0)