Skip to content

Commit fe4e10c

Browse files
authored
Merge pull request #6476 from tautschnig/refactor-array-unpack
Byte-operator lowering: Factor out unbounded array unpacking
2 parents 2743d87 + b9f4a36 commit fe4e10c

File tree

1 file changed

+58
-41
lines changed

1 file changed

+58
-41
lines changed

src/solvers/lowering/byte_operators.cpp

Lines changed: 58 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,59 @@ static exprt::operandst instantiate_byte_array(
418418
return bytes;
419419
}
420420

421+
/// Rewrite an array or vector into its individual bytes when no maximum number
422+
/// of bytes is known.
423+
/// \param src: array/vector to unpack
424+
/// \param el_bytes: byte width of array/vector elements
425+
/// \param little_endian: true, iff assumed endianness is little-endian
426+
/// \param ns: namespace for type lookups
427+
/// \return Array expression holding unpacked elements or array comprehension
428+
static exprt unpack_array_vector_no_known_bounds(
429+
const exprt &src,
430+
std::size_t el_bytes,
431+
bool little_endian,
432+
const namespacet &ns)
433+
{
434+
// TODO we either need a symbol table here or make array comprehensions
435+
// introduce a scope
436+
static std::size_t array_comprehension_index_counter = 0;
437+
++array_comprehension_index_counter;
438+
symbol_exprt array_comprehension_index{
439+
"$array_comprehension_index_a_v" +
440+
std::to_string(array_comprehension_index_counter),
441+
index_type()};
442+
443+
index_exprt element{
444+
src,
445+
div_exprt{array_comprehension_index, from_integer(el_bytes, index_type())}};
446+
447+
exprt sub = unpack_rec(element, little_endian, {}, {}, ns, false);
448+
exprt::operandst sub_operands = instantiate_byte_array(sub, 0, el_bytes, ns);
449+
450+
exprt body = sub_operands.front();
451+
const mod_exprt offset{
452+
array_comprehension_index,
453+
from_integer(el_bytes, array_comprehension_index.type())};
454+
for(std::size_t i = 1; i < el_bytes; ++i)
455+
{
456+
body = if_exprt{
457+
equal_exprt{offset, from_integer(i, array_comprehension_index.type())},
458+
sub_operands[i],
459+
body};
460+
}
461+
462+
const exprt array_vector_size = src.type().id() == ID_vector
463+
? to_vector_type(src.type()).size()
464+
: to_array_type(src.type()).size();
465+
466+
return array_comprehension_exprt{
467+
std::move(array_comprehension_index),
468+
std::move(body),
469+
array_typet{bv_typet{8},
470+
mult_exprt{array_vector_size,
471+
from_integer(el_bytes, array_vector_size.type())}}};
472+
}
473+
421474
/// Rewrite an array or vector into its individual bytes.
422475
/// \param src: array/vector to unpack
423476
/// \param src_size: array/vector size; if not a constant and thus not set,
@@ -445,47 +498,11 @@ static exprt unpack_array_vector(
445498

446499
if(!src_size.has_value() && !max_bytes.has_value())
447500
{
448-
// TODO we either need a symbol table here or make array comprehensions
449-
// introduce a scope
450-
static std::size_t array_comprehension_index_counter = 0;
451-
++array_comprehension_index_counter;
452-
symbol_exprt array_comprehension_index{
453-
"$array_comprehension_index_a_v" +
454-
std::to_string(array_comprehension_index_counter),
455-
index_type()};
456-
457-
CHECK_RETURN(el_bytes > 0);
458-
index_exprt element{src,
459-
div_exprt{array_comprehension_index,
460-
from_integer(el_bytes, index_type())}};
461-
462-
exprt sub = unpack_rec(element, little_endian, {}, {}, ns, false);
463-
exprt::operandst sub_operands =
464-
instantiate_byte_array(sub, 0, el_bytes, ns);
465-
466-
exprt body = sub_operands.front();
467-
const mod_exprt offset{
468-
array_comprehension_index,
469-
from_integer(el_bytes, array_comprehension_index.type())};
470-
for(std::size_t i = 1; i < el_bytes; ++i)
471-
{
472-
body = if_exprt{
473-
equal_exprt{offset, from_integer(i, array_comprehension_index.type())},
474-
sub_operands[i],
475-
body};
476-
}
477-
478-
const exprt array_vector_size = src.type().id() == ID_vector
479-
? to_vector_type(src.type()).size()
480-
: to_array_type(src.type()).size();
481-
482-
return array_comprehension_exprt{
483-
std::move(array_comprehension_index),
484-
std::move(body),
485-
array_typet{
486-
bv_typet{8},
487-
mult_exprt{array_vector_size,
488-
from_integer(el_bytes, array_vector_size.type())}}};
501+
PRECONDITION_WITH_DIAGNOSTICS(
502+
el_bytes > 0 && element_bits % 8 == 0,
503+
"unpacking of arrays with non-byte-aligned elements is not supported");
504+
return unpack_array_vector_no_known_bounds(
505+
src, el_bytes, little_endian, ns);
489506
}
490507

491508
exprt::operandst byte_operands;

0 commit comments

Comments
 (0)