1use vstd::prelude::*;
3
4macro_rules! define_bit_is_set {
6 ($name:ident, $uN:ty, $one:expr) => {
7 verus! {
8 pub open spec fn $name(w: $uN, b: int) -> bool {
10 (w & ($one << (b as usize))) != 0
11 }
12 }
13 };
14}
15
16define_bit_is_set!(u8_bit_is_set, u8, 1u8);
17define_bit_is_set!(u16_bit_is_set, u16, 1u16);
18define_bit_is_set!(u32_bit_is_set, u32, 1u32);
19define_bit_is_set!(u64_bit_is_set, u64, 1u64);
20define_bit_is_set!(u128_bit_is_set, u128, 1u128);
21define_bit_is_set!(usize_bit_is_set, usize, 1usize);
22
23macro_rules! define_unsigned_bit_lemmas {
25 (
26 $uN:ty, $zero:expr, $one:expr, $width:expr, $width_u32:expr,
27 $bit_is_set:ident,
28 $allones_bit_it_set:ident,
29 $unit_le_shl:ident,
30 $masked_bit_clear:ident,
31 $masked_bit_keep:ident,
32 $setbit_bit_is_set:ident,
33 $setbit_bit_unchanged:ident,
34 $clearbit_not_bit_is_set:ident,
35 $clearbit_bit_unchanged:ident,
36 $and_zero:ident,
37 $group:ident
38 ) => {
39 verus! {
40
41 pub broadcast proof fn $allones_bit_it_set(k: int)
43 requires
44 0 <= k < $width,
45 ensures
46 #![trigger $bit_is_set(!$zero, k)]
47 $bit_is_set(!$zero, k),
48 {
49 let ku: u32 = k as u32;
50 assert((!$zero & ($one << ku)) == ($one << ku)) by (bit_vector);
51 assert((ku < $width_u32) ==> (($one << ku) != $zero)) by (bit_vector);
52 }
53
54 pub broadcast proof fn $unit_le_shl(k: int)
56 requires
57 0 <= k < $width,
58 ensures
59 #![trigger ($one << (k as usize))]
60 $one <= ($one << (k as usize)),
61 {
62 let ku: u32 = k as u32;
63 assert((ku < $width_u32) ==> ($one <= ($one << ku))) by (bit_vector);
64 }
65
66 pub broadcast proof fn $masked_bit_clear(word: $uN, mask: $uN, k: int, b: int)
68 requires
69 0 <= k <= $width,
70 k <= b < $width,
71 mask == ($one << (k as usize)) - $one,
72 ensures
73 #![trigger $bit_is_set(word & mask, b), ($one << (k as usize))]
74 !$bit_is_set(word & mask, b),
75 {
76 let ku: u32 = k as u32;
77 let bu: u32 = b as u32;
78 assert(((word & mask) & ($one << bu)) == $zero) by (bit_vector)
79 requires
80 ku <= bu,
81 bu < $width_u32,
82 mask == ($one << ku) - $one,
83 ;
84 }
85
86 pub broadcast proof fn $masked_bit_keep(word: $uN, mask: $uN, k: int, b: int)
88 requires
89 0 < k <= $width,
90 0 <= b < k,
91 mask == ($one << (k as usize)) - $one,
92 ensures
93 #![trigger $bit_is_set(word & mask, b), ($one << (k as usize))]
94 $bit_is_set(word & mask, b) == $bit_is_set(word, b),
95 {
96 let ku: u32 = k as u32;
97 let bu: u32 = b as u32;
98 assert(((word & mask) & ($one << bu)) == (word & ($one << bu))) by (bit_vector)
99 requires
100 bu < ku,
101 ku <= $width_u32,
102 mask == ($one << ku) - $one,
103 ;
104 }
105
106 pub broadcast proof fn $setbit_bit_is_set(word: $uN, b: int)
108 requires
109 0 <= b < $width,
110 ensures
111 #![trigger $bit_is_set(word | ($one << (b as usize)), b)]
112 $bit_is_set(word | ($one << (b as usize)), b),
113 {
114 let bu: u32 = b as u32;
115 assert(((word | ($one << bu)) & ($one << bu)) == ($one << bu)) by (bit_vector);
116 assert((bu < $width_u32) ==> (($one << bu) != $zero)) by (bit_vector);
117 }
118
119 pub broadcast proof fn $setbit_bit_unchanged(word: $uN, b: int, b2: int)
121 requires
122 0 <= b < $width,
123 0 <= b2 < $width,
124 b != b2,
125 ensures
126 #![trigger $bit_is_set(word | ($one << (b as usize)), b2), ($one << (b as usize))]
127 $bit_is_set(word | ($one << (b as usize)), b2) == $bit_is_set(word, b2),
128 {
129 let bu: u32 = b as u32;
130 let b2u: u32 = b2 as u32;
131 assert((bu != b2u) ==> (((word | ($one << bu)) & ($one << b2u))
132 == (word & ($one << b2u)))) by (bit_vector);
133 }
134
135 pub broadcast proof fn $clearbit_not_bit_is_set(word: $uN, b: int)
137 requires
138 0 <= b < $width,
139 ensures
140 #![trigger $bit_is_set(word & (!($one << (b as usize))), b)]
141 !$bit_is_set(word & (!($one << (b as usize))), b),
142 {
143 let bu: u32 = b as u32;
144 assert((word & (!($one << bu))) & ($one << bu) == $zero) by (bit_vector);
145 }
146
147 pub broadcast proof fn $clearbit_bit_unchanged(word: $uN, b: int, b2: int)
149 requires
150 0 <= b < $width,
151 0 <= b2 < $width,
152 b != b2,
153 ensures
154 #![trigger $bit_is_set(word & (!($one << (b as usize))), b2), ($one << (b as usize))]
155 $bit_is_set(word & (!($one << (b as usize))), b2) == $bit_is_set(word, b2),
156 {
157 let bu: u32 = b as u32;
158 let b2u: u32 = b2 as u32;
159 assert((bu != b2u) ==> (((word & (!($one << bu))) & ($one << b2u))
160 == (word & ($one << b2u)))) by (bit_vector);
161 }
162
163 pub proof fn $and_zero(x: $uN)
165 ensures
166 $zero & x == $zero,
167 {
168 assert($zero & x == $zero) by (bit_vector);
169 }
170
171 pub broadcast group $group {
172 $allones_bit_it_set,
173 $unit_le_shl,
174 $masked_bit_clear,
175 $masked_bit_keep,
176 $setbit_bit_is_set,
177 $setbit_bit_unchanged,
178 $clearbit_not_bit_is_set,
179 $clearbit_bit_unchanged,
180 }
181
182 } };
184}
185
186define_unsigned_bit_lemmas!(
187 u8,
188 0u8,
189 1u8,
190 8,
191 8u32,
192 u8_bit_is_set,
193 lemma_u8_allones_bit_it_set,
194 lemma_u8_unit_le_shl,
195 lemma_u8_masked_bit_clear,
196 lemma_u8_masked_bit_keep,
197 lemma_u8_setbit_bit_is_set,
198 lemma_u8_setbit_bit_unchanged,
199 lemma_u8_clearbit_not_bit_is_set,
200 lemma_u8_clearbit_bit_unchanged,
201 lemma_u8_and_zero,
202 group_u8_bit_algebra
203);
204define_unsigned_bit_lemmas!(
205 u16,
206 0u16,
207 1u16,
208 16,
209 16u32,
210 u16_bit_is_set,
211 lemma_u16_allones_bit_it_set,
212 lemma_u16_unit_le_shl,
213 lemma_u16_masked_bit_clear,
214 lemma_u16_masked_bit_keep,
215 lemma_u16_setbit_bit_is_set,
216 lemma_u16_setbit_bit_unchanged,
217 lemma_u16_clearbit_not_bit_is_set,
218 lemma_u16_clearbit_bit_unchanged,
219 lemma_u16_and_zero,
220 group_u16_bit_algebra
221);
222define_unsigned_bit_lemmas!(
223 u32,
224 0u32,
225 1u32,
226 32,
227 32u32,
228 u32_bit_is_set,
229 lemma_u32_allones_bit_it_set,
230 lemma_u32_unit_le_shl,
231 lemma_u32_masked_bit_clear,
232 lemma_u32_masked_bit_keep,
233 lemma_u32_setbit_bit_is_set,
234 lemma_u32_setbit_bit_unchanged,
235 lemma_u32_clearbit_not_bit_is_set,
236 lemma_u32_clearbit_bit_unchanged,
237 lemma_u32_and_zero,
238 group_u32_bit_algebra
239);
240define_unsigned_bit_lemmas!(
241 u64,
242 0u64,
243 1u64,
244 64,
245 64u32,
246 u64_bit_is_set,
247 lemma_u64_allones_bit_it_set,
248 lemma_u64_unit_le_shl,
249 lemma_u64_masked_bit_clear,
250 lemma_u64_masked_bit_keep,
251 lemma_u64_setbit_bit_is_set,
252 lemma_u64_setbit_bit_unchanged,
253 lemma_u64_clearbit_not_bit_is_set,
254 lemma_u64_clearbit_bit_unchanged,
255 lemma_u64_and_zero,
256 group_u64_bit_algebra
257);
258define_unsigned_bit_lemmas!(
259 u128,
260 0u128,
261 1u128,
262 128,
263 128u32,
264 u128_bit_is_set,
265 lemma_u128_allones_bit_it_set,
266 lemma_u128_unit_le_shl,
267 lemma_u128_masked_bit_clear,
268 lemma_u128_masked_bit_keep,
269 lemma_u128_setbit_bit_is_set,
270 lemma_u128_setbit_bit_unchanged,
271 lemma_u128_clearbit_not_bit_is_set,
272 lemma_u128_clearbit_bit_unchanged,
273 lemma_u128_and_zero,
274 group_u128_bit_algebra
275);
276define_unsigned_bit_lemmas!(
277 usize,
278 0usize,
279 1usize,
280 usize::BITS as int,
281 usize::BITS,
282 usize_bit_is_set,
283 lemma_usize_allones_bit_it_set,
284 lemma_usize_unit_le_shl,
285 lemma_usize_masked_bit_clear,
286 lemma_usize_masked_bit_keep,
287 lemma_usize_setbit_bit_is_set,
288 lemma_usize_setbit_bit_unchanged,
289 lemma_usize_clearbit_not_bit_is_set,
290 lemma_usize_clearbit_bit_unchanged,
291 lemma_usize_and_zero,
292 group_usize_bit_algebra
293);