Home | History | Annotate | Download | only in CodeGen
      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>
     23 struct __attribute((packed)) s0 {
     24   int f0 : 24;
     25 };
     26 
     27 struct s0 g0 = { 0xdeadbeef };
     28 
     29 int f0_load(struct s0 *a0) {
     30   int size_check[sizeof(struct s0) == 3 ? 1 : -1];
     31   return a0->f0;
     32 }
     33 int f0_store(struct s0 *a0) {
     34   return (a0->f0 = 1);
     35 }
     36 int 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: }
     43 unsigned 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)
     76 struct __attribute((packed)) s1 {
     77   signed f0 : 10;
     78   signed f1 : 10;
     79 };
     80 #pragma pack(pop)
     81 
     82 struct s1 g1 = { 0xdeadbeef, 0xdeadbeef };
     83 
     84 int f1_load(struct s1 *a0) {
     85   int size_check[sizeof(struct s1) == 3 ? 1 : -1];
     86   return a0->f1;
     87 }
     88 int f1_store(struct s1 *a0) {
     89   return (a0->f1 = 1234);
     90 }
     91 int 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: }
     98 unsigned 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 
    124 union __attribute__((packed)) u2 {
    125   unsigned long long f0 : 3;
    126 };
    127 
    128 union u2 g2 = { 0xdeadbeef };
    129 
    130 int f2_load(union u2 *a0) {
    131   return a0->f0;
    132 }
    133 int f2_store(union u2 *a0) {
    134   return (a0->f0 = 1234);
    135 }
    136 int 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: }
    143 unsigned 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 
    156 struct s3 {
    157   long long f0 : 32;
    158   long long f1 : 32;
    159 };
    160 
    161 struct s3 g3 = { 0xdeadbeef, 0xdeadbeef };
    162 
    163 int f3_load(struct s3 *a0) {
    164   a0->f0 = 1;
    165   return a0->f0;
    166 }
    167 int f3_store(struct s3 *a0) {
    168   a0->f0 = 1;
    169   return (a0->f0 = 1234);
    170 }
    171 int 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: }
    179 unsigned 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 
    193 struct s4 {
    194   unsigned f0 : 16;
    195   unsigned f1 : 28 __attribute__ ((packed));
    196 };
    197 
    198 struct s4 g4 = { 0xdeadbeef, 0xdeadbeef };
    199 
    200 int f4_load(struct s4 *a0) {
    201   return a0->f0 ^ a0->f1;
    202 }
    203 int f4_store(struct s4 *a0) {
    204   return (a0->f0 = 1234) ^ (a0->f1 = 5678);
    205 }
    206 int 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: }
    213 unsigned 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 
    224 struct s5 {
    225   unsigned f0 : 2;
    226   _Bool f1 : 1;
    227   _Bool f2 : 1;
    228 };
    229 
    230 struct s5 g5 = { 0xdeadbeef, 0xdeadbeef };
    231 
    232 int f5_load(struct s5 *a0) {
    233   return a0->f0 ^ a0->f1;
    234 }
    235 int f5_store(struct s5 *a0) {
    236   return (a0->f0 = 0xF) ^ (a0->f1 = 0xF) ^ (a0->f2 = 0xF);
    237 }
    238 int 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: }
    245 unsigned 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 
    256 struct s6 {
    257   _Bool f0 : 2;
    258 };
    259 
    260 struct s6 g6 = { 0xF };
    261 
    262 int f6_load(struct s6 *a0) {
    263   return a0->f0;
    264 }
    265 int f6_store(struct s6 *a0) {
    266   return a0->f0 = 0x0;
    267 }
    268 int 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 
    304 struct __attribute__((aligned(16))) s7 {
    305   int a, b, c;
    306   int f0 : 5;
    307   int f1 : 29;
    308 };
    309 
    310 int 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 
    318 struct __attribute__((packed)) s8 {
    319   char f0 : 4;
    320   char f1;
    321   int  f2 : 4;
    322   char f3 : 4;
    323 };
    324 
    325 struct s8 g8 = { 0xF };
    326 
    327 int f8_load(struct s8 *a0) {
    328   return a0->f0 ^ a0 ->f2 ^ a0->f3;
    329 }
    330 int f8_store(struct s8 *a0) {
    331   return (a0->f0 = 0xFD) ^ (a0->f2 = 0xFD) ^ (a0->f3 = 0xFD);
    332 }
    333 int 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: }
    340 unsigned 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 
    355 struct __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 
    366 int f9_load(struct s9 *a0) {
    367   return a0->f7;
    368 }
    369