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