CBMC
bitvector_expr.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: API to expression classes for bitvectors
4 
5 Author: 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 
23 extractbit_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 _upper,
34  const std::size_t _lower,
35  typet _type)
36  : expr_protectedt(ID_extractbits, std::move(_type))
37 {
38  PRECONDITION(_upper >= _lower);
40  std::move(_src),
41  from_integer(_upper, integer_typet()),
42  from_integer(_lower, integer_typet()));
43 }
44 
46 {
47  const auto width = to_bitvector_type(type()).get_width();
48  auto src_bv_type = bv_typet(width);
49 
50  // build a mask 0...0 1
51  auto mask_bv =
52  make_bvrep(width, [](std::size_t index) { return index == 0; });
53  auto mask_expr = constant_exprt(mask_bv, src_bv_type);
54 
55  // shift the mask by the index
56  auto mask_shifted = shl_exprt(mask_expr, index());
57 
58  auto src_masked = bitand_exprt(
59  typecast_exprt(src(), src_bv_type), bitnot_exprt(mask_shifted));
60 
61  // zero-extend the replacement bit to match src
62  auto new_value_casted = typecast_exprt(
63  typecast_exprt(new_value(), unsignedbv_typet(width)), src_bv_type);
64 
65  // shift the replacement bits
66  auto new_value_shifted = shl_exprt(new_value_casted, index());
67 
68  // or the masked src and the shifted replacement bits
69  return typecast_exprt(
70  bitor_exprt(src_masked, new_value_shifted), src().type());
71 }
72 
74 {
75  const auto width = to_bitvector_type(type()).get_width();
76  const auto new_value_width =
78  auto src_bv_type = bv_typet(width);
79 
80  // build a mask 1...1 0...0
81  auto mask_bv = make_bvrep(width, [new_value_width](std::size_t index) {
82  return index >= new_value_width;
83  });
84  auto mask_expr = constant_exprt(mask_bv, src_bv_type);
85 
86  // shift the mask by the index
87  auto mask_shifted = shl_exprt(mask_expr, index());
88 
89  auto src_masked =
90  bitand_exprt(typecast_exprt(src(), src_bv_type), mask_shifted);
91 
92  // zero-extend or shrink the replacement bits to match src
93  auto new_value_casted = typecast_exprt(new_value(), src_bv_type);
94 
95  // shift the replacement bits
96  auto new_value_shifted = shl_exprt(new_value_casted, index());
97 
98  // or the masked src and the shifted replacement bits
99  return typecast_exprt(
100  bitor_exprt(src_masked, new_value_shifted), src().type());
101 }
102 
104 {
105  // Hacker's Delight, variant pop0:
106  // x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
107  // x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
108  // x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
109  // x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
110  // etc.
111  // return x;
112  // http://www.hackersdelight.org/permissions.htm
113 
114  // make sure the operand width is a power of two
115  exprt x = op();
116  const auto x_width = to_bitvector_type(x.type()).get_width();
117  CHECK_RETURN(x_width >= 1);
118  const std::size_t bits = address_bits(x_width);
119  const std::size_t new_width = numeric_cast_v<std::size_t>(power(2, bits));
120 
121  const bool need_typecast =
122  new_width > x_width || x.type().id() != ID_unsignedbv;
123 
124  if(need_typecast)
125  x = typecast_exprt(x, unsignedbv_typet(new_width));
126 
127  // repeatedly compute x = (x & bitmask) + ((x >> shift) & bitmask)
128  for(std::size_t shift = 1; shift < new_width; shift <<= 1)
129  {
130  // x >> shift
131  lshr_exprt shifted_x(
132  x, from_integer(shift, unsignedbv_typet(address_bits(shift) + 1)));
133  // bitmask is a string of alternating shift-many bits starting from lsb set
134  // to 1
135  std::string bitstring;
136  bitstring.reserve(new_width);
137  for(std::size_t i = 0; i < new_width / (2 * shift); ++i)
138  bitstring += std::string(shift, '0') + std::string(shift, '1');
139  const mp_integer value = binary2integer(bitstring, false);
140  const constant_exprt bitmask(integer2bvrep(value, new_width), x.type());
141  // build the expression
142  x = plus_exprt(bitand_exprt(x, bitmask), bitand_exprt(shifted_x, bitmask));
143  }
144 
145  // the result is restricted to the result type
147 }
148 
150 {
151  // x = x | (x >> 1);
152  // x = x | (x >> 2);
153  // x = x | (x >> 4);
154  // x = x | (x >> 8);
155  // etc.
156  // return popcount(~x);
157 
158  // make sure the operand width is a power of two
159  exprt x = op();
160  const auto x_width = to_bitvector_type(x.type()).get_width();
161  CHECK_RETURN(x_width >= 1);
162  const std::size_t bits = address_bits(x_width);
163  const std::size_t new_width = numeric_cast_v<std::size_t>(power(2, bits));
164 
165  const bool need_typecast =
166  new_width > x_width || x.type().id() != ID_unsignedbv;
167 
168  if(need_typecast)
169  x = typecast_exprt(x, unsignedbv_typet(new_width));
170 
171  // repeatedly compute x = x | (x >> shift)
172  for(std::size_t shift = 1; shift < new_width; shift <<= 1)
173  {
174  // x >> shift
175  lshr_exprt shifted_x(
176  x, from_integer(shift, unsignedbv_typet(address_bits(shift) + 1)));
177  // build the expression
178  x = bitor_exprt{x, shifted_x};
179  }
180 
181  // the result is restricted to the result type
182  return popcount_exprt{
184  .lower();
185 }
186 
188 {
189  exprt x = op();
190 
191  // popcount(~(x | (~x + 1)))
192  // compute -x using two's complement
193  plus_exprt minus_x{bitnot_exprt{x}, from_integer(1, x.type())};
194  bitor_exprt x_or_minus_x{x, std::move(minus_x)};
195  popcount_exprt popcount{bitnot_exprt{std::move(x_or_minus_x)}};
196 
197  return typecast_exprt::conditional_cast(popcount.lower(), type());
198 }
199 
201 {
202  const std::size_t int_width = to_bitvector_type(type()).get_width();
203 
204  exprt::operandst result_bits;
205  result_bits.reserve(int_width);
206 
207  const symbol_exprt to_reverse("to_reverse", op().type());
208  for(std::size_t i = 0; i < int_width; ++i)
209  result_bits.push_back(extractbit_exprt{to_reverse, i});
210 
211  return let_exprt{to_reverse, op(), concatenation_exprt{result_bits, type()}};
212 }
213 
215 {
216  std::size_t lhs_ssize = to_bitvector_type(lhs().type()).get_width();
217  if(lhs().type().id() == ID_unsignedbv)
218  ++lhs_ssize;
219  std::size_t rhs_ssize = to_bitvector_type(rhs().type()).get_width();
220  if(rhs().type().id() == ID_unsignedbv)
221  ++rhs_ssize;
222 
223  std::size_t ssize = std::max(lhs_ssize, rhs_ssize) + 1;
224  signedbv_typet ssize_type{ssize};
225  plus_exprt exact_result{
226  typecast_exprt{lhs(), ssize_type}, typecast_exprt{rhs(), ssize_type}};
227 
228  return notequal_exprt{
229  typecast_exprt{typecast_exprt{exact_result, lhs().type()}, ssize_type},
230  exact_result};
231 }
232 
234 {
235  std::size_t lhs_ssize = to_bitvector_type(lhs().type()).get_width();
236  if(lhs().type().id() == ID_unsignedbv)
237  ++lhs_ssize;
238  std::size_t rhs_ssize = to_bitvector_type(rhs().type()).get_width();
239  if(rhs().type().id() == ID_unsignedbv)
240  ++rhs_ssize;
241 
242  std::size_t ssize = std::max(lhs_ssize, rhs_ssize) + 1;
243  signedbv_typet ssize_type{ssize};
244  minus_exprt exact_result{
245  typecast_exprt{lhs(), ssize_type}, typecast_exprt{rhs(), ssize_type}};
246 
247  return notequal_exprt{
248  typecast_exprt{typecast_exprt{exact_result, lhs().type()}, ssize_type},
249  exact_result};
250 }
251 
253 {
254  std::size_t lhs_ssize = to_bitvector_type(lhs().type()).get_width();
255  if(lhs().type().id() == ID_unsignedbv)
256  ++lhs_ssize;
257  std::size_t rhs_ssize = to_bitvector_type(rhs().type()).get_width();
258  if(rhs().type().id() == ID_unsignedbv)
259  ++rhs_ssize;
260 
261  std::size_t ssize = lhs_ssize + rhs_ssize;
262  signedbv_typet ssize_type{ssize};
263  mult_exprt exact_result{
264  typecast_exprt{lhs(), ssize_type}, typecast_exprt{rhs(), ssize_type}};
265 
266  return notequal_exprt{
267  typecast_exprt{typecast_exprt{exact_result, lhs().type()}, ssize_type},
268  exact_result};
269 }
270 
272 {
273  exprt x = op();
274  const auto int_width = to_bitvector_type(x.type()).get_width();
275  CHECK_RETURN(int_width >= 1);
276 
277  // bitwidth(x) - clz(x & ~((unsigned)x - 1));
278  const unsignedbv_typet ut{int_width};
279  minus_exprt minus_one{
282  x, bitnot_exprt{typecast_exprt::conditional_cast(minus_one, x.type())}}};
283  minus_exprt result{from_integer(int_width, x.type()), clz.lower()};
284 
285  return typecast_exprt::conditional_cast(result, type());
286 }
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.
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.
A base class for binary expressions.
Definition: std_expr.h:638
exprt & lhs()
Definition: std_expr.h:668
exprt & rhs()
Definition: std_expr.h:678
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly two argu...
Definition: std_expr.h:731
Bit-wise AND.
Bit-wise negation of bit-vectors.
Bit-wise OR.
exprt lower() const
Lower a bitreverse_exprt to arithmetic and logic expressions.
std::size_t get_width() const
Definition: std_types.h:920
Fixed-width bit-vector without numerical interpretation.
Concatenation of bit-vector operands.
A constant literal expression.
Definition: std_expr.h:2987
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.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
Base class for all expressions.
Definition: expr.h:344
Base class for all expressions.
Definition: expr.h:56
std::vector< exprt > operandst
Definition: expr.h:58
typet & type()
Return the type of the expression.
Definition: expr.h:84
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition: expr.h:170
Extracts a single bit of a bit-vector operand.
extractbit_exprt(exprt _src, exprt _index)
Extract the _index-th least significant bit from _src.
extractbits_exprt(exprt _src, exprt _upper, exprt _lower, typet _type)
Extract the bits [_lower .
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:384
A let expression.
Definition: std_expr.h:3196
Logical right shift.
Binary minus.
Definition: std_expr.h:1061
exprt lower() const
Lower a minus_overflow_exprt to arithmetic and logic expressions.
Binary multiplication Associativity is not specified.
Definition: std_expr.h:1107
exprt lower() const
Lower a mult_overflow_exprt to arithmetic and logic expressions.
Disequality.
Definition: std_expr.h:1420
The plus expression Associativity is not specified.
Definition: std_expr.h:1002
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.
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:131
Semantic type conversion.
Definition: std_expr.h:2068
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2076
The type of an expression, extends irept.
Definition: type.h:29
const exprt & op() const
Definition: std_expr.h:391
Fixed-width bit-vector with unsigned binary interpretation.
exprt lower() const
A lowering to masking, shifting, or.
exprt lower() const
A lowering to masking, shifting, or.
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
BigInt mp_integer
Definition: smt_terms.h:17
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
#define PRECONDITION(CONDITION)
Definition: invariant.h:463