1*67e74705SXin Li // RUN: %clang_cc1 -emit-llvm -triple x86_64 -O3 -o %t.opt.ll %s \
2*67e74705SXin Li // RUN: -fdump-record-layouts > %t.dump.txt
3*67e74705SXin Li // RUN: FileCheck -check-prefix=CHECK-RECORD < %t.dump.txt %s
4*67e74705SXin Li // RUN: FileCheck -check-prefix=CHECK-OPT < %t.opt.ll %s
5*67e74705SXin Li
6*67e74705SXin Li /****/
7*67e74705SXin Li
8*67e74705SXin Li // Check that we don't read off the end a packed 24-bit structure.
9*67e74705SXin Li // PR6176
10*67e74705SXin Li
11*67e74705SXin Li // CHECK-RECORD: *** Dumping IRgen Record Layout
12*67e74705SXin Li // CHECK-RECORD: Record: RecordDecl{{.*}}s0
13*67e74705SXin Li // CHECK-RECORD: Layout: <CGRecordLayout
14*67e74705SXin Li // CHECK-RECORD: LLVMType:%struct.s0 = type { [3 x i8] }
15*67e74705SXin Li // CHECK-RECORD: IsZeroInitializable:1
16*67e74705SXin Li // CHECK-RECORD: BitFields:[
17*67e74705SXin Li // CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:24 IsSigned:1 StorageSize:24 StorageOffset:0>
18*67e74705SXin Li struct __attribute((packed)) s0 {
19*67e74705SXin Li int f0 : 24;
20*67e74705SXin Li };
21*67e74705SXin Li
22*67e74705SXin Li struct s0 g0 = { 0xdeadbeef };
23*67e74705SXin Li
f0_load(struct s0 * a0)24*67e74705SXin Li int f0_load(struct s0 *a0) {
25*67e74705SXin Li int size_check[sizeof(struct s0) == 3 ? 1 : -1];
26*67e74705SXin Li return a0->f0;
27*67e74705SXin Li }
f0_store(struct s0 * a0)28*67e74705SXin Li int f0_store(struct s0 *a0) {
29*67e74705SXin Li return (a0->f0 = 1);
30*67e74705SXin Li }
f0_reload(struct s0 * a0)31*67e74705SXin Li int f0_reload(struct s0 *a0) {
32*67e74705SXin Li return (a0->f0 += 1);
33*67e74705SXin Li }
34*67e74705SXin Li
35*67e74705SXin Li // CHECK-OPT-LABEL: define i64 @test_0()
36*67e74705SXin Li // CHECK-OPT: ret i64 1
37*67e74705SXin Li // CHECK-OPT: }
test_0()38*67e74705SXin Li unsigned long long test_0() {
39*67e74705SXin Li struct s0 g0 = { 0xdeadbeef };
40*67e74705SXin Li unsigned long long res = 0;
41*67e74705SXin Li res ^= g0.f0;
42*67e74705SXin Li res ^= f0_load(&g0) ^ f0_store(&g0) ^ f0_reload(&g0);
43*67e74705SXin Li res ^= g0.f0;
44*67e74705SXin Li return res;
45*67e74705SXin Li }
46*67e74705SXin Li
47*67e74705SXin Li /****/
48*67e74705SXin Li
49*67e74705SXin Li // PR5591
50*67e74705SXin Li
51*67e74705SXin Li // CHECK-RECORD: *** Dumping IRgen Record Layout
52*67e74705SXin Li // CHECK-RECORD: Record: RecordDecl{{.*}}s1
53*67e74705SXin Li // CHECK-RECORD: Layout: <CGRecordLayout
54*67e74705SXin Li // CHECK-RECORD: LLVMType:%struct.s1 = type { [3 x i8] }
55*67e74705SXin Li // CHECK-RECORD: IsZeroInitializable:1
56*67e74705SXin Li // CHECK-RECORD: BitFields:[
57*67e74705SXin Li // CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:10 IsSigned:1 StorageSize:24 StorageOffset:0>
58*67e74705SXin Li // CHECK-RECORD: <CGBitFieldInfo Offset:10 Size:10 IsSigned:1 StorageSize:24 StorageOffset:0>
59*67e74705SXin Li
60*67e74705SXin Li #pragma pack(push)
61*67e74705SXin Li #pragma pack(1)
62*67e74705SXin Li struct __attribute((packed)) s1 {
63*67e74705SXin Li signed f0 : 10;
64*67e74705SXin Li signed f1 : 10;
65*67e74705SXin Li };
66*67e74705SXin Li #pragma pack(pop)
67*67e74705SXin Li
68*67e74705SXin Li struct s1 g1 = { 0xdeadbeef, 0xdeadbeef };
69*67e74705SXin Li
f1_load(struct s1 * a0)70*67e74705SXin Li int f1_load(struct s1 *a0) {
71*67e74705SXin Li int size_check[sizeof(struct s1) == 3 ? 1 : -1];
72*67e74705SXin Li return a0->f1;
73*67e74705SXin Li }
f1_store(struct s1 * a0)74*67e74705SXin Li int f1_store(struct s1 *a0) {
75*67e74705SXin Li return (a0->f1 = 1234);
76*67e74705SXin Li }
f1_reload(struct s1 * a0)77*67e74705SXin Li int f1_reload(struct s1 *a0) {
78*67e74705SXin Li return (a0->f1 += 1234);
79*67e74705SXin Li }
80*67e74705SXin Li
81*67e74705SXin Li // CHECK-OPT-LABEL: define i64 @test_1()
82*67e74705SXin Li // CHECK-OPT: ret i64 210
83*67e74705SXin Li // CHECK-OPT: }
test_1()84*67e74705SXin Li unsigned long long test_1() {
85*67e74705SXin Li struct s1 g1 = { 0xdeadbeef, 0xdeadbeef };
86*67e74705SXin Li unsigned long long res = 0;
87*67e74705SXin Li res ^= g1.f0 ^ g1.f1;
88*67e74705SXin Li res ^= f1_load(&g1) ^ f1_store(&g1) ^ f1_reload(&g1);
89*67e74705SXin Li res ^= g1.f0 ^ g1.f1;
90*67e74705SXin Li return res;
91*67e74705SXin Li }
92*67e74705SXin Li
93*67e74705SXin Li /****/
94*67e74705SXin Li
95*67e74705SXin Li // Check that we don't access beyond the bounds of a union.
96*67e74705SXin Li //
97*67e74705SXin Li // PR5567
98*67e74705SXin Li
99*67e74705SXin Li // CHECK-RECORD: *** Dumping IRgen Record Layout
100*67e74705SXin Li // CHECK-RECORD: Record: RecordDecl{{.*}}u2
101*67e74705SXin Li // CHECK-RECORD: Layout: <CGRecordLayout
102*67e74705SXin Li // CHECK-RECORD: LLVMType:%union.u2 = type { i8 }
103*67e74705SXin Li // CHECK-RECORD: IsZeroInitializable:1
104*67e74705SXin Li // CHECK-RECORD: BitFields:[
105*67e74705SXin Li // CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:3 IsSigned:0 StorageSize:8 StorageOffset:0>
106*67e74705SXin Li
107*67e74705SXin Li union __attribute__((packed)) u2 {
108*67e74705SXin Li unsigned long long f0 : 3;
109*67e74705SXin Li };
110*67e74705SXin Li
111*67e74705SXin Li union u2 g2 = { 0xdeadbeef };
112*67e74705SXin Li
f2_load(union u2 * a0)113*67e74705SXin Li int f2_load(union u2 *a0) {
114*67e74705SXin Li return a0->f0;
115*67e74705SXin Li }
f2_store(union u2 * a0)116*67e74705SXin Li int f2_store(union u2 *a0) {
117*67e74705SXin Li return (a0->f0 = 1234);
118*67e74705SXin Li }
f2_reload(union u2 * a0)119*67e74705SXin Li int f2_reload(union u2 *a0) {
120*67e74705SXin Li return (a0->f0 += 1234);
121*67e74705SXin Li }
122*67e74705SXin Li
123*67e74705SXin Li // CHECK-OPT-LABEL: define i64 @test_2()
124*67e74705SXin Li // CHECK-OPT: ret i64 2
125*67e74705SXin Li // CHECK-OPT: }
test_2()126*67e74705SXin Li unsigned long long test_2() {
127*67e74705SXin Li union u2 g2 = { 0xdeadbeef };
128*67e74705SXin Li unsigned long long res = 0;
129*67e74705SXin Li res ^= g2.f0;
130*67e74705SXin Li res ^= f2_load(&g2) ^ f2_store(&g2) ^ f2_reload(&g2);
131*67e74705SXin Li res ^= g2.f0;
132*67e74705SXin Li return res;
133*67e74705SXin Li }
134*67e74705SXin Li
135*67e74705SXin Li /***/
136*67e74705SXin Li
137*67e74705SXin Li // PR5039
138*67e74705SXin Li
139*67e74705SXin Li struct s3 {
140*67e74705SXin Li long long f0 : 32;
141*67e74705SXin Li long long f1 : 32;
142*67e74705SXin Li };
143*67e74705SXin Li
144*67e74705SXin Li struct s3 g3 = { 0xdeadbeef, 0xdeadbeef };
145*67e74705SXin Li
f3_load(struct s3 * a0)146*67e74705SXin Li int f3_load(struct s3 *a0) {
147*67e74705SXin Li a0->f0 = 1;
148*67e74705SXin Li return a0->f0;
149*67e74705SXin Li }
f3_store(struct s3 * a0)150*67e74705SXin Li int f3_store(struct s3 *a0) {
151*67e74705SXin Li a0->f0 = 1;
152*67e74705SXin Li return (a0->f0 = 1234);
153*67e74705SXin Li }
f3_reload(struct s3 * a0)154*67e74705SXin Li int f3_reload(struct s3 *a0) {
155*67e74705SXin Li a0->f0 = 1;
156*67e74705SXin Li return (a0->f0 += 1234);
157*67e74705SXin Li }
158*67e74705SXin Li
159*67e74705SXin Li // CHECK-OPT-LABEL: define i64 @test_3()
160*67e74705SXin Li // CHECK-OPT: ret i64 -559039940
161*67e74705SXin Li // CHECK-OPT: }
test_3()162*67e74705SXin Li unsigned long long test_3() {
163*67e74705SXin Li struct s3 g3 = { 0xdeadbeef, 0xdeadbeef };
164*67e74705SXin Li unsigned long long res = 0;
165*67e74705SXin Li res ^= g3.f0 ^ g3.f1;
166*67e74705SXin Li res ^= f3_load(&g3) ^ f3_store(&g3) ^ f3_reload(&g3);
167*67e74705SXin Li res ^= g3.f0 ^ g3.f1;
168*67e74705SXin Li return res;
169*67e74705SXin Li }
170*67e74705SXin Li
171*67e74705SXin Li /***/
172*67e74705SXin Li
173*67e74705SXin Li // This is a case where the bitfield access will straddle an alignment boundary
174*67e74705SXin Li // of its underlying type.
175*67e74705SXin Li
176*67e74705SXin Li struct s4 {
177*67e74705SXin Li unsigned f0 : 16;
178*67e74705SXin Li unsigned f1 : 28 __attribute__ ((packed));
179*67e74705SXin Li };
180*67e74705SXin Li
181*67e74705SXin Li struct s4 g4 = { 0xdeadbeef, 0xdeadbeef };
182*67e74705SXin Li
f4_load(struct s4 * a0)183*67e74705SXin Li int f4_load(struct s4 *a0) {
184*67e74705SXin Li return a0->f0 ^ a0->f1;
185*67e74705SXin Li }
f4_store(struct s4 * a0)186*67e74705SXin Li int f4_store(struct s4 *a0) {
187*67e74705SXin Li return (a0->f0 = 1234) ^ (a0->f1 = 5678);
188*67e74705SXin Li }
f4_reload(struct s4 * a0)189*67e74705SXin Li int f4_reload(struct s4 *a0) {
190*67e74705SXin Li return (a0->f0 += 1234) ^ (a0->f1 += 5678);
191*67e74705SXin Li }
192*67e74705SXin Li
193*67e74705SXin Li // CHECK-OPT-LABEL: define i64 @test_4()
194*67e74705SXin Li // CHECK-OPT: ret i64 4860
195*67e74705SXin Li // CHECK-OPT: }
test_4()196*67e74705SXin Li unsigned long long test_4() {
197*67e74705SXin Li struct s4 g4 = { 0xdeadbeef, 0xdeadbeef };
198*67e74705SXin Li unsigned long long res = 0;
199*67e74705SXin Li res ^= g4.f0 ^ g4.f1;
200*67e74705SXin Li res ^= f4_load(&g4) ^ f4_store(&g4) ^ f4_reload(&g4);
201*67e74705SXin Li res ^= g4.f0 ^ g4.f1;
202*67e74705SXin Li return res;
203*67e74705SXin Li }
204*67e74705SXin Li
205*67e74705SXin Li /***/
206*67e74705SXin Li
207*67e74705SXin Li struct s5 {
208*67e74705SXin Li unsigned f0 : 2;
209*67e74705SXin Li _Bool f1 : 1;
210*67e74705SXin Li _Bool f2 : 1;
211*67e74705SXin Li };
212*67e74705SXin Li
213*67e74705SXin Li struct s5 g5 = { 0xdeadbeef, 0xdeadbeef };
214*67e74705SXin Li
f5_load(struct s5 * a0)215*67e74705SXin Li int f5_load(struct s5 *a0) {
216*67e74705SXin Li return a0->f0 ^ a0->f1;
217*67e74705SXin Li }
f5_store(struct s5 * a0)218*67e74705SXin Li int f5_store(struct s5 *a0) {
219*67e74705SXin Li return (a0->f0 = 0xF) ^ (a0->f1 = 0xF) ^ (a0->f2 = 0xF);
220*67e74705SXin Li }
f5_reload(struct s5 * a0)221*67e74705SXin Li int f5_reload(struct s5 *a0) {
222*67e74705SXin Li return (a0->f0 += 0xF) ^ (a0->f1 += 0xF) ^ (a0->f2 += 0xF);
223*67e74705SXin Li }
224*67e74705SXin Li
225*67e74705SXin Li // CHECK-OPT-LABEL: define i64 @test_5()
226*67e74705SXin Li // CHECK-OPT: ret i64 2
227*67e74705SXin Li // CHECK-OPT: }
test_5()228*67e74705SXin Li unsigned long long test_5() {
229*67e74705SXin Li struct s5 g5 = { 0xdeadbeef, 0xdeadbeef, 0xdeadbeef };
230*67e74705SXin Li unsigned long long res = 0;
231*67e74705SXin Li res ^= g5.f0 ^ g5.f1 ^ g5.f2;
232*67e74705SXin Li res ^= f5_load(&g5) ^ f5_store(&g5) ^ f5_reload(&g5);
233*67e74705SXin Li res ^= g5.f0 ^ g5.f1 ^ g5.f2;
234*67e74705SXin Li return res;
235*67e74705SXin Li }
236*67e74705SXin Li
237*67e74705SXin Li /***/
238*67e74705SXin Li
239*67e74705SXin Li struct s6 {
240*67e74705SXin Li unsigned f0 : 2;
241*67e74705SXin Li };
242*67e74705SXin Li
243*67e74705SXin Li struct s6 g6 = { 0xF };
244*67e74705SXin Li
f6_load(struct s6 * a0)245*67e74705SXin Li int f6_load(struct s6 *a0) {
246*67e74705SXin Li return a0->f0;
247*67e74705SXin Li }
f6_store(struct s6 * a0)248*67e74705SXin Li int f6_store(struct s6 *a0) {
249*67e74705SXin Li return a0->f0 = 0x0;
250*67e74705SXin Li }
f6_reload(struct s6 * a0)251*67e74705SXin Li int f6_reload(struct s6 *a0) {
252*67e74705SXin Li return (a0->f0 += 0xF);
253*67e74705SXin Li }
254*67e74705SXin Li
255*67e74705SXin Li // CHECK-OPT-LABEL: define zeroext i1 @test_6()
256*67e74705SXin Li // CHECK-OPT: ret i1 true
257*67e74705SXin Li // CHECK-OPT: }
test_6()258*67e74705SXin Li _Bool test_6() {
259*67e74705SXin Li struct s6 g6 = { 0xF };
260*67e74705SXin Li unsigned long long res = 0;
261*67e74705SXin Li res ^= g6.f0;
262*67e74705SXin Li res ^= f6_load(&g6);
263*67e74705SXin Li res ^= g6.f0;
264*67e74705SXin Li return res;
265*67e74705SXin Li }
266*67e74705SXin Li
267*67e74705SXin Li /***/
268*67e74705SXin Li
269*67e74705SXin Li // Check that we compute the best alignment possible for each access.
270*67e74705SXin Li //
271*67e74705SXin Li // CHECK-RECORD: *** Dumping IRgen Record Layout
272*67e74705SXin Li // CHECK-RECORD: Record: RecordDecl{{.*}}s7
273*67e74705SXin Li // CHECK-RECORD: Layout: <CGRecordLayout
274*67e74705SXin Li // CHECK-RECORD: LLVMType:%struct.s7 = type { i32, i32, i32, i8, i32, [12 x i8] }
275*67e74705SXin Li // CHECK-RECORD: IsZeroInitializable:1
276*67e74705SXin Li // CHECK-RECORD: BitFields:[
277*67e74705SXin Li // CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:5 IsSigned:1 StorageSize:8 StorageOffset:12>
278*67e74705SXin Li // CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:29 IsSigned:1 StorageSize:32 StorageOffset:16>
279*67e74705SXin Li
280*67e74705SXin Li struct __attribute__((aligned(16))) s7 {
281*67e74705SXin Li int a, b, c;
282*67e74705SXin Li int f0 : 5;
283*67e74705SXin Li int f1 : 29;
284*67e74705SXin Li };
285*67e74705SXin Li
f7_load(struct s7 * a0)286*67e74705SXin Li int f7_load(struct s7 *a0) {
287*67e74705SXin Li return a0->f0;
288*67e74705SXin Li }
289*67e74705SXin Li
290*67e74705SXin Li /***/
291*67e74705SXin Li
292*67e74705SXin Li // This is a case where we narrow the access width immediately.
293*67e74705SXin Li
294*67e74705SXin Li struct __attribute__((packed)) s8 {
295*67e74705SXin Li char f0 : 4;
296*67e74705SXin Li char f1;
297*67e74705SXin Li int f2 : 4;
298*67e74705SXin Li char f3 : 4;
299*67e74705SXin Li };
300*67e74705SXin Li
301*67e74705SXin Li struct s8 g8 = { 0xF };
302*67e74705SXin Li
f8_load(struct s8 * a0)303*67e74705SXin Li int f8_load(struct s8 *a0) {
304*67e74705SXin Li return a0->f0 ^ a0 ->f2 ^ a0->f3;
305*67e74705SXin Li }
f8_store(struct s8 * a0)306*67e74705SXin Li int f8_store(struct s8 *a0) {
307*67e74705SXin Li return (a0->f0 = 0xFD) ^ (a0->f2 = 0xFD) ^ (a0->f3 = 0xFD);
308*67e74705SXin Li }
f8_reload(struct s8 * a0)309*67e74705SXin Li int f8_reload(struct s8 *a0) {
310*67e74705SXin Li return (a0->f0 += 0xFD) ^ (a0->f2 += 0xFD) ^ (a0->f3 += 0xFD);
311*67e74705SXin Li }
312*67e74705SXin Li
313*67e74705SXin Li // CHECK-OPT-LABEL: define i32 @test_8()
314*67e74705SXin Li // CHECK-OPT: ret i32 -3
315*67e74705SXin Li // CHECK-OPT: }
test_8()316*67e74705SXin Li unsigned test_8() {
317*67e74705SXin Li struct s8 g8 = { 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef };
318*67e74705SXin Li unsigned long long res = 0;
319*67e74705SXin Li res ^= g8.f0 ^ g8.f2 ^ g8.f3;
320*67e74705SXin Li res ^= f8_load(&g8) ^ f8_store(&g8) ^ f8_reload(&g8);
321*67e74705SXin Li res ^= g8.f0 ^ g8.f2 ^ g8.f3;
322*67e74705SXin Li return res;
323*67e74705SXin Li }
324*67e74705SXin Li
325*67e74705SXin Li /***/
326*67e74705SXin Li
327*67e74705SXin Li // This is another case where we narrow the access width immediately.
328*67e74705SXin Li //
329*67e74705SXin Li // <rdar://problem/7893760>
330*67e74705SXin Li
331*67e74705SXin Li struct __attribute__((packed)) s9 {
332*67e74705SXin Li unsigned f0 : 7;
333*67e74705SXin Li unsigned f1 : 7;
334*67e74705SXin Li unsigned f2 : 7;
335*67e74705SXin Li unsigned f3 : 7;
336*67e74705SXin Li unsigned f4 : 7;
337*67e74705SXin Li unsigned f5 : 7;
338*67e74705SXin Li unsigned f6 : 7;
339*67e74705SXin Li unsigned f7 : 7;
340*67e74705SXin Li };
341*67e74705SXin Li
f9_load(struct s9 * a0)342*67e74705SXin Li int f9_load(struct s9 *a0) {
343*67e74705SXin Li return a0->f7;
344*67e74705SXin Li }
345