CBMC
boolbv_with.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
9 #include "boolbv.h"
10 
11 #include <util/arith_tools.h>
12 #include <util/c_types.h>
13 #include <util/namespace.h>
14 #include <util/std_expr.h>
15 
17 {
18  bvt bv = convert_bv(expr.old());
19 
20  std::size_t width=boolbv_width(expr.type());
21 
22  if(width==0)
23  {
24  // A zero-length array is acceptable:
25  return bvt{};
26  }
27 
29  bv.size() == width,
30  "unexpected operand 0 width",
32 
33  bvt prev_bv;
34  prev_bv.resize(width);
35 
36  const exprt::operandst &ops=expr.operands();
37 
38  for(std::size_t op_no=1; op_no<ops.size(); op_no+=2)
39  {
40  bv.swap(prev_bv);
41 
42  convert_with(expr.old().type(), ops[op_no], ops[op_no + 1], prev_bv, bv);
43  }
44 
45  return bv;
46 }
47 
49  const typet &type,
50  const exprt &op1,
51  const exprt &op2,
52  const bvt &prev_bv,
53  bvt &next_bv)
54 {
55  // we only do that on arrays, bitvectors, structs, and unions
56 
57  next_bv.resize(prev_bv.size());
58 
59  if(type.id()==ID_array)
60  return convert_with_array(to_array_type(type), op1, op2, prev_bv, next_bv);
61  else if(type.id()==ID_bv ||
62  type.id()==ID_unsignedbv ||
63  type.id()==ID_signedbv)
64  return convert_with_bv(op1, op2, prev_bv, next_bv);
65  else if(type.id()==ID_struct)
66  return
67  convert_with_struct(to_struct_type(type), op1, op2, prev_bv, next_bv);
68  else if(type.id() == ID_struct_tag)
69  return convert_with(
70  ns.follow_tag(to_struct_tag_type(type)), op1, op2, prev_bv, next_bv);
71  else if(type.id()==ID_union)
72  return convert_with_union(to_union_type(type), op2, prev_bv, next_bv);
73  else if(type.id() == ID_union_tag)
74  return convert_with(
75  ns.follow_tag(to_union_tag_type(type)), op1, op2, prev_bv, next_bv);
76 
78  false, "unexpected with type", irep_pretty_diagnosticst{type});
79 }
80 
82  const array_typet &type,
83  const exprt &op1,
84  const exprt &op2,
85  const bvt &prev_bv,
86  bvt &next_bv)
87 {
88  // can't do this
90  !is_unbounded_array(type),
91  "convert_with_array called for unbounded array",
93 
94  const exprt &array_size=type.size();
95 
96  const auto size = numeric_cast<mp_integer>(array_size);
97 
99  size.has_value(),
100  "convert_with_array expects constant array size",
102 
103  const bvt &op2_bv=convert_bv(op2);
104 
106  *size * op2_bv.size() == prev_bv.size(),
107  "convert_with_array: unexpected operand 2 width",
109 
110  // Is the index a constant?
111  if(const auto op1_value = numeric_cast<mp_integer>(op1))
112  {
113  // Yes, it is!
114  next_bv=prev_bv;
115 
116  if(*op1_value >= 0 && *op1_value < *size) // bounds check
117  {
118  const std::size_t offset =
119  numeric_cast_v<std::size_t>(*op1_value * op2_bv.size());
120 
121  for(std::size_t j=0; j<op2_bv.size(); j++)
122  next_bv[offset+j]=op2_bv[j];
123  }
124 
125  return;
126  }
127 
128  typet counter_type=op1.type();
129 
130  for(mp_integer i=0; i<size; i=i+1)
131  {
132  exprt counter=from_integer(i, counter_type);
133 
134  literalt eq_lit=convert(equal_exprt(op1, counter));
135 
136  const std::size_t offset = numeric_cast_v<std::size_t>(i * op2_bv.size());
137 
138  for(std::size_t j=0; j<op2_bv.size(); j++)
139  next_bv[offset+j]=
140  prop.lselect(eq_lit, op2_bv[j], prev_bv[offset+j]);
141  }
142 }
143 
145  const exprt &op1,
146  const exprt &op2,
147  const bvt &prev_bv,
148  bvt &next_bv)
149 {
150  literalt l=convert(op2);
151 
152  if(const auto op1_value = numeric_cast<mp_integer>(op1))
153  {
154  next_bv=prev_bv;
155 
156  if(*op1_value < next_bv.size())
157  next_bv[numeric_cast_v<std::size_t>(*op1_value)] = l;
158 
159  return;
160  }
161 
162  typet counter_type=op1.type();
163 
164  for(std::size_t i=0; i<prev_bv.size(); i++)
165  {
166  exprt counter=from_integer(i, counter_type);
167 
168  literalt eq_lit=convert(equal_exprt(op1, counter));
169 
170  next_bv[i]=prop.lselect(eq_lit, l, prev_bv[i]);
171  }
172 }
173 
175  const struct_typet &type,
176  const exprt &op1,
177  const exprt &op2,
178  const bvt &prev_bv,
179  bvt &next_bv)
180 {
181  next_bv=prev_bv;
182 
183  const bvt &op2_bv=convert_bv(op2);
184 
185  const irep_idt &component_name=op1.get(ID_component_name);
186  const struct_typet::componentst &components=
187  type.components();
188 
189  std::size_t offset=0;
190 
191  for(const auto &c : components)
192  {
193  const typet &subtype = c.type();
194 
195  std::size_t sub_width=boolbv_width(subtype);
196 
197  if(c.get_name() == component_name)
198  {
200  subtype == op2.type(),
201  "with/struct: component '" + id2string(component_name) +
202  "' type does not match",
203  irep_pretty_diagnosticst{subtype},
205 
207  sub_width == op2_bv.size(),
208  "convert_with_struct: unexpected operand op2 width",
210 
211  for(std::size_t i=0; i<sub_width; i++)
212  next_bv[offset+i]=op2_bv[i];
213 
214  break; // done
215  }
216 
217  offset+=sub_width;
218  }
219 }
220 
222  const union_typet &type,
223  const exprt &op2,
224  const bvt &prev_bv,
225  bvt &next_bv)
226 {
227  next_bv=prev_bv;
228 
229  const bvt &op2_bv=convert_bv(op2);
230 
232  next_bv.size() >= op2_bv.size(),
233  "convert_with_union: unexpected operand op2 width",
235 
236  endianness_mapt map_u = endianness_map(type);
237  endianness_mapt map_op2 = endianness_map(op2.type());
238 
239  for(std::size_t i = 0; i < op2_bv.size(); i++)
240  next_bv[map_u.map_bit(i)] = op2_bv[map_op2.map_bit(i)];
241 }
with_exprt
Operator to update elements in structs and arrays.
Definition: std_expr.h:2423
to_union_tag_type
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition: c_types.h:202
struct_union_typet::components
const componentst & components() const
Definition: std_types.h:147
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
to_union_type
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition: c_types.h:162
boolbvt::convert_with_array
void convert_with_array(const array_typet &type, const exprt &op1, const exprt &op2, const bvt &prev_bv, bvt &next_bv)
Definition: boolbv_with.cpp:81
mp_integer
BigInt mp_integer
Definition: smt_terms.h:17
arith_tools.h
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
boolbvt::is_unbounded_array
bool is_unbounded_array(const typet &type) const override
Definition: boolbv.cpp:518
typet
The type of an expression, extends irept.
Definition: type.h:28
bvt
std::vector< literalt > bvt
Definition: literal.h:201
boolbvt::convert_with_struct
void convert_with_struct(const struct_typet &type, const exprt &op1, const exprt &op2, const bvt &prev_bv, bvt &next_bv)
Definition: boolbv_with.cpp:174
exprt
Base class for all expressions.
Definition: expr.h:55
struct_union_typet::componentst
std::vector< componentt > componentst
Definition: std_types.h:140
namespace_baset::follow_tag
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
namespace.h
equal_exprt
Equality.
Definition: std_expr.h:1305
irept::get
const irep_idt & get(const irep_idt &name) const
Definition: irep.cpp:45
array_typet::size
const exprt & size() const
Definition: std_types.h:800
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
with_exprt::old
exprt & old()
Definition: std_expr.h:2434
DATA_INVARIANT_WITH_DIAGNOSTICS
#define DATA_INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Definition: invariant.h:511
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:47
boolbvt::boolbv_width
virtual std::size_t boolbv_width(const typet &type) const
Definition: boolbv.h:102
boolbvt::convert_bv
virtual const bvt & convert_bv(const exprt &expr, const optionalt< std::size_t > expected_width={})
Convert expression to vector of literalts, using an internal cache to speed up conversion if availabl...
Definition: boolbv.cpp:39
arrayst::ns
const namespacet & ns
Definition: arrays.h:56
endianness_mapt::map_bit
size_t map_bit(size_t bit) const
Definition: endianness_map.h:47
boolbvt::convert_with_union
void convert_with_union(const union_typet &type, const exprt &op2, const bvt &prev_bv, bvt &next_bv)
Definition: boolbv_with.cpp:221
irept::id
const irep_idt & id() const
Definition: irep.h:396
to_struct_tag_type
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:474
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
union_typet
The union type.
Definition: c_types.h:124
prop_conv_solvert::convert
literalt convert(const exprt &expr) override
Convert a Boolean expression and return the corresponding literal.
Definition: prop_conv_solver.cpp:156
irep_pretty_diagnosticst
Definition: irep.h:502
struct_typet
Structure type, corresponds to C style structs.
Definition: std_types.h:230
array_typet
Arrays with given size.
Definition: std_types.h:762
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:100
boolbvt::convert_with_bv
void convert_with_bv(const exprt &op1, const exprt &op2, const bvt &prev_bv, bvt &next_bv)
Definition: boolbv_with.cpp:144
literalt
Definition: literal.h:25
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
endianness_mapt
Maps a big-endian offset to a little-endian offset.
Definition: endianness_map.h:30
boolbv.h
exprt::operands
operandst & operands()
Definition: expr.h:94
boolbvt::endianness_map
virtual endianness_mapt endianness_map(const typet &type, bool little_endian) const
Definition: boolbv.h:108
std_expr.h
propt::lselect
virtual literalt lselect(literalt a, literalt b, literalt c)=0
c_types.h
prop_conv_solvert::prop
propt & prop
Definition: prop_conv_solver.h:130
boolbvt::convert_with
virtual bvt convert_with(const with_exprt &expr)
Definition: boolbv_with.cpp:16