@@ -2278,20 +2278,59 @@ exprt lower_byte_update(const byte_update_exprt &src, const namespacet &ns)
22782278 // place.
22792279 // 4) Construct a new object.
22802280 optionalt<exprt> non_const_update_bound;
2281- auto update_size_expr_opt = size_of_expr (src.value ().type (), ns);
2281+ // update value, may require extension to full bytes
2282+ exprt update_value = src.value ();
2283+ auto update_size_expr_opt = size_of_expr (update_value.type (), ns);
22822284 CHECK_RETURN (update_size_expr_opt.has_value ());
22832285 simplify (update_size_expr_opt.value (), ns);
22842286
22852287 if (!update_size_expr_opt.value ().is_constant ())
22862288 non_const_update_bound = *update_size_expr_opt;
2289+ else
2290+ {
2291+ auto update_bits = pointer_offset_bits (update_value.type (), ns);
2292+ // If the following invariant fails, then the type was only found to be
2293+ // constant via simplification. Such instances should be fixed at the place
2294+ // introducing these constant-but-not-constant_exprt type sizes.
2295+ DATA_INVARIANT (
2296+ update_bits.has_value (), " constant size-of should imply fixed bit width" );
2297+ const size_t update_bits_int = numeric_cast_v<size_t >(*update_bits);
2298+
2299+ if (update_bits_int % 8 != 0 )
2300+ {
2301+ DATA_INVARIANT (
2302+ can_cast_type<bitvector_typet>(update_value.type ()),
2303+ " non-byte aligned type expected to be a bitvector type" );
2304+ size_t n_extra_bits = 8 - update_bits_int % 8 ;
2305+
2306+ endianness_mapt endianness_map (
2307+ src.op ().type (), src.id () == ID_byte_update_little_endian, ns);
2308+ const auto bounds = map_bounds (
2309+ endianness_map, update_bits_int, update_bits_int + n_extra_bits - 1 );
2310+ extractbits_exprt extra_bits{
2311+ src.op (), bounds.ub , bounds.lb , bv_typet{n_extra_bits}};
2312+
2313+ update_value =
2314+ concatenation_exprt{typecast_exprt::conditional_cast (
2315+ update_value, bv_typet{update_bits_int}),
2316+ extra_bits,
2317+ bitvector_typet{update_value.type ().id (),
2318+ update_bits_int + n_extra_bits}};
2319+ }
2320+ else
2321+ {
2322+ update_size_expr_opt =
2323+ from_integer (update_bits_int / 8 , update_size_expr_opt->type ());
2324+ }
2325+ }
22872326
22882327 const irep_idt extract_opcode = src.id () == ID_byte_update_little_endian
22892328 ? ID_byte_extract_little_endian
22902329 : ID_byte_extract_big_endian;
22912330
22922331 const byte_extract_exprt byte_extract_expr{
22932332 extract_opcode,
2294- src. value () ,
2333+ update_value ,
22952334 from_integer (0 , src.offset ().type ()),
22962335 array_typet{bv_typet{8 }, *update_size_expr_opt}};
22972336
0 commit comments