21
21
static exprt unpack_rec (
22
22
const exprt &src,
23
23
bool little_endian,
24
- const exprt &offset_bytes,
25
- const exprt &max_bytes,
24
+ const optionalt<constant_exprt> &offset_bytes,
25
+ const optionalt<constant_exprt> &max_bytes,
26
26
const namespacet &ns,
27
27
bool unpack_byte_array = false );
28
28
29
29
// / Rewrite an array or vector into its individual bytes.
30
30
// / \param src: array/vector to unpack
31
- // / \param src_size: array/vector size; if not a constant, \p max_bytes must be
32
- // / a constant value, otherwise we fail with an exception
31
+ // / \param src_size: array/vector size; if not a constant and thus not set,
32
+ // / \p max_bytes must be a known constant value, otherwise we fail with an
33
+ // / exception
33
34
// / \param element_bits: bit width of array/vector elements
34
35
// / \param little_endian: true, iff assumed endianness is little-endian
35
- // / \param offset_bytes: if not nil , bytes prior to this offset will be filled
36
+ // / \param offset_bytes: if set , bytes prior to this offset will be filled
36
37
// / with nil values
37
- // / \param max_bytes: if not nil , use as upper bound of the number of bytes to
38
+ // / \param max_bytes: if set , use as upper bound of the number of bytes to
38
39
// / unpack
39
40
// / \param ns: namespace for type lookups
40
41
// / \return array_exprt holding unpacked elements
41
42
static array_exprt unpack_array_vector (
42
43
const exprt &src,
43
- const exprt &src_size,
44
+ const optionalt<constant_exprt> &src_size,
44
45
const mp_integer &element_bits,
45
46
bool little_endian,
46
- const exprt &offset_bytes,
47
- const exprt &max_bytes,
47
+ const optionalt<constant_exprt> &offset_bytes,
48
+ const optionalt<constant_exprt> &max_bytes,
48
49
const namespacet &ns)
49
50
{
50
- auto max_bytes_int = numeric_cast<mp_integer>(max_bytes);
51
- auto num_elements = numeric_cast<mp_integer>(src_size);
52
-
53
- if (!max_bytes_int && !num_elements)
54
- {
55
- throw non_const_array_sizet (src.type (), max_bytes);
56
- }
51
+ if (!src_size.has_value () && !max_bytes.has_value ())
52
+ throw non_const_array_sizet (src.type (), nil_exprt ());
57
53
58
54
exprt::operandst byte_operands;
59
55
mp_integer first_element = 0 ;
60
56
61
57
// refine the number of elements to extract in case the element width is known
62
58
// and a multiple of bytes; otherwise we will expand the entire array/vector
63
- optionalt<mp_integer> max_elements;
59
+ optionalt<mp_integer> num_elements;
60
+ if (src_size.has_value ())
61
+ num_elements = numeric_cast<mp_integer>(*src_size);
64
62
if (element_bits > 0 && element_bits % 8 == 0 )
65
63
{
66
64
mp_integer el_bytes = element_bits / 8 ;
@@ -69,17 +67,19 @@ static array_exprt unpack_array_vector(
69
67
if (!num_elements)
70
68
{
71
69
// round up to nearest multiple of el_bytes
72
- max_elements = (*max_bytes_int + el_bytes - 1 ) / el_bytes;
70
+ auto max_bytes_int = numeric_cast_v<mp_integer>(*max_bytes);
71
+ num_elements = (max_bytes_int + el_bytes - 1 ) / el_bytes;
73
72
}
74
73
75
- if (auto offset_bytes_int = numeric_cast<mp_integer>( offset_bytes))
74
+ if (offset_bytes. has_value ( ))
76
75
{
76
+ auto offset_bytes_int = numeric_cast_v<mp_integer>(*offset_bytes);
77
77
// compute offset as number of elements
78
- first_element = * offset_bytes_int / el_bytes;
78
+ first_element = offset_bytes_int / el_bytes;
79
79
// insert offset_bytes-many nil bytes into the output array
80
- * offset_bytes_int -= * offset_bytes_int % el_bytes;
80
+ offset_bytes_int -= offset_bytes_int % el_bytes;
81
81
byte_operands.resize (
82
- numeric_cast_v<std::size_t >(* offset_bytes_int),
82
+ numeric_cast_v<std::size_t >(offset_bytes_int),
83
83
from_integer (0 , unsignedbv_typet (8 )));
84
84
}
85
85
}
@@ -88,7 +88,7 @@ static array_exprt unpack_array_vector(
88
88
// array/vector is unknown; if element_bits was usable above this will
89
89
// have been turned into a number of elements already
90
90
if (!num_elements)
91
- num_elements = *max_elements ;
91
+ num_elements = numeric_cast_v<mp_integer>(*max_bytes) ;
92
92
93
93
const exprt src_simp = simplify_expr (src, ns);
94
94
@@ -111,7 +111,7 @@ static array_exprt unpack_array_vector(
111
111
// recursively unpack each element until so that we eventually just have an
112
112
// array of bytes left
113
113
exprt sub =
114
- unpack_rec (element, little_endian, nil_exprt () , max_bytes, ns, true );
114
+ unpack_rec (element, little_endian, nullopt , max_bytes, ns, true );
115
115
byte_operands.insert (
116
116
byte_operands.end (), sub.operands ().begin (), sub.operands ().end ());
117
117
}
@@ -125,22 +125,22 @@ static array_exprt unpack_array_vector(
125
125
// / Rewrite an object into its individual bytes.
126
126
// / \param src: object to unpack
127
127
// / \param little_endian: true, iff assumed endianness is little-endian
128
- // / \param offset_bytes: if not nil , bytes prior to this offset will be filled
129
- // / with nil values
130
- // / \param max_bytes: if not nil , use as upper bound of the number of bytes to
128
+ // / \param offset_bytes: if set , bytes prior to this offset will be filled with
129
+ // / nil values
130
+ // / \param max_bytes: if set , use as upper bound of the number of bytes to
131
131
// / unpack
132
132
// / \param ns: namespace for type lookups
133
133
// / \param unpack_byte_array: if true, return unmodified \p src iff it is an
134
134
// array of bytes
135
135
// / \return array of bytes in the sequence found in memory
136
- // / \throws flatten_byte_extract_exceptiont Raised is unable to unpack the
136
+ // / \throws flatten_byte_extract_exceptiont Raised if unable to unpack the
137
137
// / object because of either non constant size, byte misalignment or
138
138
// / non-constant component width.
139
139
static exprt unpack_rec (
140
140
const exprt &src,
141
141
bool little_endian,
142
- const exprt &offset_bytes,
143
- const exprt &max_bytes,
142
+ const optionalt<constant_exprt> &offset_bytes,
143
+ const optionalt<constant_exprt> &max_bytes,
144
144
const namespacet &ns,
145
145
bool unpack_byte_array)
146
146
{
@@ -155,9 +155,11 @@ static exprt unpack_rec(
155
155
if (!unpack_byte_array && *element_bits == 8 )
156
156
return src;
157
157
158
+ const auto constant_size_or_nullopt =
159
+ expr_try_dynamic_cast<constant_exprt>(exprt (array_type.size ()));
158
160
return unpack_array_vector (
159
161
src,
160
- array_type. size () ,
162
+ constant_size_or_nullopt ,
161
163
*element_bits,
162
164
little_endian,
163
165
offset_bytes,
@@ -204,28 +206,28 @@ static exprt unpack_rec(
204
206
throw non_byte_alignedt (struct_type, comp, *component_bits);
205
207
}
206
208
207
- exprt offset_in_member = nil_exprt ();
208
- auto offset_in_member_int = numeric_cast<mp_integer>(offset_bytes);
209
- exprt max_bytes_left = nil_exprt ();
210
- auto max_bytes_left_int = numeric_cast<mp_integer>(max_bytes);
209
+ optionalt<constant_exprt> offset_in_member;
210
+ optionalt<constant_exprt> max_bytes_left;
211
211
212
- if (offset_in_member_int .has_value ())
212
+ if (offset_bytes .has_value ())
213
213
{
214
- *offset_in_member_int -= member_offset_bits / 8 ;
214
+ auto offset_in_member_int = numeric_cast_v<mp_integer>(*offset_bytes);
215
+ offset_in_member_int -= member_offset_bits / 8 ;
215
216
// if the offset is negative, offset_in_member remains nil, which has
216
217
// the same effect as setting it to zero
217
- if (* offset_in_member_int >= 0 )
218
+ if (offset_in_member_int >= 0 )
218
219
{
219
220
offset_in_member =
220
- from_integer (* offset_in_member_int, offset_bytes. type ());
221
+ from_integer (offset_in_member_int, offset_bytes-> type ());
221
222
}
222
223
}
223
224
224
- if (max_bytes_left_int .has_value ())
225
+ if (max_bytes .has_value ())
225
226
{
226
- *max_bytes_left_int -= member_offset_bits / 8 ;
227
- if (*max_bytes_left_int >= 0 )
228
- max_bytes_left = from_integer (*max_bytes_left_int, max_bytes.type ());
227
+ auto max_bytes_left_int = numeric_cast_v<mp_integer>(*max_bytes);
228
+ max_bytes_left_int -= member_offset_bits / 8 ;
229
+ if (max_bytes_left_int >= 0 )
230
+ max_bytes_left = from_integer (max_bytes_left_int, max_bytes->type ());
229
231
else
230
232
break ;
231
233
}
@@ -257,16 +259,10 @@ static exprt unpack_rec(
257
259
258
260
if (bits_opt.has_value ())
259
261
bits = *bits_opt;
262
+ else if (max_bytes.has_value ())
263
+ bits = numeric_cast_v<mp_integer>(*max_bytes) * 8 ;
260
264
else
261
- {
262
- bits_opt = numeric_cast<mp_integer>(max_bytes);
263
- if (!bits_opt.has_value ())
264
- {
265
- throw non_constant_widtht (src, max_bytes);
266
- }
267
- else
268
- bits = *bits_opt * 8 ;
269
- }
265
+ throw non_constant_widtht (src, nil_exprt ());
270
266
271
267
exprt::operandst byte_operands;
272
268
for (mp_integer i=0 ; i<bits; i+=8 )
@@ -353,19 +349,24 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
353
349
// determine an upper bound of the number of bytes we might need
354
350
exprt upper_bound=size_of_expr (src.type (), ns);
355
351
if (upper_bound.is_not_nil ())
356
- upper_bound=
357
- simplify_expr (
358
- plus_exprt (
359
- upper_bound,
360
- typecast_exprt (src.offset (), upper_bound.type ())),
361
- ns);
352
+ upper_bound = simplify_expr (
353
+ plus_exprt (
354
+ upper_bound,
355
+ typecast_exprt::conditional_cast (src.offset (), upper_bound.type ())),
356
+ ns);
362
357
363
- exprt lb = src.offset ();
364
- if (!lb.is_constant ())
365
- lb.make_nil ();
358
+ const auto lower_bound_or_nullopt =
359
+ expr_try_dynamic_cast<constant_exprt>(exprt (src.offset ()));
360
+ const auto upper_bound_or_nullopt =
361
+ expr_try_dynamic_cast<constant_exprt>(std::move (upper_bound));
366
362
367
363
byte_extract_exprt unpacked (src);
368
- unpacked.op () = unpack_rec (src.op (), little_endian, lb, upper_bound, ns);
364
+ unpacked.op () = unpack_rec (
365
+ src.op (),
366
+ little_endian,
367
+ lower_bound_or_nullopt,
368
+ upper_bound_or_nullopt,
369
+ ns);
369
370
370
371
if (src.type ().id ()==ID_array)
371
372
{
0 commit comments