163 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-linux-gnu -ffine-grained-bitfield-accesses \2// RUN: -emit-llvm -o - %s | FileCheck %s3// RUN: %clang_cc1 -triple x86_64-linux-gnu -ffine-grained-bitfield-accesses \4// RUN: -emit-llvm -fsanitize=address -o - %s | FileCheck %s --check-prefix=SANITIZE5// Check -fsplit-bitfields will be ignored since sanitizer is enabled.6 7struct S1 {8 unsigned f1:2;9 unsigned f2:6;10 unsigned f3:8;11 unsigned f4:4;12 unsigned f5:8;13};14 15S1 a1;16unsigned read8_1() {17 // CHECK-LABEL: @_Z7read8_1v18 // CHECK: %bf.load = load i8, ptr getelementptr inbounds nuw (%struct.S1, ptr @a1, i32 0, i32 1), align 119 // CHECK-NEXT: %bf.cast = zext i8 %bf.load to i3220 // CHECK-NEXT: ret i32 %bf.cast21 // SANITIZE-LABEL: @_Z7read8_1v22 // SANITIZE: %bf.load = load i32, ptr {{.*}}, align 423 // SANITIZE: %bf.lshr = lshr i32 %bf.load, 824 // SANITIZE: %bf.clear = and i32 %bf.lshr, 25525 // SANITIZE: ret i32 %bf.clear26 return a1.f3;27}28void write8_1() {29 // CHECK-LABEL: @_Z8write8_1v30 // CHECK: store i8 3, ptr getelementptr inbounds nuw (%struct.S1, ptr @a1, i32 0, i32 1), align 131 // CHECK-NEXT: ret void32 // SANITIZE-LABEL: @_Z8write8_1v33 // SANITIZE: %bf.load = load i32, ptr {{.*}}, align 434 // SANITIZE-NEXT: %bf.clear = and i32 %bf.load, -6528135 // SANITIZE-NEXT: %bf.set = or i32 %bf.clear, 76836 // SANITIZE-NEXT: store i32 %bf.set, ptr {{.*}}, align 437 // SANITIZE-NEXT: ret void38 a1.f3 = 3;39}40 41unsigned read8_2() {42 // CHECK-LABEL: @_Z7read8_2v43 // CHECK: %bf.load = load i16, ptr getelementptr inbounds nuw (%struct.S1, ptr @a1, i32 0, i32 2), align 244 // CHECK-NEXT: %bf.lshr = lshr i16 %bf.load, 445 // CHECK-NEXT: %bf.clear = and i16 %bf.lshr, 25546 // CHECK-NEXT: %bf.cast = zext i16 %bf.clear to i3247 // CHECK-NEXT: ret i32 %bf.cast48 // SANITIZE-LABEL: @_Z7read8_2v49 // SANITIZE: %bf.load = load i32, ptr {{.*}}, align 450 // SANITIZE-NEXT: %bf.lshr = lshr i32 %bf.load, 2051 // SANITIZE-NEXT: %bf.clear = and i32 %bf.lshr, 25552 // SANITIZE-NEXT: ret i32 %bf.clear53 return a1.f5;54}55void write8_2() {56 // CHECK-LABEL: @_Z8write8_2v57 // CHECK: %bf.load = load i16, ptr getelementptr inbounds nuw (%struct.S1, ptr @a1, i32 0, i32 2), align 258 // CHECK-NEXT: %bf.clear = and i16 %bf.load, -408159 // CHECK-NEXT: %bf.set = or i16 %bf.clear, 4860 // CHECK-NEXT: store i16 %bf.set, ptr getelementptr inbounds nuw (%struct.S1, ptr @a1, i32 0, i32 2), align 261 // CHECK-NEXT: ret void62 // SANITIZE-LABEL: @_Z8write8_2v63 // SANITIZE: %bf.load = load i32, ptr {{.*}}, align 464 // SANITIZE-NEXT: %bf.clear = and i32 %bf.load, -26738688165 // SANITIZE-NEXT: %bf.set = or i32 %bf.clear, 314572866 // SANITIZE-NEXT: store i32 %bf.set, ptr {{.*}}, align 467 // SANITIZE-NEXT: ret void68 a1.f5 = 3;69}70 71struct S2 {72 unsigned long f1:16;73 unsigned long f2:16;74 unsigned long f3:6;75};76 77S2 a2;78unsigned read16_1() {79 // CHECK-LABEL: @_Z8read16_1v80 // CHECK: %bf.load = load i16, ptr @a2, align 881 // CHECK-NEXT: %bf.cast = zext i16 %bf.load to i6482 // CHECK-NEXT: %conv = trunc i64 %bf.cast to i3283 // CHECK-NEXT: ret i32 %conv84 // SANITIZE-LABEL: @_Z8read16_1v85 // SANITIZE: %bf.load = load i64, ptr {{.*}}, align 886 // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, 6553587 // SANITIZE-NEXT: %conv = trunc i64 %bf.clear to i3288 // SANITIZE-NEXT: ret i32 %conv89 return a2.f1;90}91unsigned read16_2() {92 // CHECK-LABEL: @_Z8read16_2v93 // CHECK: %bf.load = load i16, ptr getelementptr inbounds nuw (%struct.S2, ptr @a2, i32 0, i32 1), align 294 // CHECK-NEXT: %bf.cast = zext i16 %bf.load to i6495 // CHECK-NEXT: %conv = trunc i64 %bf.cast to i3296 // CHECK-NEXT: ret i32 %conv97 // SANITIZE-LABEL: @_Z8read16_2v98 // SANITIZE: %bf.load = load i64, ptr {{.*}}, align 899 // SANITIZE-NEXT: %bf.lshr = lshr i64 %bf.load, 16100 // SANITIZE-NEXT: %bf.clear = and i64 %bf.lshr, 65535101 // SANITIZE-NEXT: %conv = trunc i64 %bf.clear to i32102 // SANITIZE-NEXT: ret i32 %conv103 return a2.f2;104}105 106void write16_1() {107 // CHECK-LABEL: @_Z9write16_1v108 // CHECK: store i16 5, ptr @a2, align 8109 // CHECK-NEXT: ret void110 // SANITIZE-LABEL: @_Z9write16_1v111 // SANITIZE: %bf.load = load i64, ptr {{.*}}, align 8112 // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, -65536113 // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 5114 // SANITIZE-NEXT: store i64 %bf.set, ptr {{.*}}, align 8115 // SANITIZE-NEXT: ret void116 a2.f1 = 5;117}118void write16_2() {119 // CHECK-LABEL: @_Z9write16_2v120 // CHECK: store i16 5, ptr getelementptr inbounds nuw (%struct.S2, ptr @a2, i32 0, i32 1), align 2121 // CHECK-NEXT: ret void122 // SANITIZE-LABEL: @_Z9write16_2v123 // SANITIZE: %bf.load = load i64, ptr {{.*}}, align 8124 // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, -4294901761125 // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 327680126 // SANITIZE-NEXT: store i64 %bf.set, ptr {{.*}}, align 8127 // SANITIZE-NEXT: ret void128 a2.f2 = 5;129}130 131struct S3 {132 unsigned long f1:14;133 unsigned long f2:18;134 unsigned long f3:32;135};136 137S3 a3;138unsigned read32_1() {139 // CHECK-LABEL: @_Z8read32_1v140 // CHECK: %bf.load = load i32, ptr getelementptr inbounds nuw (%struct.S3, ptr @a3, i32 0, i32 1), align 4141 // CHECK-NEXT: %bf.cast = zext i32 %bf.load to i64142 // CHECK-NEXT: %conv = trunc i64 %bf.cast to i32143 // CHECK-NEXT: ret i32 %conv144 // SANITIZE-LABEL: @_Z8read32_1v145 // SANITIZE: %bf.load = load i64, ptr {{.*}}, align 8146 // SANITIZE-NEXT: %bf.lshr = lshr i64 %bf.load, 32147 // SANITIZE-NEXT: %conv = trunc i64 %bf.lshr to i32148 // SANITIZE-NEXT: ret i32 %conv149 return a3.f3;150}151void write32_1() {152 // CHECK-LABEL: @_Z9write32_1v153 // CHECK: store i32 5, ptr getelementptr inbounds nuw (%struct.S3, ptr @a3, i32 0, i32 1), align 4154 // CHECK-NEXT: ret void155 // SANITIZE-LABEL: @_Z9write32_1v156 // SANITIZE: %bf.load = load i64, ptr {{.*}}, align 8157 // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, 4294967295158 // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 21474836480159 // SANITIZE-NEXT: store i64 %bf.set, ptr {{.*}}, align 8160 // SANITIZE-NEXT: ret void161 a3.f3 = 5;162}163