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