24 const exprt &bitvector_expr,
25 const typet &target_type,
38 std::size_t lower_bound,
39 std::size_t upper_bound)
42 result.
lb = lower_bound;
43 result.
ub = upper_bound;
51 if(result.
ub < result.
lb)
52 std::swap(result.
lb, result.
ub);
61 if(src.
id() == ID_unsignedbv)
63 else if(src.
id() == ID_signedbv)
65 else if(src.
id() == ID_bv)
67 else if(src.
id() == ID_c_enum)
69 else if(src.
id() == ID_c_bit_field)
79 const exprt &bitvector_expr,
87 operands.reserve(components.size());
89 for(
const auto &comp : components)
92 std::size_t component_bits;
93 if(component_bits_opt.has_value())
99 if(component_bits == 0)
118 if(component_bits_opt.has_value())
128 const exprt &bitvector_expr,
135 if(components.empty())
140 std::size_t component_bits;
141 if(widest_member.has_value())
146 if(component_bits == 0)
149 components.front().get_name(),
150 bv_to_expr(bitvector_expr, components.front().type(), endianness_map, ns),
154 const auto bounds =
map_bounds(endianness_map, 0, component_bits - 1);
156 const irep_idt &component_name = widest_member.has_value()
157 ? widest_member->first.get_name()
158 : components.front().get_name();
159 const typet &component_type = widest_member.has_value()
160 ? widest_member->first.type()
161 : components.front().type();
176 const exprt &bitvector_expr,
184 const std::size_t total_bits =
186 if(!num_elements.has_value())
188 if(!subtype_bits.has_value() || *subtype_bits == 0)
189 num_elements = total_bits;
194 !num_elements.has_value() || !subtype_bits.has_value() ||
195 *subtype_bits * *num_elements == total_bits,
196 "subtype width times array size should be total bitvector width");
199 operands.reserve(*num_elements);
200 for(std::size_t i = 0; i < *num_elements; ++i)
202 if(subtype_bits.has_value())
204 const std::size_t subtype_bits_int =
207 endianness_map, i * subtype_bits_int, ((i + 1) * subtype_bits_int) - 1);
220 bitvector_expr, array_type.
element_type(), endianness_map, ns));
224 return array_exprt{std::move(operands), array_type};
230 const exprt &bitvector_expr,
235 const std::size_t num_elements =
239 !subtype_bits.has_value() ||
240 *subtype_bits * num_elements ==
242 "subtype width times vector size should be total bitvector width");
245 operands.reserve(num_elements);
246 for(std::size_t i = 0; i < num_elements; ++i)
248 if(subtype_bits.has_value())
250 const std::size_t subtype_bits_int =
253 endianness_map, i * subtype_bits_int, ((i + 1) * subtype_bits_int) - 1);
266 bitvector_expr, vector_type.
element_type(), endianness_map, ns));
276 const exprt &bitvector_expr,
281 const std::size_t total_bits =
284 std::size_t subtype_bits;
285 if(subtype_bits_opt.has_value())
289 subtype_bits * 2 == total_bits,
290 "subtype width should be half of the total bitvector width");
293 subtype_bits = total_bits / 2;
295 const auto bounds_real =
map_bounds(endianness_map, 0, subtype_bits - 1);
296 const auto bounds_imag =
297 map_bounds(endianness_map, subtype_bits, subtype_bits * 2 - 1);
331 const exprt &bitvector_expr,
332 const typet &target_type,
338 if(target_type.
id() == ID_floatbv)
348 target_type.
id() == ID_c_enum || target_type.
id() == ID_c_enum_tag ||
349 target_type.
id() == ID_string ||
350 (target_type.
id() == ID_bool &&
356 else if(target_type.
id() == ID_struct)
361 else if(target_type.
id() == ID_struct_tag)
368 result.
type() = target_type;
369 return std::move(result);
371 else if(target_type.
id() == ID_union)
374 bitvector_expr,
to_union_type(target_type), endianness_map, ns);
376 else if(target_type.
id() == ID_union_tag)
383 result.
type() = target_type;
386 else if(target_type.
id() == ID_array)
389 bitvector_expr,
to_array_type(target_type), endianness_map, ns);
391 else if(target_type.
id() == ID_vector)
396 else if(target_type.
id() == ID_complex)
404 false,
"bv_to_expr does not yet support ", target_type.
id_string());
411 const std::optional<mp_integer> &offset_bytes,
412 const std::optional<mp_integer> &max_bytes,
413 const std::size_t bits_per_byte,
415 bool unpack_byte_array =
false);
426 std::size_t lower_bound,
427 std::size_t upper_bound,
428 const std::size_t bits_per_byte,
433 if(src.
id() == ID_array)
441 const typet &element_type = src.
type().
id() == ID_array
444 const typet index_type = src.
type().
id() == ID_array
451 bytes.reserve(upper_bound - lower_bound);
452 for(std::size_t i = lower_bound; i < upper_bound; ++i)
470 std::size_t el_bytes,
472 const std::size_t bits_per_byte,
475 const typet index_type = src.
type().
id() == ID_array
481 static std::size_t array_comprehension_index_counter = 0;
482 ++array_comprehension_index_counter;
484 "$array_comprehension_index_a_v" +
485 std::to_string(array_comprehension_index_counter),
493 unpack_rec(element, little_endian, {}, {}, bits_per_byte, ns,
false);
497 exprt body = sub_operands.front();
499 array_comprehension_index,
501 for(std::size_t i = 1; i < el_bytes; ++i)
509 const exprt array_vector_size = src.
type().
id() == ID_vector
513 if(array_vector_size.
is_nil())
521 std::move(array_comprehension_index),
527 std::move(array_comprehension_index),
552 const std::optional<mp_integer> &src_size,
555 const std::optional<mp_integer> &offset_bytes,
556 const std::optional<mp_integer> &max_bytes,
557 const std::size_t bits_per_byte,
561 (element_bits + bits_per_byte - 1) / bits_per_byte);
563 if(!src_size.has_value() && !max_bytes.has_value())
566 el_bytes > 0 && element_bits % bits_per_byte == 0,
567 "unpacking of arrays with non-byte-aligned elements is not supported");
569 src, el_bytes, little_endian, bits_per_byte, ns);
577 std::optional<mp_integer> num_elements = src_size;
578 if(element_bits > 0 && element_bits % bits_per_byte == 0)
580 if(!num_elements.has_value())
583 num_elements = (*max_bytes + el_bytes - 1) / el_bytes;
586 if(offset_bytes.has_value())
589 first_element = *offset_bytes / el_bytes;
591 byte_operands.resize(
593 *offset_bytes - (*offset_bytes % el_bytes),
594 *num_elements * el_bytes)),
603 num_elements = *max_bytes;
606 const typet index_type = src_simp.
type().
id() == ID_array
610 for(
mp_integer i = first_element; i < *num_elements; ++i)
615 (src_simp.
id() == ID_array || src_simp.
id() == ID_vector) &&
619 element = src_simp.
operands()[index_int];
629 const std::optional<mp_integer> element_max_bytes =
631 ? std::min(
mp_integer{el_bytes}, *max_bytes - byte_operands.size())
632 : std::optional<mp_integer>{};
633 const std::size_t element_max_bytes_int =
638 element, little_endian, {}, element_max_bytes, bits_per_byte, ns,
true);
641 byte_operands.insert(
642 byte_operands.end(), sub_operands.begin(), sub_operands.end());
644 if(max_bytes && byte_operands.size() >= *max_bytes)
648 const std::size_t size = byte_operands.size();
650 std::move(byte_operands),
667 std::size_t total_bits,
670 const std::optional<mp_integer> &offset_bytes,
671 const std::optional<mp_integer> &max_bytes,
672 const std::size_t bits_per_byte,
676 std::move(bit_fields),
bv_typet{total_bits}};
689 std::make_move_iterator(sub.
operands().begin()),
690 std::make_move_iterator(sub.
operands().end()));
706 const std::optional<mp_integer> &offset_bytes,
707 const std::optional<mp_integer> &max_bytes,
708 const std::size_t bits_per_byte,
712 src.
type().
id() == ID_struct_tag
717 std::optional<mp_integer> offset_in_member;
718 std::optional<mp_integer> max_bytes_left;
719 std::optional<std::pair<exprt::operandst, std::size_t>> bit_fields;
723 for(
auto it = components.begin(); it != components.end(); ++it)
725 const auto &comp = *it;
734 component_bits.has_value() ||
735 (std::next(it) == components.end() && !bit_fields.has_value()),
736 "members of non-constant width should come last in a struct");
739 if(src.
id() == ID_struct)
745 if(bit_fields.has_value())
748 std::move(bit_fields->first),
759 if(offset_bytes.has_value())
764 if(*offset_in_member < 0)
765 offset_in_member.reset();
768 if(max_bytes.has_value())
771 if(*max_bytes_left < 0)
778 (component_bits.has_value() && *component_bits % bits_per_byte != 0))
780 if(!bit_fields.has_value())
784 bit_fields->first.insert(
785 little_endian ? bit_fields->first.begin() : bit_fields->first.end(),
787 bit_fields->second += bits_int;
795 !bit_fields.has_value(),
796 "all preceding members should have been processed");
799 component_bits.has_value() && offset_in_member.has_value() &&
800 *offset_in_member * bits_per_byte >= *component_bits)
804 byte_operands.resize(
805 byte_operands.size() +
820 byte_operands.insert(
822 std::make_move_iterator(sub.
operands().begin()),
823 std::make_move_iterator(sub.
operands().end()));
826 if(component_bits.has_value())
831 if(bit_fields.has_value())
834 std::move(bit_fields->first),
844 const std::size_t size = byte_operands.size();
846 std::move(byte_operands),
859 const std::size_t bits_per_byte,
873 *subtype_bits / bits_per_byte,
883 *subtype_bits / bits_per_byte,
887 byte_operands.insert(
889 std::make_move_iterator(sub_imag.
operands().begin()),
890 std::make_move_iterator(sub_imag.
operands().end()));
892 const std::size_t size = byte_operands.size();
894 std::move(byte_operands),
913 const std::optional<mp_integer> &offset_bytes,
914 const std::optional<mp_integer> &max_bytes,
915 const std::size_t bits_per_byte,
917 bool unpack_byte_array)
919 if(src.
type().
id() == ID_array)
928 !unpack_byte_array && *element_bits == bits_per_byte &&
945 else if(src.
type().
id() == ID_vector)
954 !unpack_byte_array && *element_bits == bits_per_byte &&
970 else if(src.
type().
id() == ID_complex)
974 else if(src.
type().
id() == ID_struct || src.
type().
id() == ID_struct_tag)
977 src, little_endian, offset_bytes, max_bytes, bits_per_byte, ns);
979 else if(src.
type().
id() == ID_union || src.
type().
id() == ID_union_tag)
982 src.
type().
id() == ID_union_tag
988 if(widest_member.has_value())
991 src, widest_member->first.get_name(), widest_member->first.
type()};
996 widest_member->second,
1014 else if(src.
type().
id() == ID_pointer)
1025 else if(src.
id() == ID_string_constant)
1047 else if(src.
type().
id() != ID_empty)
1052 DATA_INVARIANT(bits_opt.has_value(),
"basic type should have a fixed size");
1058 if(max_bytes.has_value())
1060 const auto max_bits = *max_bytes * bits_per_byte;
1063 last_bit = std::min(last_bit, max_bits);
1067 bit_offset = std::max(
mp_integer{0}, last_bit - max_bits);
1077 total_bits % bits_per_byte == 0
1079 : total_bits + bits_per_byte - total_bits % bits_per_byte;
1082 if(padded_bits > total_bits)
1087 auto const byte_type =
bv_typet{bits_per_byte};
1092 for(; bit_offset < last_bit; bit_offset += bits_per_byte)
1105 byte_operands.push_back(extractbits);
1107 byte_operands.insert(byte_operands.begin(), extractbits);
1110 const std::size_t size = byte_operands.size();
1112 return array_exprt{std::move(byte_operands), std::move(array_type)};
1132 const typet &subtype,
1136 std::optional<std::size_t> num_elements;
1137 if(src.
type().
id() == ID_array)
1142 if(num_elements.has_value())
1145 operands.reserve(*num_elements);
1146 for(std::size_t i = 0; i < *num_elements; ++i)
1155 tmp.
type() = subtype;
1156 tmp.
offset() = new_offset;
1162 if(src.
type().
id() == ID_array)
1175 static std::size_t array_comprehension_index_counter = 0;
1176 ++array_comprehension_index_counter;
1178 "$array_comprehension_index_a" +
1179 std::to_string(array_comprehension_index_counter),
1186 array_comprehension_index,
1189 array_comprehension_index.
type())},
1190 unpacked.
offset().type())};
1193 body.
type() = subtype;
1194 body.
offset() = std::move(new_offset);
1197 std::move(array_comprehension_index),
1224 real.
type() = subtype;
1231 imag.
type() = subtype;
1290 src.
id() == ID_byte_extract_little_endian ||
1291 src.
id() == ID_byte_extract_big_endian);
1292 const bool little_endian = src.
id() == ID_byte_extract_little_endian;
1296 if(upper_bound_opt.has_value())
1300 upper_bound_opt.value(),
1302 src.
offset(), upper_bound_opt.value().
type())),
1305 else if(src.
type().
id() == ID_empty)
1309 const auto upper_bound_int_opt =
1316 lower_bound_int_opt,
1317 upper_bound_int_opt,
1324 if(src.
type().
id() == ID_array || src.
type().
id() == ID_vector)
1333 element_bits.has_value() && *element_bits >= 1 &&
1337 src, unpacked, subtype, *element_bits, ns);
1340 else if(src.
type().
id() == ID_complex)
1343 if(result.has_value())
1344 return std::move(*result);
1348 else if(src.
type().
id() == ID_struct || src.
type().
id() == ID_struct_tag)
1351 src.
type().
id() == ID_struct_tag
1359 for(
const auto &comp : components)
1365 !component_bits.has_value() ||
1372 auto member_offset_opt =
1375 if(!member_offset_opt.has_value())
1384 member_offset_opt.value(), unpacked.
offset().
type()));
1387 tmp.
type() = comp.type();
1388 tmp.
offset() = new_offset;
1396 else if(src.
type().
id() == ID_union || src.
type().
id() == ID_union_tag)
1399 src.
type().
id() == ID_union_tag
1405 if(widest_member.has_value())
1408 tmp.
type() = widest_member->first.type();
1411 widest_member->first.get_name(),
1417 const exprt &root = unpacked.
op();
1420 std::optional<typet> subtype;
1421 std::optional<typet> index_type;
1422 if(root.
type().
id() == ID_vector)
1437 "offset bits are byte aligned");
1440 if(!size_bits.has_value())
1445 op0_bits.has_value(),
1446 "the extracted width or the source width must be known");
1447 size_bits = op0_bits;
1457 op.reserve(width_bytes);
1459 for(std::size_t i = 0; i < width_bytes; i++)
1462 std::size_t offset_int = little_endian ? (width_bytes - i - 1) : i;
1472 (root.
id() == ID_array || root.
id() == ID_vector) &&
1474 index < root.
operands().size() && index >= 0)
1485 if(width_bytes == 1)
1503 const exprt &value_as_byte_array,
1504 const std::optional<exprt> &non_const_update_bound,
1518 const typet &subtype,
1519 const exprt &value_as_byte_array,
1520 const exprt &non_const_update_bound,
1525 static std::size_t array_comprehension_index_counter = 0;
1526 ++array_comprehension_index_counter;
1528 "$array_comprehension_index_u_a_v" +
1529 std::to_string(array_comprehension_index_counter),
1534 array_comprehension_index, src.
offset().
type()),
1539 array_comprehension_index, non_const_update_bound.
type()),
1543 src.
offset(), non_const_update_bound.
type()),
1544 non_const_update_bound}};
1547 src.
id() == ID_byte_update_little_endian ||
1548 src.
id() == ID_byte_update_big_endian);
1549 const bool little_endian = src.
id() == ID_byte_update_little_endian;
1555 or_exprt{std::move(lower_bound), std::move(upper_bound)},
1559 value_as_byte_array,
1561 array_comprehension_index,
1563 src.
offset(), array_comprehension_index.
type())}},
1570 array_comprehension_index,
1571 std::move(array_comprehension_body),
1587 const typet &subtype,
1589 const std::optional<exprt> &non_const_update_bound,
1593 src.
id() == ID_byte_update_little_endian ||
1594 src.
id() == ID_byte_update_big_endian);
1595 const bool little_endian = src.
id() == ID_byte_update_little_endian;
1597 const typet index_type = src.
type().
id() == ID_array
1604 for(std::size_t i = 0; i < value_as_byte_array.
operands().size(); ++i)
1617 if(e.id() == ID_index)
1620 if(index_expr.
array() == src.
op() && index_expr.
index() == where)
1626 if(non_const_update_bound.has_value())
1632 *non_const_update_bound},
1637 result =
with_exprt{result, std::move(where), std::move(update_value)};
1660 const typet &subtype,
1661 const exprt &subtype_size,
1662 const exprt &value_as_byte_array,
1663 const exprt &non_const_update_bound,
1664 const exprt &initial_bytes,
1665 const exprt &first_index,
1666 const exprt &first_update_value,
1669 const irep_idt extract_opcode = src.
id() == ID_byte_update_little_endian
1670 ? ID_byte_extract_little_endian
1671 : ID_byte_extract_big_endian;
1675 static std::size_t array_comprehension_index_counter = 0;
1676 ++array_comprehension_index_counter;
1678 "$array_comprehension_index_u_a_v_u" +
1679 std::to_string(array_comprehension_index_counter),
1691 array_comprehension_index, first_index.
type()),
1702 array_comprehension_index, first_index.
type()),
1707 value_as_byte_array,
1708 std::move(offset_expr),
1720 non_const_update_bound, subtype_size.
type()),
1735 non_const_update_bound, initial_bytes.
type()),
1737 subtype_size.
type()),
1744 array_comprehension_index, last_index.
type()),
1759 value_as_byte_array,
1764 or_exprt{std::move(lower_bound), std::move(upper_bound)},
1769 array_comprehension_index, first_index.
type()),
1775 array_comprehension_index, last_index.
type()),
1777 std::move(last_update_value),
1778 std::move(update_value)}}};
1782 array_comprehension_index,
1783 std::move(array_comprehension_body),
1800 const typet &subtype,
1801 const exprt &value_as_byte_array,
1802 const std::optional<exprt> &non_const_update_bound,
1812 subtype_size_opt.value(), src.
offset().
type()),
1827 const exprt update_size =
1831 if(non_const_update_bound.has_value())
1834 *non_const_update_bound, subtype_size.
type());
1839 value_as_byte_array.
id() == ID_array,
1840 "value should be an array expression if the update bound is constant");
1841 update_bound = update_size;
1857 value_as_byte_array,
1861 if(value_as_byte_array.
id() != ID_array)
1867 value_as_byte_array,
1868 *non_const_update_bound,
1880 std::size_t step_size = 1;
1887 std::size_t offset = 0;
1891 with_exprt result{src.
op(), first_index, first_update_value};
1893 auto lower_byte_update_array_vector_non_const_one_element =
1898 &value_as_byte_array,
1900 &result](std::size_t i) ->
void {
1915 value_as_byte_array,
1919 result =
with_exprt{result, std::move(where), std::move(element)};
1923 for(; offset + step_size <= value_as_byte_array.
operands().size();
1924 offset += step_size, ++i)
1926 lower_byte_update_array_vector_non_const_one_element(i);
1930 if(offset < value_as_byte_array.
operands().size())
1931 lower_byte_update_array_vector_non_const_one_element(i);
1951 const exprt &element_to_update,
1954 const exprt &value_as_byte_array,
1955 const std::optional<exprt> &non_const_update_bound,
1963 std::size_t first = 0;
1970 mp_integer offset_bits_in_target_element = offset_bits - bits_already_set;
1972 if(offset_bits_in_target_element < 0)
1975 value_as_byte_array.
id() != ID_array ||
1977 -offset_bits_in_target_element,
1978 "indices past the update should be handled below");
1981 offset_bits_in_target_element +=
1984 if(offset_bits_in_target_element < 0)
1991 update_elements > 0,
"indices before the update should be handled above");
1995 if(value_as_byte_array.
id() == ID_array)
1996 end = std::min(end, value_as_byte_array.
operands().size());
1999 const std::size_t update_size = update_values.size();
2008 offset_bits_in_target_element >= 0 &&
2011 new_value =
array_exprt{update_values, update_type};
2015 if(src.
id() == ID_byte_update_little_endian)
2016 std::reverse(update_values.begin(), update_values.end());
2017 if(offset_bits_in_target_element < 0)
2019 if(src.
id() == ID_byte_update_little_endian)
2036 const std::size_t offset_bits_int =
2038 const std::size_t subtype_bits_int =
2043 subtype_bits_int - offset_bits_int,
2055 const irep_idt extract_opcode = src.
id() == ID_byte_update_little_endian
2056 ? ID_byte_extract_little_endian
2057 : ID_byte_extract_big_endian;
2068 offset_bits_in_target_element = 0;
2083 std::optional<exprt> update_bound;
2084 if(non_const_update_bound.has_value())
2092 *non_const_update_bound,
2096 *non_const_update_bound,
2106 remaining_update_bytes},
2125 const typet &subtype,
2126 const std::optional<mp_integer> &subtype_bits,
2127 const exprt &value_as_byte_array,
2128 const std::optional<exprt> &non_const_update_bound,
2131 const bool is_array = src.
type().
id() == ID_array;
2148 !subtype_bits.has_value() || value_as_byte_array.
id() != ID_array)
2151 src, subtype, value_as_byte_array, non_const_update_bound, ns);
2154 std::size_t num_elements =
2161 elements.reserve(num_elements);
2165 for(; i < num_elements && (i + 1) * *subtype_bits <= offset_bits; ++i)
2166 elements.push_back(
index_exprt{src.op(), from_integer(i, index_type)});
2171 i * *subtype_bits < offset_bits + value_as_byte_array.
operands().size() *
2181 value_as_byte_array,
2182 non_const_update_bound,
2187 for(; i < num_elements; ++i)
2188 elements.push_back(
index_exprt{src.op(), from_integer(i, index_type)});
2210 const exprt &value_as_byte_array,
2211 const std::optional<exprt> &non_const_update_bound,
2215 elements.reserve(struct_type.
components().size());
2218 for(
const auto &comp : struct_type.
components())
2232 if(!offset_bits.has_value() || !element_width.has_value())
2239 const irep_idt extract_opcode = src.
id() == ID_byte_update_little_endian
2240 ? ID_byte_extract_little_endian
2241 : ID_byte_extract_big_endian;
2261 bu, value_as_byte_array, non_const_update_bound, ns),
2276 *offset_bits >= *element_width ||
2277 (value_as_byte_array.
id() == ID_array && *offset_bits < 0 &&
2281 elements.push_back(member);
2292 value_as_byte_array,
2293 non_const_update_bound,
2314 const exprt &value_as_byte_array,
2315 const std::optional<exprt> &non_const_update_bound,
2321 widest_member.has_value(),
2322 "lower_byte_update of union of unknown size is not supported");
2326 src.
op(), widest_member->first.get_name(), widest_member->first.
type()});
2327 bu.
type() = widest_member->first.type();
2330 widest_member->first.get_name(),
2345 const exprt &value_as_byte_array,
2346 const std::optional<exprt> &non_const_update_bound,
2349 if(src.
type().
id() == ID_array || src.
type().
id() == ID_vector)
2351 std::optional<typet> subtype;
2352 if(src.
type().
id() == ID_vector)
2361 if(value_as_byte_array.
id() != ID_array)
2364 non_const_update_bound.has_value(),
2365 "constant update bound should yield an array expression");
2367 src, *subtype, value_as_byte_array, *non_const_update_bound, ns);
2374 non_const_update_bound,
2383 value_as_byte_array,
2384 non_const_update_bound,
2388 else if(src.
type().
id() == ID_struct || src.
type().
id() == ID_struct_tag)
2391 src.
type().
id() == ID_struct_tag
2395 src, struct_type, value_as_byte_array, non_const_update_bound, ns);
2399 else if(src.
type().
id() == ID_union || src.
type().
id() == ID_union_tag)
2402 src.
type().
id() == ID_union_tag
2406 src, union_type, value_as_byte_array, non_const_update_bound, ns);
2412 src.
type().
id() == ID_c_enum || src.
type().
id() == ID_c_enum_tag)
2417 CHECK_RETURN(type_width.has_value() && *type_width > 0);
2421 if(value_as_byte_array.
id() == ID_array)
2422 update_bytes = value_as_byte_array.
operands();
2426 value_as_byte_array,
2433 const std::size_t update_size_bits =
2435 const std::size_t bit_width = std::max(type_bits, update_size_bits);
2437 const bool is_little_endian = src.
id() == ID_byte_update_little_endian;
2441 if(bit_width > type_bits)
2448 if(!is_little_endian)
2454 if(non_const_update_bound.has_value())
2458 src.
id() == ID_byte_update_little_endian,
2465 for(std::size_t i = 0; i < update_bytes.size(); ++i)
2471 *non_const_update_bound},
2479 if(is_little_endian)
2484 power(2, bit_width) -
power(2, bit_width - update_size_bits),
2499 if(!is_little_endian)
2512 if(is_little_endian)
2515 exprt zero_extended;
2516 if(bit_width > update_size_bits)
2518 if(is_little_endian)
2530 zero_extended = value;
2535 shl_exprt{zero_extended, offset_in_bits},
2537 if(!is_little_endian)
2546 bitor_exprt bitor_expr{bitand_expr, value_shifted};
2548 if(bit_width > type_bits)
2551 bitor_expr.
type(), src.
id() == ID_byte_update_little_endian, ns);
2552 const auto bounds =
map_bounds(endianness_map, 0, type_bits - 1);
2568 false,
"lower_byte_update does not yet support ", src.
type().
id_string());
2575 src.
id() == ID_byte_update_little_endian ||
2576 src.
id() == ID_byte_update_big_endian,
2577 "byte update expression should either be little or big endian");
2593 std::optional<exprt> non_const_update_bound;
2598 simplify(update_size_expr_opt.value(), ns);
2600 const irep_idt extract_opcode = src.
id() == ID_byte_update_little_endian
2601 ? ID_byte_extract_little_endian
2602 : ID_byte_extract_big_endian;
2605 if(!update_size_expr_opt.value().is_constant())
2606 non_const_update_bound = *update_size_expr_opt;
2614 update_bits.has_value(),
"constant size-of should imply fixed bit width");
2617 if(update_bits_int % bits_per_byte != 0)
2621 "non-byte aligned type expected to be a bitvector type");
2632 const exprt overlapping_byte =
2635 size_t n_extra_bits = bits_per_byte - update_bits_int % bits_per_byte;
2640 update_value,
bv_typet{update_bits_int}),
2647 update_bits_int / bits_per_byte, update_size_expr_opt->type());
2676 src.
id() == ID_byte_update_little_endian ||
2677 src.
id() == ID_byte_update_big_endian)
2682 src.
id() == ID_byte_extract_little_endian ||
2683 src.
id() == ID_byte_extract_big_endian)
API to expression classes for bitvectors.
const shift_exprt & to_shift_expr(const exprt &expr)
Cast an exprt to a shift_exprt.
const concatenation_exprt & to_concatenation_expr(const exprt &expr)
Cast an exprt to a concatenation_exprt.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
Expression classes for byte-level operators.
const byte_update_exprt & to_byte_update_expr(const exprt &expr)
exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
Rewrite a byte extract expression to more fundamental operations.
const byte_extract_exprt & to_byte_extract_expr(const exprt &expr)
unsignedbv_typet size_type()
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Expression to define a mapping from an argument (index) to elements.
Array constructor from list of elements.
typet index_type() const
The type of the index expressions into any instance of this type.
const exprt & size() const
const typet & element_type() const
The type of the elements of the array.
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly two argu...
Bit-wise AND Any number of operands that is greater or equal one.
Bit-wise negation of bit-vectors.
Bit-wise OR Any number of operands that is greater or equal one.
Base class of fixed-width bit-vector types.
constant_exprt all_zeros_expr() const
std::size_t get_width() const
Fixed-width bit-vector without numerical interpretation.
Expression corresponding to op() where the bytes starting at position offset (given in number of byte...
const exprt & offset() const
std::size_t get_bits_per_byte() const
const exprt & value() const
Type for C bit fields These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (...
Complex constructor from a pair of numbers.
Imaginary part of the expression describing a complex number.
Real part of the expression describing a complex number.
Complex numbers made of pair of given subtype.
Concatenation of bit-vector operands.
Union constructor to support unions without any member (a GCC/Clang feature).
Maps a big-endian offset to a little-endian offset.
size_t number_of_bits() const
size_t map_bit(size_t bit) const
Base class for all expressions.
std::vector< exprt > operandst
bool is_constant() const
Return whether the expression is a constant.
typet & type()
Return the type of the expression.
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
The trinary if-then-else operator.
const std::string & id_string() const
const irep_idt & id() const
Extract member of struct or union.
Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
Binary multiplication Associativity is not specified.
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Boolean OR All operands must be boolean, and the result is always boolean.
The plus expression Associativity is not specified.
Fixed-width bit-vector with two's complement interpretation.
Struct constructor from list of elements.
Structure type, corresponds to C style structs.
const componentst & components() const
std::vector< componentt > componentst
Expression to hold a symbol (variable).
const typet & subtype() const
Semantic type conversion.
static exprt conditional_cast(const exprt &expr, const typet &type)
The type of an expression, extends irept.
The unary minus expression.
Union constructor from single element.
std::optional< std::pair< struct_union_typet::componentt, mp_integer > > find_widest_union_component(const namespacet &ns) const
Determine the member of maximum bit width in a union type.
Fixed-width bit-vector with unsigned binary interpretation.
Vector constructor from list of elements.
const constant_exprt & size() const
typet index_type() const
The type of any index expression into an instance of this type.
const typet & element_type() const
The type of the elements of the vector.
Operator to update elements in structs and arrays.
zero extension The operand is converted to the given type by either a) truncating if the new type is ...
#define Forall_operands(it, expr)
bool can_cast_type(const typet &base)
Check whether a reference to a generic typet is of a specific derived class.
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
Deprecated expression utility functions.
static exprt lower_byte_update_union(const byte_update_exprt &src, const union_typet &union_type, const exprt &value_as_byte_array, const std::optional< exprt > &non_const_update_bound, const namespacet &ns)
Apply a byte update src to a union typed operand using the byte array value_as_byte_array as update v...
static exprt lower_byte_update_byte_array_vector(const byte_update_exprt &src, const typet &subtype, const array_exprt &value_as_byte_array, const std::optional< exprt > &non_const_update_bound, const namespacet &ns)
Apply a byte update src to an array/vector of bytes using the byte array value_as_byte_array as updat...
static exprt bv_to_expr(const exprt &bitvector_expr, const typet &target_type, const endianness_mapt &endianness_map, const namespacet &ns)
Convert a bitvector-typed expression bitvector_expr to an expression of type target_type.
static exprt bv_to_union_expr(const exprt &bitvector_expr, const union_typet &union_type, const endianness_mapt &endianness_map, const namespacet &ns)
Convert a bitvector-typed expression bitvector_expr to a union-typed expression.
static complex_exprt bv_to_complex_expr(const exprt &bitvector_expr, const complex_typet &complex_type, const endianness_mapt &endianness_map, const namespacet &ns)
Convert a bitvector-typed expression bitvector_expr to a complex-typed expression.
static array_exprt unpack_struct(const exprt &src, bool little_endian, const std::optional< mp_integer > &offset_bytes, const std::optional< mp_integer > &max_bytes, const std::size_t bits_per_byte, const namespacet &ns)
Rewrite a struct-typed expression into its individual bytes.
static exprt::operandst instantiate_byte_array(const exprt &src, std::size_t lower_bound, std::size_t upper_bound, const std::size_t bits_per_byte, const namespacet &ns)
Build the individual bytes to be used in an update.
exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
rewrite byte extraction from an array to byte extraction from a concatenation of array index expressi...
bitvector_typet adjust_width(const typet &src, std::size_t new_width)
changes the width of the given bitvector type
static vector_exprt bv_to_vector_expr(const exprt &bitvector_expr, const vector_typet &vector_type, const endianness_mapt &endianness_map, const namespacet &ns)
Convert a bitvector-typed expression bitvector_expr to a vector-typed expression.
static void process_bit_fields(exprt::operandst &&bit_fields, std::size_t total_bits, exprt::operandst &dest, bool little_endian, const std::optional< mp_integer > &offset_bytes, const std::optional< mp_integer > &max_bytes, const std::size_t bits_per_byte, const namespacet &ns)
Extract bytes from a sequence of bitvector-typed elements.
static struct_exprt bv_to_struct_expr(const exprt &bitvector_expr, const struct_typet &struct_type, const endianness_mapt &endianness_map, const namespacet &ns)
Convert a bitvector-typed expression bitvector_expr to a struct-typed expression.
static array_exprt unpack_complex(const exprt &src, bool little_endian, const std::size_t bits_per_byte, const namespacet &ns)
Rewrite a complex_exprt into its individual bytes.
static exprt unpack_array_vector_no_known_bounds(const exprt &src, std::size_t el_bytes, bool little_endian, const std::size_t bits_per_byte, const namespacet &ns)
Rewrite an array or vector into its individual bytes when no maximum number of bytes is known.
static exprt lower_byte_update_array_vector(const byte_update_exprt &src, const typet &subtype, const std::optional< mp_integer > &subtype_bits, const exprt &value_as_byte_array, const std::optional< exprt > &non_const_update_bound, const namespacet &ns)
Apply a byte update src to an array/vector typed operand using the byte array value_as_byte_array as ...
static exprt lower_byte_update_array_vector_non_const(const byte_update_exprt &src, const typet &subtype, const exprt &value_as_byte_array, const std::optional< exprt > &non_const_update_bound, const namespacet &ns)
Apply a byte update src to an array/vector typed operand, using the byte array value_as_byte_array as...
static array_exprt bv_to_array_expr(const exprt &bitvector_expr, const array_typet &array_type, const endianness_mapt &endianness_map, const namespacet &ns)
Convert a bitvector-typed expression bitvector_expr to an array-typed expression.
static boundst map_bounds(const endianness_mapt &endianness_map, std::size_t lower_bound, std::size_t upper_bound)
Map bit boundaries according to endianness.
exprt lower_byte_operators(const exprt &src, const namespacet &ns)
Rewrite an expression possibly containing byte-extract or -update expressions to more fundamental ope...
static exprt lower_byte_extract_array_vector(const byte_extract_exprt &src, const byte_extract_exprt &unpacked, const typet &subtype, const mp_integer &element_bits, const namespacet &ns)
Rewrite a byte extraction of an array/vector-typed result to byte extraction of the individual compon...
static exprt lower_byte_update(const byte_update_exprt &src, const exprt &value_as_byte_array, const std::optional< exprt > &non_const_update_bound, const namespacet &ns)
Apply a byte update src using the byte array value_as_byte_array as update value.
static exprt unpack_array_vector(const exprt &src, const std::optional< mp_integer > &src_size, const mp_integer &element_bits, bool little_endian, const std::optional< mp_integer > &offset_bytes, const std::optional< mp_integer > &max_bytes, const std::size_t bits_per_byte, const namespacet &ns)
Rewrite an array or vector into its individual bytes.
static exprt unpack_rec(const exprt &src, bool little_endian, const std::optional< mp_integer > &offset_bytes, const std::optional< mp_integer > &max_bytes, const std::size_t bits_per_byte, const namespacet &ns, bool unpack_byte_array=false)
Rewrite an object into its individual bytes.
static exprt lower_byte_update_struct(const byte_update_exprt &src, const struct_typet &struct_type, const exprt &value_as_byte_array, const std::optional< exprt > &non_const_update_bound, const namespacet &ns)
Apply a byte update src to a struct typed operand using the byte array value_as_byte_array as update ...
static std::optional< exprt > lower_byte_extract_complex(const byte_extract_exprt &src, const byte_extract_exprt &unpacked, const namespacet &ns)
Rewrite a byte extraction of a complex-typed result to byte extraction of the individual components t...
static exprt lower_byte_update_byte_array_vector_non_const(const byte_update_exprt &src, const typet &subtype, const exprt &value_as_byte_array, const exprt &non_const_update_bound, const namespacet &ns)
Apply a byte update src to an array/vector of bytes using the byte-array typed expression value_as_by...
static exprt lower_byte_update_single_element(const byte_update_exprt &src, const mp_integer &offset_bits, const exprt &element_to_update, const mp_integer &subtype_bits, const mp_integer &bits_already_set, const exprt &value_as_byte_array, const std::optional< exprt > &non_const_update_bound, const namespacet &ns)
Byte update a struct/array/vector element.
static exprt lower_byte_update_array_vector_unbounded(const byte_update_exprt &src, const typet &subtype, const exprt &subtype_size, const exprt &value_as_byte_array, const exprt &non_const_update_bound, const exprt &initial_bytes, const exprt &first_index, const exprt &first_update_value, const namespacet &ns)
Apply a byte update src to an array/vector typed operand, using the byte array value_as_byte_array as...
output_type narrow_cast(input_type value)
Alias for static_cast intended to be used for numeric casting Rationale: Easier to grep than static_c...
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
std::optional< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
std::optional< mp_integer > member_offset_bits(const struct_typet &type, const irep_idt &member, const namespacet &ns)
std::optional< exprt > size_of_expr(const typet &type, const namespacet &ns)
std::optional< exprt > member_offset_expr(const member_exprt &member_expr, const namespacet &ns)
const std::size_t sharing_mapt< keyT, valueT, fail_if_equal, hashT, equalT >::mask
bool simplify(exprt &expr, const namespacet &ns)
exprt simplify_expr(exprt src, const namespacet &ns)
#define PRECONDITION_WITH_DIAGNOSTICS(CONDITION,...)
#define CHECK_RETURN(CONDITION)
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
#define PRECONDITION(CONDITION)
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
const array_exprt & to_array_expr(const exprt &expr)
Cast an exprt to an array_exprt.
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
const vector_typet & to_vector_type(const typet &type)
Cast a typet to a vector_typet.
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
const complex_typet & to_complex_type(const typet &type)
Cast a typet to a complex_typet.
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
const string_constantt & to_string_constant(const exprt &expr)
static bool failed(bool error_indicator)
const type_with_subtypet & to_type_with_subtype(const typet &type)