@@ -944,6 +944,84 @@ static exprt unpack_rec(
944
944
{}, array_typet{bv_typet{8 }, from_integer (0 , size_type ())});
945
945
}
946
946
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
+
947
1025
// / Rewrite a byte extraction of a complex-typed result to byte extraction of
948
1026
// / the individual components that make up a \ref complex_exprt.
949
1027
// / \param src: Original byte extract expression
@@ -1060,97 +1138,18 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
1060
1138
to_bitvector_type (to_type_with_subtype (unpacked.op ().type ()).subtype ())
1061
1139
.get_width () == 8 );
1062
1140
1063
- if (src.type ().id ()== ID_array)
1141
+ if (src.type ().id () == ID_array || src. type (). id () == ID_vector )
1064
1142
{
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 ();
1067
1144
1068
1145
// consider ways of dealing with arrays of unknown subtype size or with a
1069
1146
// subtype size that does not fit byte boundaries; currently we fall back to
1070
1147
// stitching together consecutive elements down below
1071
1148
auto element_bits = pointer_offset_bits (subtype, ns);
1072
1149
if (element_bits.has_value () && *element_bits >= 1 && *element_bits % 8 == 0 )
1073
1150
{
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);
1154
1153
}
1155
1154
}
1156
1155
else if (src.type ().id () == ID_complex)
0 commit comments