Skip to content

Commit 000f528

Browse files
authored
Merge pull request #6486 from tautschnig/refactor-byte-extract-arrays-vector
Byte extract lowering: refactor lowering of arrays/vectors [blocks: #6488]
2 parents 5750c68 + bee3b76 commit 000f528

File tree

1 file changed

+82
-83
lines changed

1 file changed

+82
-83
lines changed

src/solvers/lowering/byte_operators.cpp

Lines changed: 82 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,84 @@ static exprt unpack_rec(
944944
{}, array_typet{bv_typet{8}, from_integer(0, size_type())});
945945
}
946946

947+
/// Rewrite a byte extraction of an array/vector-typed result to byte extraction
948+
/// of the individual components that make up an \ref array_exprt or
949+
/// \ref vector_exprt.
950+
/// \param src: Original byte extract expression
951+
/// \param unpacked: Byte extraction with root operand expanded into array (via
952+
/// \ref unpack_rec)
953+
/// \param subtype: Array/vector element type
954+
/// \param element_bits: bit width of array/vector elements
955+
/// \param ns: Namespace
956+
/// \return An array or vector expression.
957+
static exprt lower_byte_extract_array_vector(
958+
const byte_extract_exprt &src,
959+
const byte_extract_exprt &unpacked,
960+
const typet &subtype,
961+
const mp_integer &element_bits,
962+
const namespacet &ns)
963+
{
964+
optionalt<std::size_t> num_elements;
965+
if(src.type().id() == ID_array)
966+
num_elements = numeric_cast<std::size_t>(to_array_type(src.type()).size());
967+
else
968+
num_elements = numeric_cast<std::size_t>(to_vector_type(src.type()).size());
969+
970+
if(num_elements.has_value())
971+
{
972+
exprt::operandst operands;
973+
operands.reserve(*num_elements);
974+
for(std::size_t i = 0; i < *num_elements; ++i)
975+
{
976+
plus_exprt new_offset(
977+
unpacked.offset(),
978+
from_integer(i * element_bits / 8, unpacked.offset().type()));
979+
980+
byte_extract_exprt tmp(unpacked);
981+
tmp.type() = subtype;
982+
tmp.offset() = new_offset;
983+
984+
operands.push_back(lower_byte_extract(tmp, ns));
985+
}
986+
987+
exprt result;
988+
if(src.type().id() == ID_array)
989+
result = array_exprt{std::move(operands), to_array_type(src.type())};
990+
else
991+
result = vector_exprt{std::move(operands), to_vector_type(src.type())};
992+
993+
return simplify_expr(result, ns);
994+
}
995+
996+
DATA_INVARIANT(src.type().id() == ID_array, "vectors have constant size");
997+
const array_typet &array_type = to_array_type(src.type());
998+
999+
// TODO we either need a symbol table here or make array comprehensions
1000+
// introduce a scope
1001+
static std::size_t array_comprehension_index_counter = 0;
1002+
++array_comprehension_index_counter;
1003+
symbol_exprt array_comprehension_index{
1004+
"$array_comprehension_index_a" +
1005+
std::to_string(array_comprehension_index_counter),
1006+
index_type()};
1007+
1008+
plus_exprt new_offset{
1009+
unpacked.offset(),
1010+
typecast_exprt::conditional_cast(
1011+
mult_exprt{
1012+
array_comprehension_index,
1013+
from_integer(element_bits / 8, array_comprehension_index.type())},
1014+
unpacked.offset().type())};
1015+
1016+
byte_extract_exprt body(unpacked);
1017+
body.type() = subtype;
1018+
body.offset() = std::move(new_offset);
1019+
1020+
return array_comprehension_exprt{std::move(array_comprehension_index),
1021+
lower_byte_extract(body, ns),
1022+
array_type};
1023+
}
1024+
9471025
/// Rewrite a byte extraction of a complex-typed result to byte extraction of
9481026
/// the individual components that make up a \ref complex_exprt.
9491027
/// \param src: Original byte extract expression
@@ -1060,97 +1138,18 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
10601138
to_bitvector_type(to_type_with_subtype(unpacked.op().type()).subtype())
10611139
.get_width() == 8);
10621140

