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  // Hacker's Delight, variant pop0:
48  // x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
49  // x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
50  // x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
51  // x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
52  // etc.
53  // return x;
54  // http://www.hackersdelight.org/permissions.htm
55 
56  // make sure the operand width is a power of two
57  exprt x = op();
58  const auto x_width = to_bitvector_type(x.type()).get_width();
59  CHECK_RETURN(x_width >= 1);
60  const std::size_t bits = address_bits(x_width);
61  const std::size_t new_width = numeric_cast_v<std::size_t>(power(2, bits));
62 
63  const bool need_typecast =
64  new_width > x_width || x.type().id() != ID_unsignedbv;
65 
66  if(need_typecast)
67  x = typecast_exprt(x, unsignedbv_typet(new_width));
68 
69  // repeatedly compute x = (x & bitmask) + ((x >> shift) & bitmask)
70  for(std::size_t shift = 1; shift < new_width; shift <<= 1)
71  {
72  // x >> shift
73  lshr_exprt shifted_x(
74  x, from_integer(shift, unsignedbv_typet(address_bits(shift) + 1)));
75  // bitmask is a string of alternating shift-many bits starting from lsb set
76  // to 1
77  std::string bitstring;
78  bitstring.reserve(new_width);
79  for(std::size_t i = 0; i < new_width / (2 * shift); ++i)
80  bitstring += std::string(shift, '0') + std::string(shift, '1');
81  const mp_integer value = binary2integer(bitstring, false);
82  const constant_exprt bitmask(integer2bvrep(value, new_width), x.type());
83  // build the expression
84  x = plus_exprt(bitand_exprt(x, bitmask), bitand_exprt(shifted_x, bitmask));
85  }
86 
87  // the result is restricted to the result type
89 }
90 
92 {
93  // x = x | (x >> 1);
94  // x = x | (x >> 2);
95  // x = x | (x >> 4);
96  // x = x | (x >> 8);
97  // etc.
98  // return popcount(~x);
99 
100  // make sure the operand width is a power of two
101  exprt x = op();
102  const auto x_width = to_bitvector_type(x.type()).get_width();
103  CHECK_RETURN(x_width >= 1);
104  const std::size_t bits = address_bits(x_width);
105  const std::size_t new_width = numeric_cast_v<std::size_t>(power(2, bits));
106 
107  const bool need_typecast =
108  new_width > x_width || x.type().id() != ID_unsignedbv;
109 
110  if(need_typecast)
111  x = typecast_exprt(x, unsignedbv_typet(new_width));
112 
113  // repeatedly compute x = x | (x >> shift)
114  for(std::size_t shift = 1; shift < new_width; shift <<= 1)
115  {
116  // x >> shift
117  lshr_exprt shifted_x(
118  x, from_integer(shift, unsignedbv_typet(address_bits(shift) + 1)));
119  // build the expression
120  x = bitor_exprt{x, shifted_x};
121  }
122 
123  // the result is restricted to the result type
124  return popcount_exprt{
126  .lower();
127 }
128 
130 {
131  exprt x = op();
132 
133  // popcount(~(x | (~x + 1)))
134  // compute -x using two's complement
135  plus_exprt minus_x{bitnot_exprt{x}, from_integer(1, x.type())};
136  bitor_exprt x_or_minus_x{x, std::move(minus_x)};
137  popcount_exprt popcount{bitnot_exprt{std::move(x_or_minus_x)}};
138 
139  return typecast_exprt::conditional_cast(popcount.lower(), type());
140 }
141 
143 {
144  const std::size_t int_width = to_bitvector_type(type()).get_width();
145 
146  exprt::operandst result_bits;
147  result_bits.reserve(int_width);
148 
149  const symbol_exprt to_reverse("to_reverse", op().type());
150  for(std::size_t i = 0; i < int_width; ++i)
151  result_bits.push_back(extractbit_exprt{to_reverse, i});
152 
153  return let_exprt{to_reverse, op(), concatenation_exprt{result_bits, type()}};
154 }
155 
157 {
158  std::size_t lhs_ssize = to_bitvector_type(lhs().type()).get_width();
159  if(lhs().type().id() == ID_unsignedbv)
160  ++lhs_ssize;
161  std::size_t rhs_ssize = to_bitvector_type(rhs().type()).get_width();
162  if(rhs().type().id() == ID_unsignedbv)
163  ++rhs_ssize;
164 
165  std::size_t ssize = std::max(lhs_ssize, rhs_ssize) + 1;
166  signedbv_typet ssize_type{ssize};
167  plus_exprt exact_result{
168  typecast_exprt{lhs(), ssize_type}, typecast_exprt{rhs(), ssize_type}};
169 
170  return notequal_exprt{
171  typecast_exprt{typecast_exprt{exact_result, lhs().type()}, ssize_type},
172  exact_result};
173 }
174 
176 {
177  std::size_t lhs_ssize = to_bitvector_type(lhs().type()).get_width();
178  if(lhs().type().id() == ID_unsignedbv)
179  ++lhs_ssize;
180  std::size_t rhs_ssize = to_bitvector_type(rhs().type()).get_width();
181  if(rhs().type().id() == ID_unsignedbv)
182  ++rhs_ssize;
183 
184  std::size_t ssize = std::max(lhs_ssize, rhs_ssize) + 1;
185  signedbv_typet ssize_type{ssize};
186  minus_exprt exact_result{
187  typecast_exprt{lhs(), ssize_type}, typecast_exprt{rhs(), ssize_type}};
188 
189  return notequal_exprt{
190  typecast_exprt{typecast_exprt{exact_result, lhs().type()}, ssize_type},
191  exact_result};
192 }
193 
195 {
196  std::size_t lhs_ssize = to_bitvector_type(lhs().type()).get_width();
197  if(lhs().type().id() == ID_unsignedbv)
198  ++lhs_ssize;
199  std::size_t rhs_ssize = to_bitvector_type(rhs().type()).get_width();
200  if(rhs().type().id() == ID_unsignedbv)
201  ++rhs_ssize;
202 
203  std::size_t ssize = lhs_ssize + rhs_ssize;
204  signedbv_typet ssize_type{ssize};
205  mult_exprt exact_result{
206  typecast_exprt{lhs(), ssize_type}, typecast_exprt{rhs(), ssize_type}};
207 
208  return notequal_exprt{
209  typecast_exprt{typecast_exprt{exact_result, lhs().type()}, ssize_type},
210  exact_result};
211 }
212 
214 {
215  exprt x = op();
216  const auto int_width = to_bitvector_type(x.type()).get_width();
217  CHECK_RETURN(int_width >= 1);
218 
219  // bitwidth(x) - clz(x & ~((unsigned)x - 1));
220  const unsignedbv_typet ut{int_width};
221  minus_exprt minus_one{
224  x, bitnot_exprt{typecast_exprt::conditional_cast(minus_one, x.type())}}};
225  minus_exprt result{from_integer(int_width, x.type()), clz.lower()};
226 
227  return typecast_exprt::conditional_cast(result, type());
228 }
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
typecast_exprt::conditional_cast
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2025
mp_integer
BigInt mp_integer
Definition: smt_terms.h:17
shift_exprt::shift_exprt
shift_exprt(exprt _src, const irep_idt &_id, exprt _distance)
Definition: bitvector_expr.h:232
binary_exprt::rhs
exprt & rhs()
Definition: std_expr.h:623
arith_tools.h
count_leading_zeros_exprt::lower
exprt lower() const
Lower a count_leading_zeros_exprt to arithmetic and logic expressions.
Definition: bitvector_expr.cpp:91
CHECK_RETURN
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
typet
The type of an expression, extends irept.
Definition: type.h:28
count_trailing_zeros_exprt::lower
exprt lower() const
Lower a count_trailing_zeros_exprt to arithmetic and logic expressions.
Definition: bitvector_expr.cpp:129
plus_overflow_exprt::lower
exprt lower() const
Lower a plus_overflow_exprt to arithmetic and logic expressions.
Definition: bitvector_expr.cpp:156
popcount_exprt::lower
exprt lower() const
Lower a popcount_exprt to arithmetic and logic expressions.
Definition: bitvector_expr.cpp:45
integer_typet
Unbounded, signed integers (mathematical integers, not bitvectors)
Definition: mathematical_types.h:21
plus_exprt
The plus expression Associativity is not specified.
Definition: std_expr.h:946
exprt
Base class for all expressions.
Definition: expr.h:55
binary_exprt::lhs
exprt & lhs()
Definition: std_expr.h:613
binary_exprt
A base class for binary expressions.
Definition: std_expr.h:582
mult_overflow_exprt::lower
exprt lower() const
Lower a mult_overflow_exprt to arithmetic and logic expressions.
Definition: bitvector_expr.cpp:194
concatenation_exprt
Concatenation of bit-vector operands.
Definition: bitvector_expr.h:607
find_first_set_exprt::lower
exprt lower() const
Lower a find_first_set_exprt to arithmetic and logic expressions.
Definition: bitvector_expr.cpp:213
lshr_exprt
Logical right shift.
Definition: bitvector_expr.h:359
to_bitvector_type
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
Definition: bitvector_types.h:32
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
notequal_exprt
Disequality.
Definition: std_expr.h:1364
unsignedbv_typet
Fixed-width bit-vector with unsigned binary interpretation.
Definition: bitvector_types.h:158
mathematical_types.h
address_bits
std::size_t address_bits(const mp_integer &size)
ceil(log2(size))
Definition: arith_tools.cpp:177
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
bitor_exprt
Bit-wise OR.
Definition: bitvector_expr.h:124
integer2bvrep
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...
Definition: arith_tools.cpp:380
binary_predicate_exprt
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly two argu...
Definition: std_expr.h:675
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
bitvector_types.h
signedbv_typet
Fixed-width bit-vector with two's complement interpretation.
Definition: bitvector_types.h:207
mult_exprt
Binary multiplication Associativity is not specified.
Definition: std_expr.h:1051
irept::id
const irep_idt & id() const
Definition: irep.h:396
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
unary_exprt::op
const exprt & op() const
Definition: std_expr.h:326
bitand_exprt
Bit-wise AND.
Definition: bitvector_expr.h:194
minus_exprt
Binary minus.
Definition: std_expr.h:1005
bitvector_typet::get_width
std::size_t get_width() const
Definition: std_types.h:876
bitnot_exprt
Bit-wise negation of bit-vectors.
Definition: bitvector_expr.h:81
extractbit_exprt
Extracts a single bit of a bit-vector operand.
Definition: bitvector_expr.h:380
extractbit_exprt::extractbit_exprt
extractbit_exprt(exprt _src, exprt _index)
Extract the _index-th least significant bit from _src.
Definition: bitvector_expr.h:384
extractbits_exprt::extractbits_exprt
extractbits_exprt(exprt _src, exprt _upper, exprt _lower, typet _type)
Extract the bits [_lower .
Definition: bitvector_expr.h:455
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:100
binary2integer
const mp_integer binary2integer(const std::string &n, bool is_signed)
convert binary string representation to mp_integer
Definition: mp_arith.cpp:117
power
mp_integer power(const mp_integer &base, const mp_integer &exponent)
A multi-precision implementation of the power operator.
Definition: arith_tools.cpp:195
exprt::add_to_operands
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition: expr.h:162
bitreverse_exprt::lower
exprt lower() const
Lower a bitreverse_exprt to arithmetic and logic expressions.
Definition: bitvector_expr.cpp:142
minus_overflow_exprt::lower
exprt lower() const
Lower a minus_overflow_exprt to arithmetic and logic expressions.
Definition: bitvector_expr.cpp:175
popcount_exprt
The popcount (counting the number of bits set to 1) expression.
Definition: bitvector_expr.h:650
typecast_exprt
Semantic type conversion.
Definition: std_expr.h:2016
constant_exprt
A constant literal expression.
Definition: std_expr.h:2941
let_exprt
A let expression.
Definition: std_expr.h:3141
bitvector_expr.h
expr_protectedt
Base class for all expressions.
Definition: expr.h:323
count_leading_zeros_exprt
The count leading zeros (counting the number of zero bits starting from the most-significant bit) exp...
Definition: bitvector_expr.h:974