CBMC
Loading...
Searching...
No Matches
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{
20 expr.operands().size() == 3,
21 "with_exprt with more than 3 operands should no longer exist");
22
23 auto &type = expr.type();
24
25 if(
26 type.id() == ID_bv || type.id() == ID_unsignedbv ||
27 type.id() == ID_signedbv)
28 {
29 if(expr.new_value().type().id() == ID_bool)
30 {
31 return convert_bv(
32 update_bit_exprt(expr.old(), expr.where(), expr.new_value()));
33 }
34 else
35 {
36 return convert_bv(
37 update_bits_exprt(expr.old(), expr.where(), expr.new_value()));
38 }
39 }
40
41 bvt bv_old = convert_bv(expr.old());
42
43 std::size_t width = boolbv_width(type);
44
45 if(width==0)
46 {
47 // A zero-length array is acceptable:
48 return bvt{};
49 }
50
52 bv_old.size() == width,
53 "unexpected operand 0 width",
55
56 bvt bv;
57 bv.resize(width);
58
59 convert_with(expr.old().type(), expr.where(), expr.new_value(), bv_old, bv);
60
61 return bv;
62}
63
65 const typet &type,
66 const exprt &where,
67 const exprt &new_value,
68 const bvt &prev_bv,
69 bvt &next_bv)
70{
71 // we only do that on arrays, bitvectors, structs, and unions
72
73 next_bv.resize(prev_bv.size());
74
75 if(type.id()==ID_array)
76 return convert_with_array(
77 to_array_type(type), where, new_value, prev_bv, next_bv);
78 else if(type.id()==ID_bv ||
79 type.id()==ID_unsignedbv ||
80 type.id()==ID_signedbv)
81 {
82 // already done
83 PRECONDITION(false);
84 }
85 else if(type.id()==ID_struct)
87 to_struct_type(type), where, new_value, prev_bv, next_bv);
88 else if(type.id() == ID_struct_tag)
89 return convert_with(
90 ns.follow_tag(to_struct_tag_type(type)),
91 where,
92 new_value,
93 prev_bv,
94 next_bv);
95 else if(type.id()==ID_union)
96 return convert_with_union(to_union_type(type), new_value, prev_bv, next_bv);
97 else if(type.id() == ID_union_tag)
98 return convert_with(
99 ns.follow_tag(to_union_tag_type(type)),
100 where,
101 new_value,
102 prev_bv,
103 next_bv);
104
106 false, "unexpected with type", irep_pretty_diagnosticst{type});
107}
108
110 const array_typet &type,
111 const exprt &index,
112 const exprt &new_value,
113 const bvt &prev_bv,
114 bvt &next_bv)
115{
116 // can't do this
118 !is_unbounded_array(type),
119 "convert_with_array called for unbounded array",
121
122 const exprt &array_size=type.size();
123
124 const auto size = numeric_cast<mp_integer>(array_size);
125
127 size.has_value(),
128 "convert_with_array expects constant array size",
130
131 const bvt &new_value_bv = convert_bv(new_value);
132
134 *size * new_value_bv.size() == prev_bv.size(),
135 "convert_with_array: unexpected new_value operand width",
137
138 // Is the index a constant?
139 if(const auto index_value_opt = numeric_cast<mp_integer>(index))
140 {
141 // Yes, it is!
143
144 if(*index_value_opt >= 0 && *index_value_opt < *size) // bounds check
145 {
146 const std::size_t offset =
148
149 for(std::size_t j = 0; j < new_value_bv.size(); j++)
150 next_bv[offset + j] = new_value_bv[j];
151 }
152
153 return;
154 }
155
156 typet counter_type = index.type();
157
158 for(mp_integer i=0; i<size; i=i+1)
159 {
160 exprt counter=from_integer(i, counter_type);
161
162 literalt eq_lit = convert(equal_exprt(index, counter));
163
164 const std::size_t offset =
166
167 for(std::size_t j = 0; j < new_value_bv.size(); j++)
168 next_bv[offset + j] =
169 prop.lselect(eq_lit, new_value_bv[j], prev_bv[offset + j]);
170 }
171}
172
174 const struct_typet &type,
175 const exprt &where,
176 const exprt &new_value,
177 const bvt &prev_bv,
178 bvt &next_bv)
179{
181
182 const bvt &new_value_bv = convert_bv(new_value);
183
184 const irep_idt &component_name = where.get(ID_component_name);
185 const struct_typet::componentst &components=
186 type.components();
187
188 std::size_t offset=0;
189
190 for(const auto &c : components)
191 {
192 const typet &subtype = c.type();
193
194 std::size_t sub_width=boolbv_width(subtype);
195
196 if(c.get_name() == component_name)
197 {
199 subtype == new_value.type(),
200 "with/struct: component '" + id2string(component_name) +
201 "' type does not match",
203 irep_pretty_diagnosticst{new_value.type()});
204
206 sub_width == new_value_bv.size(),
207 "convert_with_struct: unexpected new_value operand width",
209
210 for(std::size_t i=0; i<sub_width; i++)
211 next_bv[offset + i] = new_value_bv[i];
212
213 break; // done
214 }
215
216 offset+=sub_width;
217 }
218}
219
221 const union_typet &type,
222 const exprt &new_value,
223 const bvt &prev_bv,
224 bvt &next_bv)
225{
227
228 const bvt &new_value_bv = convert_bv(new_value);
229
231 next_bv.size() >= new_value_bv.size(),
232 "convert_with_union: unexpected new_value operand width",
234
237
238 for(std::size_t i = 0; i < new_value_bv.size(); i++)
239 next_bv[map_u.map_bit(i)] = new_value_bv[map_new_value.map_bit(i)];
240}
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
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:2603
exprt & new_value()
Definition std_expr.h:2633
exprt & where()
Definition std_expr.h:2623
exprt & old()
Definition std_expr.h:2613
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 DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#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