CBMC
Loading...
Searching...
No Matches
bitvector_expr.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: API to expression classes for bitvectors
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
9#include "bitvector_expr.h"
10
11#include "arith_tools.h"
12#include "bitvector_types.h"
13#include "mathematical_types.h"
14
16 exprt _src,
17 const irep_idt &_id,
18 const std::size_t _distance)
19 : binary_exprt(std::move(_src), _id, from_integer(_distance, integer_typet()))
20{
21}
22
23extractbit_exprt::extractbit_exprt(exprt _src, const std::size_t _index)
25 std::move(_src),
26 ID_extractbit,
27 from_integer(_index, integer_typet()))
28{
29}
30
32 exprt _src,
33 const std::size_t _index,
34 typet _type)
35 : expr_protectedt(ID_extractbits, std::move(_type))
36{
37 add_to_operands(std::move(_src), from_integer(_index, integer_typet()));
38}
39
41 exprt _src,
42 const std::size_t _index,
43 exprt _new_value)
45 std::move(_src),
46 from_integer(_index, integer_typet()),
47 std::move(_new_value))
48{
49}
50
52{
53 const auto width = to_bitvector_type(type()).get_width();
54 auto src_bv_type = bv_typet(width);
55
56 // build a mask 0...0 1
57 auto mask_bv =
58 make_bvrep(width, [](std::size_t index) { return index == 0; });
59 auto mask_expr = constant_exprt(mask_bv, src_bv_type);
60
61 // shift the mask by the index
62 auto mask_shifted = shl_exprt(mask_expr, index());
63
64 auto src_masked = bitand_exprt(
65 typecast_exprt(src(), src_bv_type), bitnot_exprt(mask_shifted));
66
67 // zero-extend the replacement bit to match src
68 auto new_value_bv = typecast_exprt{new_value(), bv_typet{1}};
69 auto new_value_casted = zero_extend_exprt{new_value_bv, src_bv_type};
70
71 // shift the replacement bits
72 auto new_value_shifted = shl_exprt(new_value_casted, index());
73
74 // or the masked src and the shifted replacement bits
75 return typecast_exprt(
76 bitor_exprt(src_masked, new_value_shifted), src().type());
77}
78
80{
81 const auto width = to_bitvector_type(type()).get_width();
82 const auto new_value_width =
84 auto src_bv_type = bv_typet(width);
85
86 // build a mask 1...1 0...0
87 auto mask_bv = make_bvrep(width, [new_value_width](std::size_t index) {
88 return index >= new_value_width;
89 });
90 auto mask_expr = constant_exprt(mask_bv, src_bv_type);
91
92 // shift the mask by the index
93 auto mask_shifted = shl_exprt(mask_expr, index());
94
95 auto src_masked =
96 bitand_exprt(typecast_exprt(src(), src_bv_type), mask_shifted);
97
98 // zero-extend or shrink the replacement bits to match src
99 auto new_value_casted = zero_extend_exprt{new_value(), src_bv_type};
100
101 // shift the replacement bits
102 auto new_value_shifted = shl_exprt(new_value_casted, index());
103
104 // or the masked src and the shifted replacement bits
105 return typecast_exprt(
106 bitor_exprt(src_masked, new_value_shifted), src().type());
107}
108
110{
111 // Hacker's Delight, variant pop0:
112 // x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
113 // x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
114 // x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
115 // x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
116 // etc.
117 // return x;
118 // http://www.hackersdelight.org/permissions.htm
119
120 // make sure the operand width is a power of two
121 exprt x = op();
122 const auto x_width = to_bitvector_type(x.type()).get_width();
123 CHECK_RETURN(x_width >= 1);
124 const std::size_t bits = address_bits(x_width);
125 const std::size_t new_width = numeric_cast_v<std::size_t>(power(2, bits));
126
127 const bool need_typecast =
128 new_width > x_width || x.type().id() != ID_unsignedbv;
129
130 if(need_typecast)
131 x = typecast_exprt(x, unsignedbv_typet(new_width));
132
133 // repeatedly compute x = (x & bitmask) + ((x >> shift) & bitmask)
134 for(std::size_t shift = 1; shift < new_width; shift <<= 1)
135 {
136 // x >> shift
137 lshr_exprt shifted_x(
138 x, from_integer(shift, unsignedbv_typet(address_bits(shift) + 1)));
139 // bitmask is a string of alternating shift-many bits starting from lsb set
140 // to 1
141 std::string bitstring;
142 bitstring.reserve(new_width);
143 for(std::size_t i = 0; i < new_width / (2 * shift); ++i)
144 bitstring += std::string(shift, '0') + std::string(shift, '1');
145 const mp_integer value = binary2integer(bitstring, false);
146 const constant_exprt bitmask(integer2bvrep(value, new_width), x.type());
147 // build the expression
148 x = plus_exprt(bitand_exprt(x, bitmask), bitand_exprt(shifted_x, bitmask));
149 }
150
151 // the result is restricted to the result type
153}
154
156{
157 // x = x | (x >> 1);
158 // x = x | (x >> 2);
159 // x = x | (x >> 4);
160 // x = x | (x >> 8);
161 // etc.
162 // return popcount(~x);
163
164 // make sure the operand width is a power of two
165 exprt x = op();
166 const auto x_width = to_bitvector_type(x.type()).get_width();
167 CHECK_RETURN(x_width >= 1);
168 const std::size_t bits = address_bits(x_width);
169 const std::size_t new_width = numeric_cast_v<std::size_t>(power(2, bits));
170
171 const bool need_typecast =
172 new_width > x_width || x.type().id() != ID_unsignedbv;
173
174 if(need_typecast)
175 x = typecast_exprt(x, unsignedbv_typet(new_width));
176
177 // repeatedly compute x = x | (x >> shift)
178 for(std::size_t shift = 1; shift < new_width; shift <<= 1)
179 {
180 // x >> shift
181 lshr_exprt shifted_x(
182 x, from_integer(shift, unsignedbv_typet(address_bits(shift) + 1)));
183 // build the expression
184 x = bitor_exprt{x, shifted_x};
185 }
186
187 // the result is restricted to the result type
188 return popcount_exprt{
190 .lower();
191}
192
194{
195 exprt x = op();
196
197 // popcount(~(x | (~x + 1)))
198 // compute -x using two's complement
199 plus_exprt minus_x{bitnot_exprt{x}, from_integer(1, x.type())};
200 bitor_exprt x_or_minus_x{x, std::move(minus_x)};
201 popcount_exprt popcount{bitnot_exprt{std::move(x_or_minus_x)}};
202
203 return typecast_exprt::conditional_cast(popcount.lower(), type());
204}
205
207{
208 const std::size_t int_width = to_bitvector_type(type()).get_width();
209
210 exprt::operandst result_bits;
211 result_bits.reserve(int_width);
212
213 const symbol_exprt to_reverse("to_reverse", op().type());
214 for(std::size_t i = 0; i < int_width; ++i)
215 result_bits.push_back(extractbit_exprt{to_reverse, i});
216
217 return let_exprt{to_reverse, op(), concatenation_exprt{result_bits, type()}};
218}
219
221{
222 std::size_t lhs_ssize = to_bitvector_type(lhs().type()).get_width();
223 if(lhs().type().id() == ID_unsignedbv)
224 ++lhs_ssize;
225 std::size_t rhs_ssize = to_bitvector_type(rhs().type()).get_width();
226 if(rhs().type().id() == ID_unsignedbv)
227 ++rhs_ssize;
228
229 std::size_t ssize = std::max(lhs_ssize, rhs_ssize) + 1;
230 signedbv_typet ssize_type{ssize};
231 plus_exprt exact_result{
232 typecast_exprt{lhs(), ssize_type}, typecast_exprt{rhs(), ssize_type}};
233
234 return notequal_exprt{
235 typecast_exprt{typecast_exprt{exact_result, lhs().type()}, ssize_type},
236 exact_result};
237}
238
240{
241 std::size_t lhs_ssize = to_bitvector_type(lhs().type()).get_width();
242 if(lhs().type().id() == ID_unsignedbv)
243 ++lhs_ssize;
244 std::size_t rhs_ssize = to_bitvector_type(rhs().type()).get_width();
245 if(rhs().type().id() == ID_unsignedbv)
246 ++rhs_ssize;
247
248 std::size_t ssize = std::max(lhs_ssize, rhs_ssize) + 1;
249 signedbv_typet ssize_type{ssize};
250 minus_exprt exact_result{
251 typecast_exprt{lhs(), ssize_type}, typecast_exprt{rhs(), ssize_type}};
252
253 return notequal_exprt{
254 typecast_exprt{typecast_exprt{exact_result, lhs().type()}, ssize_type},
255 exact_result};
256}
257
259{
260 std::size_t lhs_ssize = to_bitvector_type(lhs().type()).get_width();
261 if(lhs().type().id() == ID_unsignedbv)
262 ++lhs_ssize;
263 std::size_t rhs_ssize = to_bitvector_type(rhs().type()).get_width();
264 if(rhs().type().id() == ID_unsignedbv)
265 ++rhs_ssize;
266
267 std::size_t ssize = lhs_ssize + rhs_ssize;
268 signedbv_typet ssize_type{ssize};
269 mult_exprt exact_result{
270 typecast_exprt{lhs(), ssize_type}, typecast_exprt{rhs(), ssize_type}};
271
272 return notequal_exprt{
273 typecast_exprt{typecast_exprt{exact_result, lhs().type()}, ssize_type},
274 exact_result};
275}
276
278{
279 exprt x = op();
280 const auto int_width = to_bitvector_type(x.type()).get_width();
281 CHECK_RETURN(int_width >= 1);
282
283 // bitwidth(x) - clz(x & ~((unsigned)x - 1));
284 const unsignedbv_typet ut{int_width};
285 minus_exprt minus_one{
289 minus_exprt result{from_integer(int_width, x.type()), clz.lower()};
290
291 return typecast_exprt::conditional_cast(result, type());
292}
293
295{
296 const auto old_width = to_bitvector_type(op().type()).get_width();
297 const auto new_width = to_bitvector_type(type()).get_width();
298
299 if(new_width > old_width)
300 {
301 return concatenation_exprt{
302 bv_typet{new_width - old_width}.all_zeros_expr(), op(), type()};
303 }
304 else // new_width <= old_width
305 {
306 return extractbits_exprt{op(), 0, type()};
307 }
308}
309
312static std::pair<exprt, exprt> onehot_lowering_helper(const exprt &expr)
313{
314 exprt one_seen = false_exprt{};
315 const auto width = to_bitvector_type(expr.type()).get_width();
316 exprt::operandst more_than_one_seen_disjuncts;
317 more_than_one_seen_disjuncts.reserve(width);
318
319 for(std::size_t i = 0; i < width; i++)
320 {
321 auto bit = extractbit_exprt{expr, i};
322 more_than_one_seen_disjuncts.push_back(and_exprt{bit, one_seen});
323 one_seen = or_exprt{one_seen, bit};
324 }
325
326 return {one_seen, disjunction(more_than_one_seen_disjuncts)};
327}
328
330{
331 auto symbol = symbol_exprt{"onehot-op", op().type()};
332 auto [one_seen, more_than_one_seen] = onehot_lowering_helper(symbol);
333
334 // exactly one bit is set
335 return let_exprt{
336 symbol, op(), and_exprt{one_seen, not_exprt{more_than_one_seen}}};
337}
338
340{
341 auto symbol = symbol_exprt{"onehot-op", op().type()};
342 auto [one_seen, more_than_one_seen] = onehot_lowering_helper(symbol);
343
344 // at most one bit is set
345 return let_exprt{symbol, op(), not_exprt{more_than_one_seen}};
346}
347
349{
350 auto &operand = op();
351 return equal_exprt{
352 operand, to_bitvector_type(operand.type()).all_ones_expr()};
353}
354
356{
357 auto &operand = op();
358 return notequal_exprt{
359 operand, to_bitvector_type(operand.type()).all_ones_expr()};
360}
361
363{
364 auto &operand = op();
365 return notequal_exprt{
366 operand, to_bitvector_type(operand.type()).all_zeros_expr()};
367}
368
370{
371 auto &operand = op();
372 return equal_exprt{
373 operand, to_bitvector_type(operand.type()).all_zeros_expr()};
374}
375
377{
378 auto &operand = op();
379 auto width = to_bitvector_type(operand.type()).width();
380 PRECONDITION(width >= 1);
382 bits.reserve(width);
383 for(std::size_t i = 0; i < width; i++)
384 bits.push_back(extractbit_exprt{operand, i});
385 return xor_exprt{std::move(bits)};
386}
387
392
394{
395 // zero-replications are allowed, and yield a concatenation
396 // with no operands.
397 auto count = numeric_cast_v<std::size_t>(times());
399 ops.reserve(count);
400 for(std::size_t i = 0; i < count; i++)
401 ops.push_back(op());
402 return concatenation_exprt{std::move(ops), type()};
403}
irep_idt make_bvrep(const std::size_t width, const std::function< bool(std::size_t)> f)
construct a bit-vector representation from a functor
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
std::size_t address_bits(const mp_integer &size)
ceil(log2(size))
irep_idt integer2bvrep(const mp_integer &src, std::size_t width)
convert an integer to bit-vector representation with given width This uses two's complement for negat...
mp_integer power(const mp_integer &base, const mp_integer &exponent)
A multi-precision implementation of the power operator.
Target numeric_cast_v(const mp_integer &arg)
Convert an mp_integer to integral type Target An invariant will fail if the conversion is not possibl...
static std::pair< exprt, exprt > onehot_lowering_helper(const exprt &expr)
Returns a pair of expressions: the first is true iff at least one bit of expr is set,...
API to expression classes for bitvectors.
Pre-defined bitvector types.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
Boolean AND All operands must be boolean, and the result is always boolean.
Definition std_expr.h:2043
exprt & lhs()
Definition std_expr.h:679
binary_exprt(const exprt &_lhs, const irep_idt &_id, exprt _rhs)
Definition std_expr.h:651
exprt & rhs()
Definition std_expr.h:689
binary_predicate_exprt(exprt _op0, const irep_idt &_id, exprt _op1)
Definition std_expr.h:739
Bit-wise AND Any number of operands that is greater or equal one.
Bit-wise negation of bit-vectors.
Bit-wise OR Any number of operands that is greater or equal one.
exprt lower() const
Lower a bitreverse_exprt to arithmetic and logic expressions.
constant_exprt all_zeros_expr() const
constant_exprt all_ones_expr() const
std::size_t get_width() const
std::size_t width() const
Fixed-width bit-vector without numerical interpretation.
Concatenation of bit-vector operands.
A constant literal expression.
Definition std_expr.h:3007
The count leading zeros (counting the number of zero bits starting from the most-significant bit) exp...
exprt lower() const
Lower a count_leading_zeros_exprt to arithmetic and logic expressions.
exprt lower() const
Lower a count_trailing_zeros_exprt to arithmetic and logic expressions.
Equality.
Definition std_expr.h:1339
expr_protectedt(irep_idt _id, typet _type)
Definition expr.h:353
Base class for all expressions.
Definition expr.h:57
std::vector< exprt > operandst
Definition expr.h:59
exprt()
Definition expr.h:62
typet & type()
Return the type of the expression.
Definition expr.h:85
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition expr.h:171
Extracts a single bit of a bit-vector operand.
extractbit_exprt(exprt _src, exprt _index)
Extract the _index-th least significant bit from _src.
Extracts a sub-range of a bit-vector operand.
extractbits_exprt(exprt _src, exprt _index, typet _type)
Extract the bits [_index .
The Boolean constant false.
Definition std_expr.h:3135
exprt lower() const
Lower a find_first_set_exprt to arithmetic and logic expressions.
Unbounded, signed integers (mathematical integers, not bitvectors).
const irep_idt & id() const
Definition irep.h:390
A let expression.
Definition std_expr.h:3259
Logical right shift.
Binary minus.
Definition std_expr.h:1065
exprt lower() const
Lower a minus_overflow_exprt to arithmetic and logic expressions.
Binary multiplication Associativity is not specified.
Definition std_expr.h:1104
exprt lower() const
Lower a mult_overflow_exprt to arithmetic and logic expressions.
Boolean negation.
Definition std_expr.h:2388
Disequality.
Definition std_expr.h:1393
exprt lower() const
lowering to extractbit
exprt lower() const
lowering to extractbit
Boolean OR All operands must be boolean, and the result is always boolean.
Definition std_expr.h:2193
The plus expression Associativity is not specified.
Definition std_expr.h:1006
exprt lower() const
Lower a plus_overflow_exprt to arithmetic and logic expressions.
The popcount (counting the number of bits set to 1) expression.
exprt lower() const
Lower a popcount_exprt to arithmetic and logic expressions.
exprt lower() const
Lower to equality with all-ones constant.
exprt lower() const
Lower to inequality with all-ones constant.
exprt lower() const
Lower to equality with zero.
exprt lower() const
Lower to inequality with zero.
exprt lower() const
Lower to negation of XOR of all individual bits.
Boolean reduction: XOR (parity) of all bits in the operand.
exprt lower() const
Lower to XOR of all individual bits.
exprt lower() const
Lower to concatenation.
constant_exprt & times()
shift_exprt(exprt _src, const irep_idt &_id, exprt _distance)
Left shift.
Fixed-width bit-vector with two's complement interpretation.
Expression to hold a symbol (variable).
Definition std_expr.h:132
Semantic type conversion.
Definition std_expr.h:1995
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:2003
The type of an expression, extends irept.
Definition type.h:29
const exprt & op() const
Definition std_expr.h:394
Fixed-width bit-vector with unsigned binary interpretation.
update_bit_exprt(exprt _src, exprt _index, exprt _new_value)
Replaces the bit [_index] from _src to produce a result of the same type as _src.
exprt lower() const
A lowering to masking, shifting, or.
exprt lower() const
A lowering to masking, shifting, or.
Boolean XOR All operands must be boolean, and the result is always boolean.
Definition std_expr.h:2300
zero extension The operand is converted to the given type by either a) truncating if the new type is ...
Mathematical types.
const mp_integer binary2integer(const std::string &n, bool is_signed)
convert binary string representation to mp_integer
Definition mp_arith.cpp:117
STL namespace.
const std::size_t sharing_mapt< keyT, valueT, fail_if_equal, hashT, equalT >::bits
BigInt mp_integer
Definition smt_terms.h:17
#define CHECK_RETURN(CONDITION)
Definition invariant.h:495
#define PRECONDITION(CONDITION)
Definition invariant.h:463
exprt disjunction(const exprt::operandst &op)
1) generates a disjunction for two or more operands 2) for one operand, returns the operand 3) return...
Definition std_expr.cpp:240
dstringt irep_idt