Clang Project

clang_source_code/test/CodeGenCXX/finegrain-bitfield-access.cpp
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
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_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}
28void 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
41unsigned 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}
55void 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
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_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}
91unsigned 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
106void 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}
118void 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
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_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}
151void 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}
163