26 const exprt &bitvector_expr,
27 const typet &target_type,
40 std::size_t lower_bound,
41 std::size_t upper_bound)
44 result.
lb = lower_bound;
45 result.
ub = upper_bound;
53 if(result.
ub < result.
lb)
54 std::swap(result.
lb, result.
ub);
63 if(src.
id() == ID_unsignedbv)
65 else if(src.
id() == ID_signedbv)
67 else if(src.
id() == ID_bv)
69 else if(src.
id() == ID_c_enum)
71 else if(src.
id() == ID_c_bit_field)
81 const exprt &bitvector_expr,
89 operands.reserve(components.size());
91 for(
const auto &comp : components)
94 std::size_t component_bits;
95 if(component_bits_opt.has_value())
96 component_bits = numeric_cast_v<std::size_t>(*component_bits_opt);
101 if(component_bits == 0)
119 if(component_bits_opt.has_value())
129 const exprt &bitvector_expr,
137 if(components.empty())
142 std::size_t component_bits;
143 if(widest_member.has_value())
144 component_bits = numeric_cast_v<std::size_t>(widest_member->second);
148 if(component_bits == 0)
155 const auto bounds =
map_bounds(endianness_map, 0, component_bits - 1);
157 const irep_idt &component_name = widest_member.has_value()
158 ? widest_member->first.get_name()
159 : components.front().get_name();
160 const typet &component_type = widest_member.has_value()
161 ? widest_member->first.type()
162 : components.front().type();
177 const exprt &bitvector_expr,
182 auto num_elements = numeric_cast<std::size_t>(array_type.
size());
185 const std::size_t total_bits =
187 if(!num_elements.has_value())
189 if(!subtype_bits.has_value() || *subtype_bits == 0)
190 num_elements = total_bits;
192 num_elements = total_bits / numeric_cast_v<std::size_t>(*subtype_bits);
195 !num_elements.has_value() || !subtype_bits.has_value() ||
196 *subtype_bits * *num_elements == total_bits,
197 "subtype width times array size should be total bitvector width");
200 operands.reserve(*num_elements);
201 for(std::size_t i = 0; i < *num_elements; ++i)
203 if(subtype_bits.has_value())
205 const std::size_t subtype_bits_int =
206 numeric_cast_v<std::size_t>(*subtype_bits);
208 endianness_map, i * subtype_bits_int, ((i + 1) * subtype_bits_int) - 1);
214 bitvector_expr, bounds.ub, bounds.lb, std::move(type)},
222 bitvector_expr, array_type.
element_type(), endianness_map, ns));
226 return array_exprt{std::move(operands), array_type};
232 const exprt &bitvector_expr,
237 const std::size_t num_elements =
238 numeric_cast_v<std::size_t>(vector_type.
size());
241 !subtype_bits.has_value() ||
242 *subtype_bits * num_elements ==
244 "subtype width times vector size should be total bitvector width");
247 operands.reserve(num_elements);
248 for(std::size_t i = 0; i < num_elements; ++i)
250 if(subtype_bits.has_value())
252 const std::size_t subtype_bits_int =
253 numeric_cast_v<std::size_t>(*subtype_bits);
255 endianness_map, i * subtype_bits_int, ((i + 1) * subtype_bits_int) - 1);
261 bitvector_expr, bounds.ub, bounds.lb, std::move(type)},
269 bitvector_expr, vector_type.
element_type(), endianness_map, ns));
279 const exprt &bitvector_expr,
284 const std::size_t total_bits =
287 std::size_t subtype_bits;
288 if(subtype_bits_opt.has_value())
290 subtype_bits = numeric_cast_v<std::size_t>(*subtype_bits_opt);
292 subtype_bits * 2 == total_bits,
293 "subtype width should be half of the total bitvector width");
296 subtype_bits = total_bits / 2;
298 const auto bounds_real =
map_bounds(endianness_map, 0, subtype_bits - 1);
299 const auto bounds_imag =
300 map_bounds(endianness_map, subtype_bits, subtype_bits * 2 - 1);
334 const exprt &bitvector_expr,
335 const typet &target_type,
343 target_type.
id() == ID_c_enum || target_type.
id() == ID_c_enum_tag ||
344 target_type.
id() == ID_string)
353 if(target_type.
id() == ID_struct)
358 else if(target_type.
id() == ID_struct_tag)
365 result.
type() = target_type;
366 return std::move(result);
368 else if(target_type.
id() == ID_union)
371 bitvector_expr,
to_union_type(target_type), endianness_map, ns);
373 else if(target_type.
id() == ID_union_tag)
380 result.
type() = target_type;
381 return std::move(result);
383 else if(target_type.
id() == ID_array)
386 bitvector_expr,
to_array_type(target_type), endianness_map, ns);
388 else if(target_type.
id() == ID_vector)
393 else if(target_type.
id() == ID_complex)
401 false,
"bv_to_expr does not yet support ", target_type.
id_string());
411 bool unpack_byte_array =
false);
421 std::size_t lower_bound,
422 std::size_t upper_bound,
427 if(src.
id() == ID_array)
431 src.
operands().begin() + narrow_cast<std::ptrdiff_t>(lower_bound),
432 src.
operands().begin() + narrow_cast<std::ptrdiff_t>(upper_bound)};
442 bytes.reserve(upper_bound - lower_bound);
443 for(std::size_t i = lower_bound; i < upper_bound; ++i)
460 std::size_t el_bytes,
466 static std::size_t array_comprehension_index_counter = 0;
467 ++array_comprehension_index_counter;
469 "$array_comprehension_index_a_v" +
480 exprt body = sub_operands.front();
482 array_comprehension_index,
483 from_integer(el_bytes, array_comprehension_index.type())};
484 for(std::size_t i = 1; i < el_bytes; ++i)
492 const exprt array_vector_size = src.
type().
id() == ID_vector
497 std::move(array_comprehension_index),
526 const std::size_t el_bytes =
527 numeric_cast_v<std::size_t>((element_bits + 7) / 8);
529 if(!src_size.has_value() && !max_bytes.has_value())
532 el_bytes > 0 && element_bits % 8 == 0,
533 "unpacking of arrays with non-byte-aligned elements is not supported");
535 src, el_bytes, little_endian, ns);
544 if(element_bits > 0 && element_bits % 8 == 0)
546 if(!num_elements.has_value())
549 num_elements = (*max_bytes + el_bytes - 1) / el_bytes;
552 if(offset_bytes.has_value())
555 first_element = *offset_bytes / el_bytes;
557 byte_operands.resize(
558 numeric_cast_v<std::size_t>(*offset_bytes - (*offset_bytes % el_bytes)),
567 num_elements = *max_bytes;
571 for(
mp_integer i = first_element; i < *num_elements; ++i)
576 (src_simp.
id() == ID_array || src_simp.
id() == ID_vector) &&
579 const std::size_t index_int = numeric_cast_v<std::size_t>(i);
580 element = src_simp.
operands()[index_int];
592 ? std::min(
mp_integer{el_bytes}, *max_bytes - byte_operands.size())
594 const std::size_t element_max_bytes_int =
595 element_max_bytes ? numeric_cast_v<std::size_t>(*element_max_bytes)
599 unpack_rec(element, little_endian, {}, element_max_bytes, ns,
true);
602 byte_operands.insert(
603 byte_operands.end(), sub_operands.begin(), sub_operands.end());
605 if(max_bytes && byte_operands.size() >= *max_bytes)
609 const std::size_t size = byte_operands.size();
611 std::move(byte_operands),
627 std::size_t total_bits,
638 unpack_rec(concatenation, little_endian, offset_bytes, max_bytes, ns,
true);
642 std::make_move_iterator(sub.
operands().begin()),
643 std::make_move_iterator(sub.
operands().end()));
671 for(
auto it = components.begin(); it != components.end(); ++it)
673 const auto &comp = *it;
682 component_bits.has_value() ||
683 (std::next(it) == components.end() && !bit_fields.has_value()),
684 "members of non-constant width should come last in a struct");
687 if(src.
id() == ID_struct)
693 if(bit_fields.has_value())
696 std::move(bit_fields->first),
706 if(offset_bytes.has_value())
711 if(*offset_in_member < 0)
712 offset_in_member.reset();
715 if(max_bytes.has_value())
718 if(*max_bytes_left < 0)
725 (component_bits.has_value() && *component_bits % 8 != 0))
727 if(!bit_fields.has_value())
730 const std::size_t bits_int = numeric_cast_v<std::size_t>(*component_bits);
731 bit_fields->first.insert(
732 little_endian ? bit_fields->first.begin() : bit_fields->first.end(),
734 bit_fields->second += bits_int;
742 !bit_fields.has_value(),
743 "all preceding members should have been processed");
746 member, little_endian, offset_in_member, max_bytes_left, ns,
true);
748 byte_operands.insert(
750 std::make_move_iterator(sub.
operands().begin()),
751 std::make_move_iterator(sub.
operands().end()));
753 if(component_bits.has_value())
757 if(bit_fields.has_value())
759 std::move(bit_fields->first),
767 const std::size_t size = byte_operands.size();
803 byte_operands.insert(
805 std::make_move_iterator(sub_imag.
operands().begin()),
806 std::make_move_iterator(sub_imag.
operands().end()));
808 const std::size_t size = byte_operands.size();
830 bool unpack_byte_array)
832 if(src.
type().
id()==ID_array)
840 if(!unpack_byte_array && *element_bits == 8)
843 const auto constant_size_opt = numeric_cast<mp_integer>(array_type.
size());
853 else if(src.
type().
id() == ID_vector)
861 if(!unpack_byte_array && *element_bits == 8)
866 numeric_cast_v<mp_integer>(vector_type.
size()),
873 else if(src.
type().
id() == ID_complex)
877 else if(src.
type().
id() == ID_struct || src.
type().
id() == ID_struct_tag)
879 return unpack_struct(src, little_endian, offset_bytes, max_bytes, ns);
881 else if(src.
type().
id() == ID_union || src.
type().
id() == ID_union_tag)
887 if(widest_member.has_value())
890 src, widest_member->first.get_name(), widest_member->first.
type()};
892 member, little_endian, offset_bytes, widest_member->second, ns,
true);
895 else if(src.
type().
id() == ID_pointer)
905 else if(src.
id() == ID_string_constant)
915 else if(src.
id() == ID_constant && src.
type().
id() == ID_string)
925 else if(src.
type().
id()!=ID_empty)
930 DATA_INVARIANT(bits_opt.has_value(),
"basic type should have a fixed size");
936 if(max_bytes.has_value())
938 const auto max_bits = *max_bytes * 8;
941 last_bit = std::min(last_bit, max_bits);
945 bit_offset = std::max(
mp_integer{0}, last_bit - max_bits);
950 src,
bv_typet{numeric_cast_v<std::size_t>(total_bits)});
953 for(; bit_offset < last_bit; bit_offset += 8)
967 byte_operands.push_back(extractbits);
969 byte_operands.insert(byte_operands.begin(), extractbits);
972 const std::size_t size = byte_operands.size();
974 std::move(byte_operands),
995 const typet &subtype,
1000 if(src.
type().
id() == ID_array)
1005 if(num_elements.has_value())
1008 operands.reserve(*num_elements);
1009 for(std::size_t i = 0; i < *num_elements; ++i)
1016 tmp.
type() = subtype;
1017 tmp.
offset() = new_offset;
1023 if(src.
type().
id() == ID_array)
1036 static std::size_t array_comprehension_index_counter = 0;
1037 ++array_comprehension_index_counter;
1039 "$array_comprehension_index_a" +
1047 array_comprehension_index,
1048 from_integer(element_bits / 8, array_comprehension_index.type())},
1052 body.
type() = subtype;
1053 body.
offset() = std::move(new_offset);
1077 if(!subtype_bits.has_value() || *subtype_bits % 8 != 0)
1082 real.
type() = subtype;
1088 imag.
type() = subtype;
1147 src.
id() == ID_byte_extract_little_endian ||
1148 src.
id() == ID_byte_extract_big_endian);
1149 const bool little_endian = src.
id() == ID_byte_extract_little_endian;
1153 if(upper_bound_opt.has_value())
1157 upper_bound_opt.value(),
1159 src.
offset(), upper_bound_opt.value().
type())),
1162 else if(src.
type().
id() == ID_empty)
1165 const auto lower_bound_int_opt = numeric_cast<mp_integer>(src.
offset());
1166 const auto upper_bound_int_opt =
1167 numeric_cast<mp_integer>(upper_bound_opt.value_or(
nil_exprt()));
1171 src.
op(), little_endian, lower_bound_int_opt, upper_bound_int_opt, ns);
1176 if(src.
type().
id() == ID_array || src.
type().
id() == ID_vector)
1184 if(element_bits.has_value() && *element_bits >= 1 && *element_bits % 8 == 0)
1187 src, unpacked, subtype, *element_bits, ns);
1190 else if(src.
type().
id() == ID_complex)
1193 if(result.has_value())
1194 return std::move(*result);
1198 else if(src.
type().
id() == ID_struct || src.
type().
id() == ID_struct_tag)
1206 for(
const auto &comp : components)
1212 !component_bits.has_value() || *component_bits == 0 ||
1213 *component_bits % 8 != 0)
1219 auto member_offset_opt =
1222 if(!member_offset_opt.has_value())
1231 member_offset_opt.value(), unpacked.
offset().
type()));
1234 tmp.
type()=comp.type();
1243 else if(src.
type().
id() == ID_union || src.
type().
id() == ID_union_tag)
1249 if(widest_member.has_value())
1252 tmp.
type() = widest_member->first.type();
1255 widest_member->first.get_name(),
1261 const exprt &root=unpacked.
op();
1265 if(root.
type().
id() == ID_vector)
1273 subtype_bits.has_value() && *subtype_bits == 8,
1274 "offset bits are byte aligned");
1277 if(!size_bits.has_value())
1282 op0_bits.has_value(),
1283 "the extracted width or the source width must be known");
1284 size_bits = op0_bits;
1287 mp_integer num_bytes = (*size_bits) / 8 + (((*size_bits) % 8 == 0) ? 0 : 1);
1290 const std::size_t width_bytes = numeric_cast_v<std::size_t>(num_bytes);
1292 op.reserve(width_bytes);
1294 for(std::size_t i=0; i<width_bytes; i++)
1297 std::size_t offset_int=
1298 little_endian?(width_bytes-i-1):i;
1305 offset_i.is_constant() &&
1306 (root.
id() == ID_array || root.
id() == ID_vector) &&
1308 index < root.
operands().size() && index >= 0)
1311 op.push_back(root.
operands()[numeric_cast_v<std::size_t>(index)]);
1327 std::move(op),
adjust_width(*subtype, width_bytes * 8));
1336 const exprt &value_as_byte_array,
1351 const typet &subtype,
1352 const exprt &value_as_byte_array,
1353 const exprt &non_const_update_bound,
1358 static std::size_t array_comprehension_index_counter = 0;
1359 ++array_comprehension_index_counter;
1361 "$array_comprehension_index_u_a_v" +
1367 array_comprehension_index, src.
offset().
type()),
1372 array_comprehension_index, non_const_update_bound.
type()),
1375 src.
offset(), non_const_update_bound.
type()),
1376 non_const_update_bound}};
1379 or_exprt{std::move(lower_bound), std::move(upper_bound)},
1383 value_as_byte_array,
1386 src.
offset(), array_comprehension_index.
type())}},
1391 std::move(array_comprehension_body),
1407 const typet &subtype,
1415 for(std::size_t i = 0; i < value_as_byte_array.
operands().size(); ++i)
1425 if(e.id() == ID_index)
1428 if(index_expr.
array() == src.
op() && index_expr.
index() == where)
1433 if(non_const_update_bound.has_value())
1439 *non_const_update_bound},
1447 if(result.
id() != ID_with)
1448 result =
with_exprt{result, std::move(where), std::move(update_value)};
1473 const typet &subtype,
1474 const exprt &subtype_size,
1475 const exprt &value_as_byte_array,
1476 const exprt &non_const_update_bound,
1477 const exprt &initial_bytes,
1478 const exprt &first_index,
1479 const exprt &first_update_value,
1482 const irep_idt extract_opcode = src.
id() == ID_byte_update_little_endian
1483 ? ID_byte_extract_little_endian
1484 : ID_byte_extract_big_endian;
1488 static std::size_t array_comprehension_index_counter = 0;
1489 ++array_comprehension_index_counter;
1491 "$array_comprehension_index_u_a_v_u" +
1503 array_comprehension_index, first_index.
type()),
1512 array_comprehension_index, first_index.
type()),
1517 extract_opcode, value_as_byte_array, std::move(offset_expr), subtype},
1526 non_const_update_bound, subtype_size.
type()),
1538 non_const_update_bound, initial_bytes.
type()),
1546 array_comprehension_index, last_index.type()),
1559 value_as_byte_array,
1561 last_index, subtype_size.
type()),
1567 or_exprt{std::move(lower_bound), std::move(upper_bound)},
1571 array_comprehension_index, first_index.
type()),
1575 array_comprehension_index, last_index.type()),
1577 std::move(last_update_value),
1578 std::move(update_value)}}};
1582 std::move(array_comprehension_body),
1599 const typet &subtype,
1600 const exprt &value_as_byte_array,
1604 const irep_idt extract_opcode = src.
id() == ID_byte_update_little_endian
1605 ? ID_byte_extract_little_endian
1606 : ID_byte_extract_big_endian;
1615 subtype_size_opt.value(), src.
offset().
type()),
1630 if(non_const_update_bound.has_value())
1633 *non_const_update_bound, subtype_size.
type());
1638 value_as_byte_array.
id() == ID_array,
1639 "value should be an array expression if the update bound is constant");
1657 value_as_byte_array,
1662 if(value_as_byte_array.
id() != ID_array)
1668 value_as_byte_array,
1669 *non_const_update_bound,
1681 std::size_t step_size = 1;
1688 std::size_t offset = 0;
1692 with_exprt result{src.
op(), first_index, first_update_value};
1695 for(; offset + step_size <= value_as_byte_array.
operands().size();
1696 offset += step_size, ++i)
1713 value_as_byte_array,
1714 std::move(offset_expr),
1722 if(offset < value_as_byte_array.
operands().size())
1724 const std::size_t tail_size =
1725 value_as_byte_array.
operands().size() - offset;
1737 value_as_byte_array,
1759 const typet &subtype,
1760 const exprt &value_as_byte_array,
1764 const bool is_array = src.
type().
id() == ID_array;
1776 !subtype_bits.has_value() || *subtype_bits == 0 || *subtype_bits % 8 != 0 ||
1777 non_const_update_bound.has_value() || value_as_byte_array.
id() != ID_array)
1780 src, subtype, value_as_byte_array, non_const_update_bound, ns);
1783 std::size_t num_elements =
1789 elements.reserve(num_elements);
1793 for(; i < num_elements && (i + 1) * *subtype_bits <= offset_bytes * 8; ++i)
1797 for(; i < num_elements &&
1799 (offset_bytes + value_as_byte_array.operands().size()) * 8;
1802 mp_integer update_offset = offset_bytes - i * (*subtype_bits / 8);
1803 mp_integer update_elements = *subtype_bits / 8;
1804 exprt::operandst::const_iterator first =
1805 value_as_byte_array.operands().begin();
1806 exprt::operandst::const_iterator end = value_as_byte_array.operands().end();
1807 if(update_offset < 0)
1810 value_as_byte_array.operands().size() > -update_offset,
1811 "indices past the update should be handled above");
1812 first += numeric_cast_v<std::ptrdiff_t>(-update_offset);
1816 update_elements -= update_offset;
1818 update_elements > 0,
1819 "indices before the update should be handled above");
1822 if(std::distance(first, end) > update_elements)
1823 end = first + numeric_cast_v<std::ptrdiff_t>(update_elements);
1825 const std::size_t update_size = update_values.size();
1830 from_integer(update_offset < 0 ? 0 : update_offset, src.offset().type()),
1832 std::move(update_values),
1838 for(; i < num_elements; ++i)
1839 elements.push_back(
index_exprt{src.op(), from_integer(i, c_index_type())});
1861 const exprt &value_as_byte_array,
1865 const irep_idt extract_opcode = src.
id() == ID_byte_update_little_endian
1866 ? ID_byte_extract_little_endian
1867 : ID_byte_extract_big_endian;
1870 elements.reserve(struct_type.
components().size());
1873 for(
const auto &comp : struct_type.
components())
1885 auto offset_bytes = numeric_cast<mp_integer>(offset);
1892 offset_bytes.has_value() &&
1893 (*offset_bytes * 8 >= *element_width ||
1894 (value_as_byte_array.
id() == ID_array && *offset_bytes < 0 &&
1895 -*offset_bytes >= value_as_byte_array.
operands().size())))
1897 elements.push_back(std::move(member));
1901 else if(!offset_bytes.has_value())
1924 bu, value_as_byte_array, non_const_update_bound, ns),
1934 mp_integer update_elements = (*element_width + 7) / 8;
1935 std::size_t first = 0;
1936 if(*offset_bytes < 0)
1940 value_as_byte_array.
id() != ID_array ||
1941 value_as_byte_array.
operands().size() > -*offset_bytes,
1942 "members past the update should be handled above");
1943 first = numeric_cast_v<std::size_t>(-*offset_bytes);
1947 update_elements -= *offset_bytes;
1949 update_elements > 0,
1950 "members before the update should be handled above");
1956 std::size_t end = first + numeric_cast_v<std::size_t>(update_elements);
1957 if(value_as_byte_array.
id() == ID_array)
1958 end = std::min(end, value_as_byte_array.
operands().size());
1961 const std::size_t update_size = update_values.size();
1970 if(non_const_update_bound.has_value())
1978 *non_const_update_bound,
1990 remaining_update_bytes};
1992 member_update_bound = std::move(update_size_expr);
1997 const std::size_t shift =
1999 const std::size_t element_bits_int =
2000 numeric_cast_v<std::size_t>(*element_width);
2002 const bool little_endian = src.
id() == ID_byte_update_little_endian;
2008 bv_typet{shift + element_bits_int}};
2017 exprt updated_element =
2021 elements.push_back(updated_element);
2027 element_bits_int - 1 + (little_endian ? shift : 0),
2028 (little_endian ? shift : 0),
2051 const exprt &value_as_byte_array,
2058 widest_member.has_value(),
2059 "lower_byte_update of union of unknown size is not supported");
2063 src.
op(), widest_member->first.get_name(), widest_member->first.
type()});
2064 bu.
type() = widest_member->first.type();
2067 widest_member->first.get_name(),
2082 const exprt &value_as_byte_array,
2086 if(src.
type().
id() == ID_array || src.
type().
id() == ID_vector)
2089 if(src.
type().
id() == ID_vector)
2099 if(*element_width == 8)
2101 if(value_as_byte_array.
id() != ID_array)
2104 non_const_update_bound.has_value(),
2105 "constant update bound should yield an array expression");
2107 src, *subtype, value_as_byte_array, *non_const_update_bound, ns);
2114 non_const_update_bound,
2119 src, *subtype, value_as_byte_array, non_const_update_bound, ns);
2121 else if(src.
type().
id() == ID_struct || src.
type().
id() == ID_struct_tag)
2126 value_as_byte_array,
2127 non_const_update_bound,
2132 else if(src.
type().
id() == ID_union || src.
type().
id() == ID_union_tag)
2137 value_as_byte_array,
2138 non_const_update_bound,
2145 src.
type().
id() == ID_c_enum || src.
type().
id() == ID_c_enum_tag)
2150 CHECK_RETURN(type_width.has_value() && *type_width > 0);
2151 const std::size_t type_bits = numeric_cast_v<std::size_t>(*type_width);
2154 if(value_as_byte_array.
id() == ID_array)
2155 update_bytes = value_as_byte_array.
operands();
2162 const std::size_t update_size_bits = update_bytes.size() * 8;
2163 const std::size_t bit_width = std::max(type_bits, update_size_bits);
2165 const bool is_little_endian = src.
id() == ID_byte_update_little_endian;
2169 if(bit_width > type_bits)
2176 if(!is_little_endian)
2182 if(non_const_update_bound.has_value())
2186 src.
id() == ID_byte_update_little_endian,
2192 for(std::size_t i = 0; i < update_bytes.size(); ++i)
2198 *non_const_update_bound},
2206 if(is_little_endian)
2211 power(2, bit_width) -
power(2, bit_width - update_size_bits),
2219 offset_times_eight, ID_ge,
from_integer(0, offset_type)};
2221 if_exprt mask_shifted{offset_ge_zero,
2224 if(!is_little_endian)
2225 mask_shifted.true_case().
swap(mask_shifted.false_case());
2232 if(is_little_endian)
2233 std::reverse(value.operands().begin(), value.operands().end());
2235 exprt zero_extended;
2236 if(bit_width > update_size_bits)
2243 if(!is_little_endian)
2249 zero_extended = value;
2252 if_exprt value_shifted{offset_ge_zero,
2253 shl_exprt{zero_extended, offset_times_eight},
2254 lshr_exprt{zero_extended, offset_times_eight}};
2255 if(!is_little_endian)
2256 value_shifted.true_case().
swap(value_shifted.false_case());
2259 bitor_exprt bitor_expr{bitand_expr, value_shifted};
2261 if(bit_width > type_bits)
2264 bitor_expr.type(), src.
id() == ID_byte_update_little_endian, ns);
2265 const auto bounds =
map_bounds(endianness_map, 0, type_bits - 1);
2271 bitor_expr, bounds.ub, bounds.lb,
bv_typet{type_bits}},
2282 false,
"lower_byte_update does not yet support ", src.
type().
id_string());
2289 src.
id() == ID_byte_update_little_endian ||
2290 src.
id() == ID_byte_update_big_endian,
2291 "byte update expression should either be little or big endian");
2312 simplify(update_size_expr_opt.value(), ns);
2314 const irep_idt extract_opcode = src.
id() == ID_byte_update_little_endian
2315 ? ID_byte_extract_little_endian
2316 : ID_byte_extract_big_endian;
2318 if(!update_size_expr_opt.value().is_constant())
2319 non_const_update_bound = *update_size_expr_opt;
2327 update_bits.has_value(),
"constant size-of should imply fixed bit width");
2328 const size_t update_bits_int = numeric_cast_v<size_t>(*update_bits);
2330 if(update_bits_int % 8 != 0)
2334 "non-byte aligned type expected to be a bitvector type");
2344 const exprt overlapping_byte =
2347 size_t n_extra_bits = 8 - update_bits_int % 8;
2349 overlapping_byte, n_extra_bits - 1, 0,
bv_typet{n_extra_bits}};
2353 update_value,
bv_typet{update_bits_int}),
2359 update_size_expr_opt =
2360 from_integer(update_bits_int / 8, update_size_expr_opt->type());
2379 if(src.
id()==ID_byte_update_little_endian ||
2380 src.
id()==ID_byte_update_big_endian ||
2381 src.
id()==ID_byte_extract_little_endian ||
2382 src.
id()==ID_byte_extract_big_endian)
2402 if(src.
id()==ID_byte_update_little_endian ||
2403 src.
id()==ID_byte_update_big_endian)
2405 else if(src.
id()==ID_byte_extract_little_endian ||
2406 src.
id()==ID_byte_extract_big_endian)