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, ptr getelementptr inbounds nuw (%struct.S1, ptr @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, ptr {{.*}}, 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, ptr getelementptr inbounds nuw (%struct.S1, ptr @a1, i32 0, i32 1), align 1 31 // CHECK-NEXT: ret void 32 // SANITIZE-LABEL: @_Z8write8_1v 33 // SANITIZE: %bf.load = load i32, ptr {{.*}}, 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, ptr {{.*}}, 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, ptr getelementptr inbounds nuw (%struct.S1, ptr @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, ptr {{.*}}, 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, ptr getelementptr inbounds nuw (%struct.S1, ptr @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, ptr getelementptr inbounds nuw (%struct.S1, ptr @a1, i32 0, i32 2), align 2 61 // CHECK-NEXT: ret void 62 // SANITIZE-LABEL: @_Z8write8_2v 63 // SANITIZE: %bf.load = load i32, ptr {{.*}}, 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, ptr {{.*}}, 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, ptr @a2, 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, ptr {{.*}}, 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, ptr getelementptr inbounds nuw (%struct.S2, ptr @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, ptr {{.*}}, 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, ptr @a2, align 8 109 // CHECK-NEXT: ret void 110 // SANITIZE-LABEL: @_Z9write16_1v 111 // SANITIZE: %bf.load = load i64, ptr {{.*}}, 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, ptr {{.*}}, 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, ptr getelementptr inbounds nuw (%struct.S2, ptr @a2, i32 0, i32 1), align 2 121 // CHECK-NEXT: ret void 122 // SANITIZE-LABEL: @_Z9write16_2v 123 // SANITIZE: %bf.load = load i64, ptr {{.*}}, 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, ptr {{.*}}, 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, ptr getelementptr inbounds nuw (%struct.S3, ptr @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, ptr {{.*}}, 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, ptr getelementptr inbounds nuw (%struct.S3, ptr @a3, i32 0, i32 1), align 4 154 // CHECK-NEXT: ret void 155 // SANITIZE-LABEL: @_Z9write32_1v 156 // SANITIZE: %bf.load = load i64, ptr {{.*}}, 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, ptr {{.*}}, align 8 160 // SANITIZE-NEXT: ret void 161 a3.f3 = 5; 162 } 163