Wei Mi | 9b3d627 | 2017-10-16 16:50:27 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -triple x86_64-linux-gnu -ffine-grained-bitfield-accesses \ |
| 2 | // RUN: -emit-llvm -o - %s | FileCheck %s |
| 3 | // RUN: %clang_cc1 -triple x86_64-linux-gnu -ffine-grained-bitfield-accesses \ |
| 4 | // RUN: -emit-llvm -fsanitize=address -o - %s | FileCheck %s --check-prefix=SANITIZE |
| 5 | // Check -fsplit-bitfields will be ignored since sanitizer is enabled. |
| 6 | |
| 7 | struct S1 { |
| 8 | unsigned f1:2; |
| 9 | unsigned f2:6; |
| 10 | unsigned f3:8; |
| 11 | unsigned f4:4; |
| 12 | unsigned f5:8; |
| 13 | }; |
| 14 | |
| 15 | S1 a1; |
| 16 | unsigned read8_1() { |
| 17 | // CHECK-LABEL: @_Z7read8_1v |
| 18 | // CHECK: %bf.load = load i8, i8* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 1), align 1 |
| 19 | // CHECK-NEXT: %bf.cast = zext i8 %bf.load to i32 |
| 20 | // CHECK-NEXT: ret i32 %bf.cast |
| 21 | // SANITIZE-LABEL: @_Z7read8_1v |
| 22 | // SANITIZE: %bf.load = load i32, i32* getelementptr inbounds {{.*}}, align 4 |
| 23 | // SANITIZE: %bf.lshr = lshr i32 %bf.load, 8 |
| 24 | // SANITIZE: %bf.clear = and i32 %bf.lshr, 255 |
| 25 | // SANITIZE: ret i32 %bf.clear |
| 26 | return a1.f3; |
| 27 | } |
| 28 | void write8_1() { |
| 29 | // CHECK-LABEL: @_Z8write8_1v |
| 30 | // CHECK: store i8 3, i8* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 1), align 1 |
| 31 | // CHECK-NEXT: ret void |
| 32 | // SANITIZE-LABEL: @_Z8write8_1v |
| 33 | // SANITIZE: %bf.load = load i32, i32* getelementptr inbounds {{.*}}, align 4 |
| 34 | // SANITIZE-NEXT: %bf.clear = and i32 %bf.load, -65281 |
| 35 | // SANITIZE-NEXT: %bf.set = or i32 %bf.clear, 768 |
| 36 | // SANITIZE-NEXT: store i32 %bf.set, i32* getelementptr inbounds {{.*}}, align 4 |
| 37 | // SANITIZE-NEXT: ret void |
| 38 | a1.f3 = 3; |
| 39 | } |
| 40 | |
| 41 | unsigned read8_2() { |
| 42 | // CHECK-LABEL: @_Z7read8_2v |
| 43 | // CHECK: %bf.load = load i16, i16* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 2), align 2 |
| 44 | // CHECK-NEXT: %bf.lshr = lshr i16 %bf.load, 4 |
| 45 | // CHECK-NEXT: %bf.clear = and i16 %bf.lshr, 255 |
| 46 | // CHECK-NEXT: %bf.cast = zext i16 %bf.clear to i32 |
| 47 | // CHECK-NEXT: ret i32 %bf.cast |
| 48 | // SANITIZE-LABEL: @_Z7read8_2v |
| 49 | // SANITIZE: %bf.load = load i32, i32* getelementptr inbounds {{.*}}, align 4 |
| 50 | // SANITIZE-NEXT: %bf.lshr = lshr i32 %bf.load, 20 |
| 51 | // SANITIZE-NEXT: %bf.clear = and i32 %bf.lshr, 255 |
| 52 | // SANITIZE-NEXT: ret i32 %bf.clear |
| 53 | return a1.f5; |
| 54 | } |
| 55 | void write8_2() { |
| 56 | // CHECK-LABEL: @_Z8write8_2v |
| 57 | // CHECK: %bf.load = load i16, i16* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 2), align 2 |
| 58 | // CHECK-NEXT: %bf.clear = and i16 %bf.load, -4081 |
| 59 | // CHECK-NEXT: %bf.set = or i16 %bf.clear, 48 |
| 60 | // CHECK-NEXT: store i16 %bf.set, i16* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 2), align 2 |
| 61 | // CHECK-NEXT: ret void |
| 62 | // SANITIZE-LABEL: @_Z8write8_2v |
| 63 | // SANITIZE: %bf.load = load i32, i32* getelementptr inbounds {{.*}}, align 4 |
| 64 | // SANITIZE-NEXT: %bf.clear = and i32 %bf.load, -267386881 |
| 65 | // SANITIZE-NEXT: %bf.set = or i32 %bf.clear, 3145728 |
| 66 | // SANITIZE-NEXT: store i32 %bf.set, i32* getelementptr inbounds {{.*}}, align 4 |
| 67 | // SANITIZE-NEXT: ret void |
| 68 | a1.f5 = 3; |
| 69 | } |
| 70 | |
| 71 | struct S2 { |
| 72 | unsigned long f1:16; |
| 73 | unsigned long f2:16; |
| 74 | unsigned long f3:6; |
| 75 | }; |
| 76 | |
| 77 | S2 a2; |
| 78 | unsigned read16_1() { |
| 79 | // CHECK-LABEL: @_Z8read16_1v |
| 80 | // CHECK: %bf.load = load i16, i16* getelementptr inbounds (%struct.S2, %struct.S2* @a2, i32 0, i32 0), align 8 |
| 81 | // CHECK-NEXT: %bf.cast = zext i16 %bf.load to i64 |
| 82 | // CHECK-NEXT: %conv = trunc i64 %bf.cast to i32 |
| 83 | // CHECK-NEXT: ret i32 %conv |
| 84 | // SANITIZE-LABEL: @_Z8read16_1v |
| 85 | // SANITIZE: %bf.load = load i64, i64* bitcast {{.*}}, align 8 |
| 86 | // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, 65535 |
| 87 | // SANITIZE-NEXT: %conv = trunc i64 %bf.clear to i32 |
| 88 | // SANITIZE-NEXT: ret i32 %conv |
| 89 | return a2.f1; |
| 90 | } |
| 91 | unsigned read16_2() { |
| 92 | // CHECK-LABEL: @_Z8read16_2v |
| 93 | // CHECK: %bf.load = load i16, i16* getelementptr inbounds (%struct.S2, %struct.S2* @a2, i32 0, i32 1), align 2 |
| 94 | // CHECK-NEXT: %bf.cast = zext i16 %bf.load to i64 |
| 95 | // CHECK-NEXT: %conv = trunc i64 %bf.cast to i32 |
| 96 | // CHECK-NEXT: ret i32 %conv |
| 97 | // SANITIZE-LABEL: @_Z8read16_2v |
| 98 | // SANITIZE: %bf.load = load i64, i64* bitcast {{.*}}, align 8 |
| 99 | // SANITIZE-NEXT: %bf.lshr = lshr i64 %bf.load, 16 |
| 100 | // SANITIZE-NEXT: %bf.clear = and i64 %bf.lshr, 65535 |
| 101 | // SANITIZE-NEXT: %conv = trunc i64 %bf.clear to i32 |
| 102 | // SANITIZE-NEXT: ret i32 %conv |
| 103 | return a2.f2; |
| 104 | } |
| 105 | |
| 106 | void write16_1() { |
| 107 | // CHECK-LABEL: @_Z9write16_1v |
| 108 | // CHECK: store i16 5, i16* getelementptr inbounds (%struct.S2, %struct.S2* @a2, i32 0, i32 0), align 8 |
| 109 | // CHECK-NEXT: ret void |
| 110 | // SANITIZE-LABEL: @_Z9write16_1v |
| 111 | // SANITIZE: %bf.load = load i64, i64* bitcast {{.*}}, align 8 |
| 112 | // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, -65536 |
| 113 | // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 5 |
| 114 | // SANITIZE-NEXT: store i64 %bf.set, i64* bitcast {{.*}}, align 8 |
| 115 | // SANITIZE-NEXT: ret void |
| 116 | a2.f1 = 5; |
| 117 | } |
| 118 | void write16_2() { |
| 119 | // CHECK-LABEL: @_Z9write16_2v |
| 120 | // CHECK: store i16 5, i16* getelementptr inbounds (%struct.S2, %struct.S2* @a2, i32 0, i32 1), align 2 |
| 121 | // CHECK-NEXT: ret void |
| 122 | // SANITIZE-LABEL: @_Z9write16_2v |
| 123 | // SANITIZE: %bf.load = load i64, i64* bitcast {{.*}}, align 8 |
| 124 | // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, -4294901761 |
| 125 | // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 327680 |
| 126 | // SANITIZE-NEXT: store i64 %bf.set, i64* bitcast {{.*}}, align 8 |
| 127 | // SANITIZE-NEXT: ret void |
| 128 | a2.f2 = 5; |
| 129 | } |
| 130 | |
| 131 | struct S3 { |
| 132 | unsigned long f1:14; |
| 133 | unsigned long f2:18; |
| 134 | unsigned long f3:32; |
| 135 | }; |
| 136 | |
| 137 | S3 a3; |
| 138 | unsigned read32_1() { |
| 139 | // CHECK-LABEL: @_Z8read32_1v |
| 140 | // CHECK: %bf.load = load i32, i32* getelementptr inbounds (%struct.S3, %struct.S3* @a3, i32 0, i32 1), align 4 |
| 141 | // CHECK-NEXT: %bf.cast = zext i32 %bf.load to i64 |
| 142 | // CHECK-NEXT: %conv = trunc i64 %bf.cast to i32 |
| 143 | // CHECK-NEXT: ret i32 %conv |
| 144 | // SANITIZE-LABEL: @_Z8read32_1v |
| 145 | // SANITIZE: %bf.load = load i64, i64* getelementptr inbounds {{.*}}, align 8 |
| 146 | // SANITIZE-NEXT: %bf.lshr = lshr i64 %bf.load, 32 |
| 147 | // SANITIZE-NEXT: %conv = trunc i64 %bf.lshr to i32 |
| 148 | // SANITIZE-NEXT: ret i32 %conv |
| 149 | return a3.f3; |
| 150 | } |
| 151 | void write32_1() { |
| 152 | // CHECK-LABEL: @_Z9write32_1v |
| 153 | // CHECK: store i32 5, i32* getelementptr inbounds (%struct.S3, %struct.S3* @a3, i32 0, i32 1), align 4 |
| 154 | // CHECK-NEXT: ret void |
| 155 | // SANITIZE-LABEL: @_Z9write32_1v |
| 156 | // SANITIZE: %bf.load = load i64, i64* getelementptr inbounds {{.*}}, align 8 |
| 157 | // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, 4294967295 |
| 158 | // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 21474836480 |
| 159 | // SANITIZE-NEXT: store i64 %bf.set, i64* getelementptr inbounds {{.*}}, align 8 |
| 160 | // SANITIZE-NEXT: ret void |
| 161 | a3.f3 = 5; |
| 162 | } |