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<mp_integer> &offset_bytes,
25
+ const optionalt<mp_integer> &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<mp_integer> &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<mp_integer> &offset_bytes,
48
+ const optionalt<mp_integer> &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 = src_size ;
64
60
if (element_bits > 0 && element_bits % 8 == 0 )
65
61
{
66
62
mp_integer el_bytes = element_bits / 8 ;
67
63
68
- if (!num_elements)
64
+ if (!num_elements. has_value () )
69
65
{
70
66
// turn bytes into elements, rounding up
71
- max_elements = (*max_bytes_int + el_bytes - 1 ) / el_bytes;
67
+ num_elements = (*max_bytes + el_bytes - 1 ) / el_bytes;
72
68
}
73
69
74
- if (auto offset_bytes_int = numeric_cast<mp_integer>( offset_bytes))
70
+ if (offset_bytes. has_value ( ))
75
71
{
76
72
// compute offset as number of elements
77
- first_element = *offset_bytes_int / el_bytes;
73
+ first_element = *offset_bytes / el_bytes;
78
74
// insert offset_bytes-many nil bytes into the output array
79
- *offset_bytes_int -= *offset_bytes_int % el_bytes;
80
75
byte_operands.resize (
81
- numeric_cast_v<std::size_t >(*offset_bytes_int ),
76
+ numeric_cast_v<std::size_t >(*offset_bytes - (*offset_bytes % el_bytes) ),
82
77
from_integer (0 , unsignedbv_typet (8 )));
83
78
}
84
79
}
@@ -87,7 +82,7 @@ static array_exprt unpack_array_vector(
87
82
// array/vector is unknown; if element_bits was usable above this will
88
83
// have been turned into a number of elements already
89
84
if (!num_elements)
90
- num_elements = *max_elements ;
85
+ num_elements = *max_bytes ;
91
86
92
87
const exprt src_simp = simplify_expr (src, ns);
93
88
@@ -109,8 +104,7 @@ static array_exprt unpack_array_vector(
109
104
110
105
// recursively unpack each element until so that we eventually just have an
111
106
// array of bytes left
112
- exprt sub =
113
- unpack_rec (element, little_endian, nil_exprt (), max_bytes, ns, true );
107
+ exprt sub = unpack_rec (element, little_endian, {}, max_bytes, ns, true );
114
108
byte_operands.insert (
115
109
byte_operands.end (), sub.operands ().begin (), sub.operands ().end ());
116
110
}
@@ -124,22 +118,22 @@ static array_exprt unpack_array_vector(
124
118
// / Rewrite an object into its individual bytes.
125
119
// / \param src: object to unpack
126
120
// / \param little_endian: true, iff assumed endianness is little-endian
127
- // / \param offset_bytes: if not nil , bytes prior to this offset will be filled
128
- // / with nil values
129
- // / \param max_bytes: if not nil , use as upper bound of the number of bytes to
121
+ // / \param offset_bytes: if set , bytes prior to this offset will be filled with
122
+ // / nil values
123
+ // / \param max_bytes: if set , use as upper bound of the number of bytes to
130
124
// / unpack
131
125
// / \param ns: namespace for type lookups
132
126
// / \param unpack_byte_array: if true, return unmodified \p src iff it is an
133
127
// array of bytes
134
128
// / \return array of bytes in the sequence found in memory
135
- // / \throws flatten_byte_extract_exceptiont Raised is unable to unpack the
129
+ // / \throws flatten_byte_extract_exceptiont Raised if unable to unpack the
136
130
// / object because of either non constant size, byte misalignment or
137
131
// / non-constant component width.
138
132
static exprt unpack_rec (
139
133
const exprt &src,
140
134
bool little_endian,
141
- const exprt &offset_bytes,
142
- const exprt &max_bytes,
135
+ const optionalt<mp_integer> &offset_bytes,
136
+ const optionalt<mp_integer> &max_bytes,
143
137
const namespacet &ns,
144
138
bool unpack_byte_array)
145
139
{
@@ -154,9 +148,11 @@ static exprt unpack_rec(
154
148
if (!unpack_byte_array && *element_bits == 8 )
155
149
return src;
156
150
151
+ const auto constant_size_or_nullopt =
152
+ numeric_cast<mp_integer>(array_type.size ());
157
153
return unpack_array_vector (
158
154
src,
159
- array_type. size () ,
155
+ constant_size_or_nullopt ,
160
156
*element_bits,
161
157
little_endian,
162
158
offset_bytes,
@@ -176,7 +172,7 @@ static exprt unpack_rec(
176
172
177
173
return unpack_array_vector (
178
174
src,
179
- vector_type.size (),
175
+ numeric_cast_v<mp_integer>( vector_type.size () ),
180
176
*element_bits,
181
177
little_endian,
182
178
offset_bytes,
@@ -203,29 +199,22 @@ static exprt unpack_rec(
203
199
throw non_byte_alignedt (struct_type, comp, *component_bits);
204
200
}
205
201
206
- exprt offset_in_member = nil_exprt ();
207
- auto offset_in_member_int = numeric_cast<mp_integer>(offset_bytes);
208
- exprt max_bytes_left = nil_exprt ();
209
- auto max_bytes_left_int = numeric_cast<mp_integer>(max_bytes);
202
+ optionalt<mp_integer> offset_in_member;
203
+ optionalt<mp_integer> max_bytes_left;
210
204
211
- if (offset_in_member_int .has_value ())
205
+ if (offset_bytes .has_value ())
212
206
{
213
- *offset_in_member_int -= member_offset_bits / 8 ;
214
- // if the offset is negative, offset_in_member remains nil , which has
207
+ offset_in_member = *offset_bytes - member_offset_bits / 8 ;
208
+ // if the offset is negative, offset_in_member remains unset , which has
215
209
// the same effect as setting it to zero
216
- if (*offset_in_member_int >= 0 )
217
- {
218
- offset_in_member =
219
- from_integer (*offset_in_member_int, offset_bytes.type ());
220
- }
210
+ if (*offset_in_member < 0 )
211
+ offset_in_member.reset ();
221
212
}
222
213
223
- if (max_bytes_left_int .has_value ())
214
+ if (max_bytes .has_value ())
224
215
{
225
- *max_bytes_left_int -= member_offset_bits / 8 ;
226
- if (*max_bytes_left_int >= 0 )
227
- max_bytes_left = from_integer (*max_bytes_left_int, max_bytes.type ());
228
- else
216
+ max_bytes_left = *max_bytes - member_offset_bits / 8 ;
217
+ if (*max_bytes_left < 0 )
229
218
break ;
230
219
}
231
220
@@ -256,16 +245,10 @@ static exprt unpack_rec(
256
245
257
246
if (bits_opt.has_value ())
258
247
bits = *bits_opt;
248
+ else if (max_bytes.has_value ())
249
+ bits = *max_bytes * 8 ;
259
250
else
260
- {
261
- bits_opt = numeric_cast<mp_integer>(max_bytes);
262
- if (!bits_opt.has_value ())
263
- {
264
- throw non_constant_widtht (src, max_bytes);
265
- }
266
- else
267
- bits = *bits_opt * 8 ;
268
- }
251
+ throw non_constant_widtht (src, nil_exprt ());
269
252
270
253
exprt::operandst byte_operands;
271
254
for (mp_integer i=0 ; i<bits; i+=8 )
@@ -352,19 +335,22 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
352
335
// determine an upper bound of the number of bytes we might need
353
336
exprt upper_bound=size_of_expr (src.type (), ns);
354
337
if (upper_bound.is_not_nil ())
355
- upper_bound=
356
- simplify_expr (
357
- plus_exprt (
358
- upper_bound,
359
- typecast_exprt (src.offset (), upper_bound.type ())),
360
- ns);
338
+ upper_bound = simplify_expr (
339
+ plus_exprt (
340
+ upper_bound,
341
+ typecast_exprt::conditional_cast (src.offset (), upper_bound.type ())),
342
+ ns);
361
343
362
- exprt lb = src.offset ();
363
- if (!lb.is_constant ())
364
- lb.make_nil ();
344
+ const auto lower_bound_or_nullopt = numeric_cast<mp_integer>(src.offset ());
345
+ const auto upper_bound_or_nullopt = numeric_cast<mp_integer>(upper_bound);
365
346
366
347
byte_extract_exprt unpacked (src);
367
- unpacked.op () = unpack_rec (src.op (), little_endian, lb, upper_bound, ns);
348
+ unpacked.op () = unpack_rec (
349
+ src.op (),
350
+ little_endian,
351
+ lower_bound_or_nullopt,
352
+ upper_bound_or_nullopt,
353
+ ns);
368
354
369
355
if (src.type ().id ()==ID_array)
370
356
{
0 commit comments