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