@@ -551,69 +551,121 @@ static exprt unpack_array_vector(
551
551
// refine the number of elements to extract in case the element width is known
552
552
// and a multiple of bytes; otherwise we will expand the entire array/vector
553
553
optionalt<mp_integer> num_elements = src_size;
554
- if (element_bits > 0 && element_bits % bits_per_byte == 0 )
554
+ if (element_bits > 0 )
555
555
{
556
556
if (!num_elements.has_value ())
557
557
{
558
558
// turn bytes into elements, rounding up
559
- num_elements = (*max_bytes + el_bytes - 1 ) / el_bytes;
559
+ num_elements =
560
+ (*max_bytes * bits_per_byte + element_bits - 1 ) / element_bits;
560
561
}
561
562
562
563
if (offset_bytes.has_value ())
563
564
{
564
565
// compute offset as number of elements
565
- first_element = *offset_bytes / el_bytes ;
566
- // insert offset_bytes-many nil bytes into the output array
566
+ first_element = *offset_bytes * bits_per_byte / element_bits ;
567
+ // insert offset_bytes-many zero bytes into the output array
567
568
byte_operands.resize (
568
- numeric_cast_v<std::size_t >(*offset_bytes - (*offset_bytes % el_bytes)),
569
+ numeric_cast_v<std::size_t >(
570
+ (*offset_bytes * bits_per_byte -
571
+ ((*offset_bytes * bits_per_byte) % element_bits)) /
572
+ bits_per_byte),
569
573
from_integer (0 , bv_typet{bits_per_byte}));
570
574
}
571
575
}
572
576
573
577
// the maximum number of bytes is an upper bound in case the size of the
574
- // array/vector is unknown; if element_bits was usable above this will
578
+ // array/vector is unknown; if element_bits was non-zero above this will
575
579
// have been turned into a number of elements already
576
580
if (!num_elements)
577
581
num_elements = *max_bytes;
578
582
579
583
const exprt src_simp = simplify_expr (src, ns);
580
584
581
- for (mp_integer i = first_element; i < *num_elements; ++i )
585
+ if (element_bits % bits_per_byte == 0 )
582
586
{
583
- exprt element;
584
-
585
- if (
586
- (src_simp.id () == ID_array || src_simp.id () == ID_vector) &&
587
- i < src_simp.operands ().size ())
587
+ for (mp_integer i = first_element; i < *num_elements; ++i)
588
588
{
589
- const std::size_t index_int = numeric_cast_v<std::size_t >(i);
590
- element = src_simp.operands ()[index_int];
589
+ exprt element;
590
+
591
+ if (
592
+ (src_simp.id () == ID_array || src_simp.id () == ID_vector) &&
593
+ i < src_simp.operands ().size ())
594
+ {
595
+ const std::size_t index_int = numeric_cast_v<std::size_t >(i);
596
+ element = src_simp.operands ()[index_int];
597
+ }
598
+ else
599
+ {
600
+ element = index_exprt (src_simp, from_integer (i, index_type ()));
601
+ }
602
+
603
+ // recursively unpack each element so that we eventually just have an
604
+ // array of bytes left
605
+
606
+ const optionalt<mp_integer> element_max_bytes =
607
+ max_bytes
608
+ ? std::min (mp_integer{el_bytes}, *max_bytes - byte_operands.size ())
609
+ : optionalt<mp_integer>{};
610
+ const std::size_t element_max_bytes_int =
611
+ element_max_bytes ? numeric_cast_v<std::size_t >(*element_max_bytes)
612
+ : el_bytes;
613
+
614
+ exprt sub = unpack_rec (
615
+ element, little_endian, {}, element_max_bytes, bits_per_byte, ns, true );
616
+ exprt::operandst sub_operands = instantiate_byte_array (
617
+ sub, 0 , element_max_bytes_int, bits_per_byte, ns);
618
+ byte_operands.insert (
619
+ byte_operands.end (), sub_operands.begin (), sub_operands.end ());
620
+
621
+ if (max_bytes && byte_operands.size () >= *max_bytes)
622
+ break ;
591
623
}
592
- else
624
+ }
625
+ else
626
+ {
627
+ const std::size_t element_bits_int =
628
+ numeric_cast_v<std::size_t >(element_bits);
629
+
630
+ exprt::operandst elements;
631
+ for (mp_integer i = *num_elements - 1 ; i >= first_element; --i)
593
632
{
594
- element = index_exprt (src_simp, from_integer (i, c_index_type ()));
633
+ if (
634
+ (src_simp.id () == ID_array || src_simp.id () == ID_vector) &&
635
+ i < src_simp.operands ().size ())
636
+ {
637
+ const std::size_t index_int = numeric_cast_v<std::size_t >(i);
638
+ elements.push_back (typecast_exprt::conditional_cast (
639
+ src_simp.operands ()[index_int], bv_typet{element_bits_int}));
640
+ }
641
+ else
642
+ {
643
+ elements.push_back (typecast_exprt::conditional_cast (
644
+ index_exprt (src_simp, from_integer (i, c_index_type ())),
645
+ bv_typet{element_bits_int}));
646
+ }
595
647
}
596
648
597
- // recursively unpack each element so that we eventually just have an array
598
- // of bytes left
649
+ const std::size_t merged_bit_width = numeric_cast_v<std::size_t >(
650
+ (*num_elements - first_element) * element_bits);
651
+ if (!little_endian)
652
+ std::reverse (elements.begin (), elements.end ());
653
+ concatenation_exprt merged{std::move (elements), bv_typet{merged_bit_width}};
599
654
600
- const optionalt<mp_integer> element_max_bytes =
601
- max_bytes
602
- ? std::min (mp_integer{el_bytes}, *max_bytes - byte_operands.size ())
603
- : optionalt<mp_integer>{};
604
- const std::size_t element_max_bytes_int =
605
- element_max_bytes ? numeric_cast_v<std::size_t >(*element_max_bytes)
606
- : el_bytes;
655
+ exprt merged_as_bytes =
656
+ unpack_rec (merged, little_endian, {}, max_bytes, bits_per_byte, ns, true );
607
657
608
- exprt sub = unpack_rec (
609
- element, little_endian, {}, element_max_bytes, bits_per_byte, ns, true );
610
- exprt::operandst sub_operands =
611
- instantiate_byte_array (sub, 0 , element_max_bytes_int, bits_per_byte, ns);
658
+ const std::size_t merged_byte_width =
659
+ (merged_bit_width + bits_per_byte - 1 ) / bits_per_byte;
660
+ const std::size_t max_bytes_int =
661
+ max_bytes.has_value ()
662
+ ? std::min (numeric_cast_v<std::size_t >(*max_bytes), merged_byte_width)
663
+ : merged_byte_width;
664
+
665
+ exprt::operandst sub_operands = instantiate_byte_array (
666
+ merged_as_bytes, 0 , max_bytes_int, bits_per_byte, ns);
612
667
byte_operands.insert (
613
668
byte_operands.end (), sub_operands.begin (), sub_operands.end ());
614
-
615
- if (max_bytes && byte_operands.size () >= *max_bytes)
616
- break ;
617
669
}
618
670
619
671
const std::size_t size = byte_operands.size ();
@@ -1072,17 +1124,55 @@ static exprt lower_byte_extract_array_vector(
1072
1124
operands.reserve (*num_elements);
1073
1125
for (std::size_t i = 0 ; i < *num_elements; ++i)
1074
1126
{
1075
- plus_exprt new_offset (
1076
- unpacked.offset (),
1077
- from_integer (
1078
- i * element_bits / src.get_bits_per_byte (),
1079
- unpacked.offset ().type ()));
1127
+ if (element_bits % src.get_bits_per_byte () == 0 )
1128
+ {
1129
+ plus_exprt new_offset (
1130
+ unpacked.offset (),
1131
+ from_integer (
1132
+ i * element_bits / src.get_bits_per_byte (),
1133
+ unpacked.offset ().type ()));
1080
1134
1081
- byte_extract_exprt tmp (unpacked);
1082
- tmp.type () = subtype;
1083
- tmp.offset () = new_offset;
1135
+ byte_extract_exprt tmp (unpacked);
1136
+ tmp.type () = subtype;
1137
+ tmp.offset () = new_offset;
1084
1138
1085
- operands.push_back (lower_byte_extract (tmp, ns));
1139
+ operands.push_back (lower_byte_extract (tmp, ns));
1140
+ }
1141
+ else
1142
+ {
1143
+ const mp_integer first_index =
1144
+ i * element_bits / src.get_bits_per_byte ();
1145
+ const mp_integer last_index =
1146
+ ((i + 1 ) * element_bits + src.get_bits_per_byte () - 1 ) /
1147
+ src.get_bits_per_byte ();
1148
+
1149
+ exprt::operandst to_concat;
1150
+ to_concat.reserve (
1151
+ numeric_cast_v<std::size_t >(last_index - first_index));
1152
+ for (mp_integer j = first_index; j < last_index; ++j)
1153
+ {
1154
+ to_concat.push_back (index_exprt{
1155
+ unpacked.op (),
1156
+ plus_exprt{
1157
+ unpacked.offset (), from_integer (j, unpacked.offset ().type ())}});
1158
+ }
1159
+
1160
+ const std::size_t base = numeric_cast_v<std::size_t >(
1161
+ (i * element_bits) % src.get_bits_per_byte ());
1162
+ const std::size_t last =
1163
+ numeric_cast_v<std::size_t >(base + element_bits - 1 );
1164
+ bv_typet concat_type{src.get_bits_per_byte () * to_concat.size ()};
1165
+ endianness_mapt endianness_map (
1166
+ concat_type, src.id () == ID_byte_extract_little_endian, ns);
1167
+ const auto bounds = map_bounds (endianness_map, base, last);
1168
+ extractbits_exprt element{
1169
+ concatenation_exprt{to_concat, std::move (concat_type)},
1170
+ from_integer (bounds.ub , size_type ()),
1171
+ from_integer (bounds.lb , size_type ()),
1172
+ subtype};
1173
+
1174
+ operands.push_back (element);
1175
+ }
1086
1176
}
1087
1177
1088
1178
exprt result;
@@ -1106,6 +1196,10 @@ static exprt lower_byte_extract_array_vector(
1106
1196
std::to_string (array_comprehension_index_counter),
1107
1197
c_index_type ()};
1108
1198
1199
+ PRECONDITION_WITH_DIAGNOSTICS (
1200
+ element_bits % src.get_bits_per_byte () == 0 ,
1201
+ " byte extracting non-byte-aligned arrays requires constant size" );
1202
+
1109
1203
plus_exprt new_offset{
1110
1204
unpacked.offset (),
1111
1205
typecast_exprt::conditional_cast (
@@ -1251,17 +1345,13 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
1251
1345
{
1252
1346
const typet &subtype = to_type_with_subtype (src.type ()).subtype ();
1253
1347
1254
- // consider ways of dealing with arrays of unknown subtype size or with a
1255
- // subtype size that does not fit byte boundaries; currently we fall back to
1256
- // stitching together consecutive elements down below
1257
1348
auto element_bits = pointer_offset_bits (subtype, ns);
1258
- if (
1259
- element_bits.has_value () && *element_bits >= 1 &&
1260
- *element_bits % src.get_bits_per_byte () == 0 )
1261
- {
1262
- return lower_byte_extract_array_vector (
1263
- src, unpacked, subtype, *element_bits, ns);
1264
- }
1349
+ PRECONDITION_WITH_DIAGNOSTICS (
1350
+ element_bits.has_value () && *element_bits >= 1 ,
1351
+ " byte extracting arrays of unknown/zero subtype is not yet implemented" );
1352
+
1353
+ return lower_byte_extract_array_vector (
1354
+ src, unpacked, subtype, *element_bits, ns);
1265
1355
}
1266
1356
else if (src.type ().id () == ID_complex)
1267
1357
{
0 commit comments