CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
boolbv_with.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
9#include <util/arith_tools.h>
10#include <util/bitvector_expr.h>
11#include <util/c_types.h>
12#include <util/namespace.h>
13#include <util/std_expr.h>
14
15#include "boolbv.h"
16
18{
19 auto &type = expr.type();
20
21 if(
22 type.id() == ID_bv || type.id() == ID_unsignedbv ||
23 type.id() == ID_signedbv)
24 {
25 if(expr.operands().size() > 3)
26 {
27 std::size_t s = expr.operands().size();
28
29 // strip off the trailing two operands
30 with_exprt tmp = expr;
31 tmp.operands().resize(s - 2);
32
34 tmp, expr.operands()[s - 2], expr.operands().back());
35
36 // recursive call
38 }
39
40 PRECONDITION(expr.operands().size() == 3);
41 if(expr.new_value().type().id() == ID_bool)
42 {
43 return convert_bv(
44 update_bit_exprt(expr.old(), expr.where(), expr.new_value()));
45 }
46 else
47 {
48 return convert_bv(
49 update_bits_exprt(expr.old(), expr.where(), expr.new_value()));
50 }
51 }
52
53 bvt bv = convert_bv(expr.old());
54
55 std::size_t width = boolbv_width(type);
56
57 if(width==0)
58 {
59 // A zero-length array is acceptable:
60 return bvt{};
61 }
62
64 bv.size() == width,
65 "unexpected operand 0 width",
67
69 prev_bv.resize(width);
70
71 const exprt::operandst &ops=expr.operands();
72
73 for(std::size_t op_no=1; op_no<ops.size(); op_no+=2)
74 {
75 bv.swap(prev_bv);
76
77 convert_with(expr.old().type(), ops[op_no], ops[op_no + 1], prev_bv, bv);
78 }
79
80 return bv;
81}
82
84 const typet &type,
85 const exprt &where,
86 const exprt &new_value,
87 const bvt &prev_bv,
88 bvt &next_bv)
89{
90 // we only do that on arrays, bitvectors, structs, and unions
91
92 next_bv.resize(prev_bv.size());
93
94 if(type.id()==ID_array)
95 return convert_with_array(
96 to_array_type(type), where, new_value, prev_bv, next_bv);
97 else if(type.id()==ID_bv ||
98 type.id()==ID_unsignedbv ||
99 type.id()==ID_signedbv)
100 {
101 // already done
102 PRECONDITION(false);
103 }
104 else if(type.id()==ID_struct)
105 return convert_with_struct(
106 to_struct_type(type), where, new_value, prev_bv, next_bv);
107 else if(type.id() == ID_struct_tag)
108 return convert_with(
109 ns.follow_tag(to_struct_tag_type(type)),
110 where,
111 new_value,
112 prev_bv,
113 next_bv);
114 else if(type.id()==ID_union)
115 return convert_with_union(to_union_type(type), new_value, prev_bv, next_bv);
116 else if(type.id() == ID_union_tag)
117 return convert_with(
118 ns.follow_tag(to_union_tag_type(type)),
119 where,
120 new_value,
121 prev_bv,
122 next_bv);
123
125 false, "unexpected with type", irep_pretty_diagnosticst{type});
126}
127
129 const array_typet &type,
130 const exprt &index,
131 const exprt &new_value,
132 const bvt &prev_bv,
133 bvt &next_bv)
134{
135 // can't do this
137 !is_unbounded_array(type),
138 "convert_with_array called for unbounded array",
140
141 const exprt &array_size=type.size();
142
143 const auto size = numeric_cast<mp_integer>(array_size);
144
146 size.has_value(),
147 "convert_with_array expects constant array size",
149
150 const bvt &new_value_bv = convert_bv(new_value);
151
153 *size * new_value_bv.size() == prev_bv.size(),
154 "convert_with_array: unexpected new_value operand width",
156
157 // Is the index a constant?
158 if(const auto index_value_opt = numeric_cast<mp_integer>(index))
159 {
160 // Yes, it is!
162
163 if(*index_value_opt >= 0 && *index_value_opt < *size) // bounds check
164 {
165 const std::size_t offset =
167
168 for(std::size_t j = 0; j < new_value_bv.size(); j++)
169 next_bv[offset + j] = new_value_bv[j];
170 }
171
172 return;
173 }
174
175 typet counter_type = index.type();
176
177 for(mp_integer i=0; i<size; i=i+1)
178 {
179 exprt counter=from_integer(i, counter_type);
180
181 literalt eq_lit = convert(equal_exprt(index, counter));
182
183 const std::size_t offset =
185
186 for(std::size_t j = 0; j < new_value_bv.size(); j++)
187 next_bv[offset + j] =
188 prop.lselect(eq_lit, new_value_bv[j], prev_bv[offset + j]);
189 }
190}
191
193 const struct_typet &type,
194 const exprt &where,
195 const exprt &new_value,
196 const bvt &prev_bv,
197 bvt &next_bv)
198{
200
201 const bvt &new_value_bv = convert_bv(new_value);
202
203 const irep_idt &component_name = where.get(ID_component_name);
204 const struct_typet::componentst &components=
205 type.components();
206
207 std::size_t offset=0;
208
209 for(const auto &c : components)
210 {
211 const typet &subtype = c.type();
212
213 std::size_t sub_width=boolbv_width(subtype);
214
215 if(c.get_name() == component_name)
216 {
218 subtype == new_value.type(),
219 "with/struct: component '" + id2string(component_name) +
220 "' type does not match",
222 irep_pretty_diagnosticst{new_value.type()});
223
225 sub_width == new_value_bv.size(),
226 "convert_with_struct: unexpected new_value operand width",
228
229 for(std::size_t i=0; i<sub_width; i++)
230 next_bv[offset + i] = new_value_bv[i];
231
232 break; // done
233 }
234
235 offset+=sub_width;
236 }
237}
238
240 const union_typet &type,
241 const exprt &new_value,
242 const bvt &prev_bv,
243 bvt &next_bv)
244{
246
247 const bvt &new_value_bv = convert_bv(new_value);
248
250 next_bv.size() >= new_value_bv.size(),
251 "convert_with_union: unexpected new_value operand width",
253
256
257 for(std::size_t i = 0; i < new_value_bv.size(); i++)
258 next_bv[map_u.map_bit(i)] = new_value_bv[map_new_value.map_bit(i)];
259}
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
API to expression classes for bitvectors.
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition c_types.h:184
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition c_types.h:224
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Arrays with given size.
Definition std_types.h:807
const exprt & size() const
Definition std_types.h:840
const namespacet & ns
Definition arrays.h:56
virtual bvt convert_with(const with_exprt &expr)
virtual const bvt & convert_bv(const exprt &expr, const std::optional< 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
void convert_with_array(const array_typet &type, const exprt &index, const exprt &new_value, const bvt &prev_bv, bvt &next_bv)
bool is_unbounded_array(const typet &type) const override
Definition boolbv.cpp:538
void convert_with_union(const union_typet &type, const exprt &new_value, const bvt &prev_bv, bvt &next_bv)
virtual endianness_mapt endianness_map(const typet &type, bool little_endian) const
Definition boolbv.h:109
virtual std::size_t boolbv_width(const typet &type) const
Definition boolbv.h:103
void convert_with_struct(const struct_typet &type, const exprt &where, const exprt &new_value, const bvt &prev_bv, bvt &next_bv)
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Maps a big-endian offset to a little-endian offset.
Equality.
Definition std_expr.h:1366
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
operandst & operands()
Definition expr.h:94
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:44
const irep_idt & id() const
Definition irep.h:388
literalt convert(const exprt &expr) override
Convert a Boolean expression and return the corresponding literal.
virtual literalt lselect(literalt a, literalt b, literalt c)=0
Structure type, corresponds to C style structs.
Definition std_types.h:231
const componentst & components() const
Definition std_types.h:147
std::vector< componentt > componentst
Definition std_types.h:140
The type of an expression, extends irept.
Definition type.h:29
The union type.
Definition c_types.h:147
Replaces a sub-range of a bit-vector operand.
Replaces a sub-range of a bit-vector operand.
Operator to update elements in structs and arrays.
Definition std_expr.h:2598
exprt & new_value()
Definition std_expr.h:2628
exprt & where()
Definition std_expr.h:2618
exprt & old()
Definition std_expr.h:2608
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
std::vector< literalt > bvt
Definition literal.h:201
BigInt mp_integer
Definition smt_terms.h:17
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define DATA_INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Definition invariant.h:535
API to expression classes.
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:308
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition std_types.h:518
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888