1063-
if(src.type().id()==ID_array)
1141+
if(src.type().id() == ID_array || src.type().id() == ID_vector)
10641142
{
1065-
const array_typet &array_type=to_array_type(src.type());
1066-
const typet &subtype=array_type.subtype();
1143+
const typet &subtype = to_type_with_subtype(src.type()).subtype();
10671144

10681145
// consider ways of dealing with arrays of unknown subtype size or with a
10691146
// subtype size that does not fit byte boundaries; currently we fall back to
10701147
// stitching together consecutive elements down below
10711148
auto element_bits = pointer_offset_bits(subtype, ns);
10721149
if(element_bits.has_value() && *element_bits >= 1 && *element_bits % 8 == 0)
10731150
{
1074-
auto num_elements = numeric_cast<std::size_t>(array_type.size());
1075-
1076-
if(num_elements.has_value())
1077-
{
1078-
exprt::operandst operands;
1079-
operands.reserve(*num_elements);
1080-
for(std::size_t i = 0; i < *num_elements; ++i)
1081-
{
1082-
plus_exprt new_offset(
1083-
unpacked.offset(),
1084-
from_integer(i * (*element_bits) / 8, unpacked.offset().type()));
1085-
1086-
byte_extract_exprt tmp(unpacked);
1087-
tmp.type() = subtype;
1088-
tmp.offset() = new_offset;
1089-
1090-
operands.push_back(lower_byte_extract(tmp, ns));
1091-
}
1092-
1093-
return simplify_expr(array_exprt(std::move(operands), array_type), ns);
1094-
}
1095-
else
1096-
{
1097-
// TODO we either need a symbol table here or make array comprehensions
1098-
// introduce a scope
1099-
static std::size_t array_comprehension_index_counter = 0;
1100-
++array_comprehension_index_counter;
1101-
symbol_exprt array_comprehension_index{
1102-
"$array_comprehension_index_a" +
1103-
std::to_string(array_comprehension_index_counter),
1104-
index_type()};
1105-
1106-
plus_exprt new_offset{
1107-
unpacked.offset(),
1108-
typecast_exprt::conditional_cast(
1109-
mult_exprt{array_comprehension_index,
1110-
from_integer(
1111-
*element_bits / 8, array_comprehension_index.type())},
1112-
unpacked.offset().type())};
1113-
1114-
byte_extract_exprt body(unpacked);
1115-
body.type() = subtype;
1116-
body.offset() = std::move(new_offset);
1117-
1118-
return array_comprehension_exprt{std::move(array_comprehension_index),
1119-
lower_byte_extract(body, ns),
1120-
array_type};
1121-
}
1122-
}
1123-
}
1124-
else if(src.type().id() == ID_vector)
1125-
{
1126-
const vector_typet &vector_type = to_vector_type(src.type());
1127-
const typet &subtype = vector_type.subtype();
1128-
1129-
// consider ways of dealing with vectors of unknown subtype size or with a
1130-
// subtype size that does not fit byte boundaries; currently we fall back to
1131-
// stitching together consecutive elements down below
1132-
auto element_bits = pointer_offset_bits(subtype, ns);
1133-
if(element_bits.has_value() && *element_bits >= 1 && *element_bits % 8 == 0)
1134-
{
1135-
const std::size_t num_elements =
1136-
numeric_cast_v<std::size_t>(vector_type.size());
1137-
1138-
exprt::operandst operands;
1139-
operands.reserve(num_elements);
1140-
for(std::size_t i = 0; i < num_elements; ++i)
1141-
{
1142-
plus_exprt new_offset(
1143-
unpacked.offset(),
1144-
from_integer(i * (*element_bits) / 8, unpacked.offset().type()));
1145-
1146-
byte_extract_exprt tmp(unpacked);
1147-
tmp.type() = subtype;
1148-
tmp.offset() = simplify_expr(new_offset, ns);
1149-
1150-
operands.push_back(lower_byte_extract(tmp, ns));
1151-
}
1152-
1153-
return simplify_expr(vector_exprt(std::move(operands), vector_type), ns);
1151+
return lower_byte_extract_array_vector(
1152+
src, unpacked, subtype, *element_bits, ns);
11541153
}
11551154
}
11561155
else if(src.type().id() == ID_complex)

0 commit comments

Comments
 (0)