@@ -21,64 +21,59 @@ Author: Daniel Kroening, kroening@kroening.com
2121static exprt unpack_rec (
2222 const exprt &src,
2323 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,
2626 const namespacet &ns,
2727 bool unpack_byte_array = false );
2828
2929// / Rewrite an array or vector into its individual bytes.
3030// / \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
3334// / \param element_bits: bit width of array/vector elements
3435// / \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
3637// / 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
3839// / unpack
3940// / \param ns: namespace for type lookups
4041// / \return array_exprt holding unpacked elements
4142static array_exprt unpack_array_vector (
4243 const exprt &src,
43- const exprt &src_size,
44+ const optionalt<mp_integer> &src_size,
4445 const mp_integer &element_bits,
4546 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,
4849 const namespacet &ns)
4950{
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 ());
5753
5854 exprt::operandst byte_operands;
5955 mp_integer first_element = 0 ;
6056
6157 // refine the number of elements to extract in case the element width is known
6258 // 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 ;
6460 if (element_bits > 0 && element_bits % 8 == 0 )
6561 {
6662 mp_integer el_bytes = element_bits / 8 ;
6763
68- if (!num_elements)
64+ if (!num_elements. has_value () )
6965 {
7066 // 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;
7268 }
7369
74- if (auto offset_bytes_int = numeric_cast<mp_integer>( offset_bytes))
70+ if (offset_bytes. has_value ( ))
7571 {
7672 // compute offset as number of elements
77- first_element = *offset_bytes_int / el_bytes;
73+ first_element = *offset_bytes / el_bytes;
7874 // insert offset_bytes-many nil bytes into the output array
79- *offset_bytes_int -= *offset_bytes_int % el_bytes;
8075 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) ),
8277 from_integer (0 , unsignedbv_typet (8 )));
8378 }
8479 }
@@ -87,7 +82,7 @@ static array_exprt unpack_array_vector(
8782 // array/vector is unknown; if element_bits was usable above this will
8883 // have been turned into a number of elements already
8984 if (!num_elements)
90- num_elements = *max_elements ;
85+ num_elements = *max_bytes ;
9186
9287 const exprt src_simp = simplify_expr (src, ns);
9388
@@ -109,8 +104,7 @@ static array_exprt unpack_array_vector(
109104
110105 // recursively unpack each element until so that we eventually just have an
111106 // 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 );
114108 byte_operands.insert (
115109 byte_operands.end (), sub.operands ().begin (), sub.operands ().end ());
116110 }
@@ -124,22 +118,22 @@ static array_exprt unpack_array_vector(
124118// / Rewrite an object into its individual bytes.
125119// / \param src: object to unpack
126120// / \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
130124// / unpack
131125// / \param ns: namespace for type lookups
132126// / \param unpack_byte_array: if true, return unmodified \p src iff it is an
133127// array of bytes
134128// / \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
136130// / object because of either non constant size, byte misalignment or
137131// / non-constant component width.
138132static exprt unpack_rec (
139133 const exprt &src,
140134 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,
143137 const namespacet &ns,
144138 bool unpack_byte_array)
145139{
@@ -154,9 +148,11 @@ static exprt unpack_rec(
154148 if (!unpack_byte_array && *element_bits == 8 )
155149 return src;
156150
151+ const auto constant_size_or_nullopt =
152+ numeric_cast<mp_integer>(array_type.size ());
157153 return unpack_array_vector (
158154 src,
159- array_type. size () ,
155+ constant_size_or_nullopt ,
160156 *element_bits,
161157 little_endian,
162158 offset_bytes,
@@ -176,7 +172,7 @@ static exprt unpack_rec(
176172
177173 return unpack_array_vector (
178174 src,
179- vector_type.size (),
175+ numeric_cast_v<mp_integer>( vector_type.size () ),
180176 *element_bits,
181177 little_endian,
182178 offset_bytes,
@@ -203,29 +199,22 @@ static exprt unpack_rec(
203199 throw non_byte_alignedt (struct_type, comp, *component_bits);
204200 }
205201
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;
210204
211- if (offset_in_member_int .has_value ())
205+ if (offset_bytes .has_value ())
212206 {
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
215209 // 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 ();
221212 }
222213
223- if (max_bytes_left_int .has_value ())
214+ if (max_bytes .has_value ())
224215 {
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 )
229218 break ;
230219 }
231220
@@ -256,16 +245,10 @@ static exprt unpack_rec(
256245
257246 if (bits_opt.has_value ())
258247 bits = *bits_opt;
248+ else if (max_bytes.has_value ())
249+ bits = *max_bytes * 8 ;
259250 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 ());
269252
270253 exprt::operandst byte_operands;
271254 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)
352335 // determine an upper bound of the number of bytes we might need
353336 exprt upper_bound=size_of_expr (src.type (), ns);
354337 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);
361343
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);
365346
366347 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);
368354
369355 if (src.type ().id ()==ID_array)
370356 {
0 commit comments