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);
1073 auto const byte_type =
bv_typet{bits_per_byte};
1078 for(; bit_offset < last_bit; bit_offset += bits_per_byte)
1091 byte_operands.push_back(extractbits);
1093 byte_operands.insert(byte_operands.begin(), extractbits);
1096 const std::size_t size = byte_operands.size();
1098 return array_exprt{std::move(byte_operands), std::move(array_type)};
1118 const typet &subtype,
1122 std::optional<std::size_t> num_elements;
1123 if(src.
type().
id() == ID_array)
1128 if(num_elements.has_value())
1131 operands.reserve(*num_elements);
1132 for(std::size_t i = 0; i < *num_elements; ++i)
1141 tmp.
type() = subtype;
1142 tmp.
offset() = new_offset;
1148 if(src.
type().
id() == ID_array)
1161 static std::size_t array_comprehension_index_counter = 0;
1162 ++array_comprehension_index_counter;
1164 "$array_comprehension_index_a" +
1165 std::to_string(array_comprehension_index_counter),
1172 array_comprehension_index,
1175 array_comprehension_index.
type())},
1176 unpacked.
offset().type())};
1179 body.
type() = subtype;
1180 body.
offset() = std::move(new_offset);
1183 std::move(array_comprehension_index),
1210 real.
type() = subtype;
1217 imag.
type() = subtype;
1276 src.
id() == ID_byte_extract_little_endian ||
1277 src.
id() == ID_byte_extract_big_endian);
1278 const bool little_endian = src.
id() == ID_byte_extract_little_endian;
1282 if(upper_bound_opt.has_value())
1286 upper_bound_opt.value(),
1288 src.
offset(), upper_bound_opt.value().
type())),
1291 else if(src.
type().
id() == ID_empty)
1295 const auto upper_bound_int_opt =
1302 lower_bound_int_opt,
1303 upper_bound_int_opt,
1310 if(src.
type().
id() == ID_array || src.
type().
id() == ID_vector)
1319 element_bits.has_value() && *element_bits >= 1 &&
1323 src, unpacked, subtype, *element_bits, ns);
1326 else if(src.
type().
id() == ID_complex)
1329 if(result.has_value())
1330 return std::move(*result);
1334 else if(src.
type().
id() == ID_struct || src.
type().
id() == ID_struct_tag)
1337 src.
type().
id() == ID_struct_tag
1345 for(
const auto &comp : components)
1351 !component_bits.has_value() ||
1358 auto member_offset_opt =
1361 if(!member_offset_opt.has_value())
1370 member_offset_opt.value(), unpacked.
offset().
type()));
1373 tmp.
type() = comp.type();
1374 tmp.
offset() = new_offset;
1382 else if(src.
type().
id() == ID_union || src.
type().
id() == ID_union_tag)
1385 src.
type().
id() == ID_union_tag
1391 if(widest_member.has_value())
1394 tmp.
type() = widest_member->first.type();
1397 widest_member->first.get_name(),
1403 const exprt &root = unpacked.
op();
1406 std::optional<typet> subtype;
1407 std::optional<typet> index_type;
1408 if(root.
type().
id() == ID_vector)
1423 "offset bits are byte aligned");
1426 if(!size_bits.has_value())
1431 op0_bits.has_value(),
1432 "the extracted width or the source width must be known");
1433 size_bits = op0_bits;
1443 op.reserve(width_bytes);
1445 for(std::size_t i = 0; i < width_bytes; i++)
1448 std::size_t offset_int = little_endian ? (width_bytes - i - 1) : i;
1458 (root.
id() == ID_array || root.
id() == ID_vector) &&
1460 index < root.
operands().size() && index >= 0)
1471 if(width_bytes == 1)
1489 const exprt &value_as_byte_array,
1490 const std::optional<exprt> &non_const_update_bound,
1504 const typet &subtype,
1505 const exprt &value_as_byte_array,
1506 const exprt &non_const_update_bound,
1511 static std::size_t array_comprehension_index_counter = 0;
1512 ++array_comprehension_index_counter;
1514 "$array_comprehension_index_u_a_v" +
1515 std::to_string(array_comprehension_index_counter),
1520 array_comprehension_index, src.
offset().
type()),
1525 array_comprehension_index, non_const_update_bound.
type()),
1529 src.
offset(), non_const_update_bound.
type()),
1530 non_const_update_bound}};
1533 src.
id() == ID_byte_update_little_endian ||
1534 src.
id() == ID_byte_update_big_endian);
1535 const bool little_endian = src.
id() == ID_byte_update_little_endian;
1541 or_exprt{std::move(lower_bound), std::move(upper_bound)},
1545 value_as_byte_array,
1547 array_comprehension_index,
1549 src.
offset(), array_comprehension_index.
type())}},
1556 array_comprehension_index,
1557 std::move(array_comprehension_body),
1573 const typet &subtype,
1575 const std::optional<exprt> &non_const_update_bound,
1579 src.
id() == ID_byte_update_little_endian ||
1580 src.
id() == ID_byte_update_big_endian);
1581 const bool little_endian = src.
id() == ID_byte_update_little_endian;
1583 const typet index_type = src.
type().
id() == ID_array
1590 for(std::size_t i = 0; i < value_as_byte_array.
operands().size(); ++i)
1603 if(e.id() == ID_index)
1606 if(index_expr.
array() == src.
op() && index_expr.
index() == where)
1612 if(non_const_update_bound.has_value())
1618 *non_const_update_bound},
1623 result =
with_exprt{result, std::move(where), std::move(update_value)};
1646 const typet &subtype,
1647 const exprt &subtype_size,
1648 const exprt &value_as_byte_array,
1649 const exprt &non_const_update_bound,
1650 const exprt &initial_bytes,
1651 const exprt &first_index,
1652 const exprt &first_update_value,
1655 const irep_idt extract_opcode = src.
id() == ID_byte_update_little_endian
1656 ? ID_byte_extract_little_endian
1657 : ID_byte_extract_big_endian;
1661 static std::size_t array_comprehension_index_counter = 0;
1662 ++array_comprehension_index_counter;
1664 "$array_comprehension_index_u_a_v_u" +
1665 std::to_string(array_comprehension_index_counter),
1677 array_comprehension_index, first_index.
type()),
1688 array_comprehension_index, first_index.
type()),
1693 value_as_byte_array,
1694 std::move(offset_expr),
1706 non_const_update_bound, subtype_size.
type()),
1721 non_const_update_bound, initial_bytes.
type()),
1723 subtype_size.
type()),
1730 array_comprehension_index, last_index.
type()),
1745 value_as_byte_array,
1750 or_exprt{std::move(lower_bound), std::move(upper_bound)},
1755 array_comprehension_index, first_index.
type()),
1761 array_comprehension_index, last_index.
type()),
1763 std::move(last_update_value),
1764 std::move(update_value)}}};
1768 array_comprehension_index,
1769 std::move(array_comprehension_body),
1786 const typet &subtype,
1787 const exprt &value_as_byte_array,
1788 const std::optional<exprt> &non_const_update_bound,
1798 subtype_size_opt.value(), src.
offset().
type()),
1813 const exprt update_size =
1817 if(non_const_update_bound.has_value())
1820 *non_const_update_bound, subtype_size.
type());
1825 value_as_byte_array.
id() == ID_array,
1826 "value should be an array expression if the update bound is constant");
1827 update_bound = update_size;
1843 value_as_byte_array,
1847 if(value_as_byte_array.
id() != ID_array)
1853 value_as_byte_array,
1854 *non_const_update_bound,
1866 std::size_t step_size = 1;
1873 std::size_t offset = 0;
1877 with_exprt result{src.
op(), first_index, first_update_value};
1879 auto lower_byte_update_array_vector_non_const_one_element =
1884 &value_as_byte_array,
1886 &result](std::size_t i) ->
void {
1901 value_as_byte_array,
1905 result =
with_exprt{result, std::move(where), std::move(element)};
1909 for(; offset + step_size <= value_as_byte_array.
operands().size();
1910 offset += step_size, ++i)
1912 lower_byte_update_array_vector_non_const_one_element(i);
1916 if(offset < value_as_byte_array.
operands().size())
1917 lower_byte_update_array_vector_non_const_one_element(i);
1937 const exprt &element_to_update,
1940 const exprt &value_as_byte_array,
1941 const std::optional<exprt> &non_const_update_bound,
1949 std::size_t first = 0;
1956 mp_integer offset_bits_in_target_element = offset_bits - bits_already_set;
1958 if(offset_bits_in_target_element < 0)
1961 value_as_byte_array.
id() != ID_array ||
1963 -offset_bits_in_target_element,
1964 "indices past the update should be handled below");
1967 offset_bits_in_target_element +=
1970 if(offset_bits_in_target_element < 0)
1977 update_elements > 0,
"indices before the update should be handled above");
1981 if(value_as_byte_array.
id() == ID_array)
1982 end = std::min(end, value_as_byte_array.
operands().size());
1985 const std::size_t update_size = update_values.size();
1994 offset_bits_in_target_element >= 0 &&
1997 new_value =
array_exprt{update_values, update_type};
2001 if(src.
id() == ID_byte_update_little_endian)
2002 std::reverse(update_values.begin(), update_values.end());
2003 if(offset_bits_in_target_element < 0)
2005 if(src.
id() == ID_byte_update_little_endian)
2022 const std::size_t offset_bits_int =
2024 const std::size_t subtype_bits_int =
2029 subtype_bits_int - offset_bits_int,
2041 const irep_idt extract_opcode = src.
id() == ID_byte_update_little_endian
2042 ? ID_byte_extract_little_endian
2043 : ID_byte_extract_big_endian;
2054 offset_bits_in_target_element = 0;
2069 std::optional<exprt> update_bound;
2070 if(non_const_update_bound.has_value())
2078 *non_const_update_bound,
2082 *non_const_update_bound,
2092 remaining_update_bytes},
2111 const typet &subtype,
2112 const std::optional<mp_integer> &subtype_bits,
2113 const exprt &value_as_byte_array,
2114 const std::optional<exprt> &non_const_update_bound,
2117 const bool is_array = src.
type().
id() == ID_array;
2134 !subtype_bits.has_value() || value_as_byte_array.
id() != ID_array)
2137 src, subtype, value_as_byte_array, non_const_update_bound, ns);
2140 std::size_t num_elements =
2147 elements.reserve(num_elements);
2151 for(; i < num_elements && (i + 1) * *subtype_bits <= offset_bits; ++i)
2152 elements.push_back(
index_exprt{src.op(), from_integer(i, index_type)});
2157 i * *subtype_bits < offset_bits + value_as_byte_array.
operands().size() *
2167 value_as_byte_array,
2168 non_const_update_bound,
2173 for(; i < num_elements; ++i)
2174 elements.push_back(
index_exprt{src.op(), from_integer(i, index_type)});
2196 const exprt &value_as_byte_array,
2197 const std::optional<exprt> &non_const_update_bound,
2201 elements.reserve(struct_type.
components().size());
2204 for(
const auto &comp : struct_type.
components())
2218 if(!offset_bits.has_value() || !element_width.has_value())
2225 const irep_idt extract_opcode = src.
id() == ID_byte_update_little_endian
2226 ? ID_byte_extract_little_endian
2227 : ID_byte_extract_big_endian;
2247 bu, value_as_byte_array, non_const_update_bound, ns),
2262 *offset_bits >= *element_width ||
2263 (value_as_byte_array.
id() == ID_array && *offset_bits < 0 &&
2267 elements.push_back(member);
2278 value_as_byte_array,
2279 non_const_update_bound,
2300 const exprt &value_as_byte_array,
2301 const std::optional<exprt> &non_const_update_bound,
2307 widest_member.has_value(),
2308 "lower_byte_update of union of unknown size is not supported");
2312 src.
op(), widest_member->first.get_name(), widest_member->first.
type()});
2313 bu.
type() = widest_member->first.type();
2316 widest_member->first.get_name(),
2331 const exprt &value_as_byte_array,
2332 const std::optional<exprt> &non_const_update_bound,
2335 if(src.
type().
id() == ID_array || src.
type().
id() == ID_vector)
2337 std::optional<typet> subtype;
2338 if(src.
type().
id() == ID_vector)
2347 if(value_as_byte_array.
id() != ID_array)
2350 non_const_update_bound.has_value(),
2351 "constant update bound should yield an array expression");
2353 src, *subtype, value_as_byte_array, *non_const_update_bound, ns);
2360 non_const_update_bound,
2369 value_as_byte_array,
2370 non_const_update_bound,
2374 else if(src.
type().
id() == ID_struct || src.
type().
id() == ID_struct_tag)
2377 src.
type().
id() == ID_struct_tag
2381 src, struct_type, value_as_byte_array, non_const_update_bound, ns);
2385 else if(src.
type().
id() == ID_union || src.
type().
id() == ID_union_tag)
2388 src.
type().
id() == ID_union_tag
2392 src, union_type, value_as_byte_array, non_const_update_bound, ns);
2398 src.
type().
id() == ID_c_enum || src.
type().
id() == ID_c_enum_tag)
2403 CHECK_RETURN(type_width.has_value() && *type_width > 0);
2407 if(value_as_byte_array.
id() == ID_array)
2408 update_bytes = value_as_byte_array.
operands();
2412 value_as_byte_array,
2419 const std::size_t update_size_bits =
2421 const std::size_t bit_width = std::max(type_bits, update_size_bits);
2423 const bool is_little_endian = src.
id() == ID_byte_update_little_endian;
2427 if(bit_width > type_bits)
2434 if(!is_little_endian)
2440 if(non_const_update_bound.has_value())
2444 src.
id() == ID_byte_update_little_endian,
2451 for(std::size_t i = 0; i < update_bytes.size(); ++i)
2457 *non_const_update_bound},
2465 if(is_little_endian)
2470 power(2, bit_width) -
power(2, bit_width - update_size_bits),
2485 if(!is_little_endian)
2498 if(is_little_endian)
2501 exprt zero_extended;
2502 if(bit_width > update_size_bits)
2504 if(is_little_endian)
2516 zero_extended = value;
2521 shl_exprt{zero_extended, offset_in_bits},
2523 if(!is_little_endian)
2532 bitor_exprt bitor_expr{bitand_expr, value_shifted};
2534 if(bit_width > type_bits)
2537 bitor_expr.
type(), src.
id() == ID_byte_update_little_endian, ns);
2538 const auto bounds =
map_bounds(endianness_map, 0, type_bits - 1);
2554 false,
"lower_byte_update does not yet support ", src.
type().
id_string());
2561 src.
id() == ID_byte_update_little_endian ||
2562 src.
id() == ID_byte_update_big_endian,
2563 "byte update expression should either be little or big endian");
2579 std::optional<exprt> non_const_update_bound;
2584 simplify(update_size_expr_opt.value(), ns);
2586 const irep_idt extract_opcode = src.
id() == ID_byte_update_little_endian
2587 ? ID_byte_extract_little_endian
2588 : ID_byte_extract_big_endian;
2591 if(!update_size_expr_opt.value().is_constant())
2592 non_const_update_bound = *update_size_expr_opt;
2600 update_bits.has_value(),
"constant size-of should imply fixed bit width");
2603 if(update_bits_int % bits_per_byte != 0)
2607 "non-byte aligned type expected to be a bitvector type");
2618 const exprt overlapping_byte =
2621 size_t n_extra_bits = bits_per_byte - update_bits_int % bits_per_byte;
2626 update_value,
bv_typet{update_bits_int}),
2633 update_bits_int / bits_per_byte, update_size_expr_opt->type());
2662 src.
id() == ID_byte_update_little_endian ||
2663 src.
id() == ID_byte_update_big_endian)
2668 src.
id() == ID_byte_extract_little_endian ||
2669 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)