@@ -2278,20 +2278,59 @@ exprt lower_byte_update(const byte_update_exprt &src, const namespacet &ns)
2278
2278
// place.
2279
2279
// 4) Construct a new object.
2280
2280
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);
2282
2284
CHECK_RETURN (update_size_expr_opt.has_value ());
2283
2285
simplify (update_size_expr_opt.value (), ns);
2284
2286
2285
2287
if (!update_size_expr_opt.value ().is_constant ())
2286
2288
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
+ }
2287
2326
2288
2327
const irep_idt extract_opcode = src.id () == ID_byte_update_little_endian
2289
2328
? ID_byte_extract_little_endian
2290
2329
: ID_byte_extract_big_endian;
2291
2330
2292
2331
const byte_extract_exprt byte_extract_expr{
2293
2332
extract_opcode,
2294
- src. value () ,
2333
+ update_value ,
2295
2334
from_integer (0 , src.offset ().type ()),
2296
2335
array_typet{bv_typet{8 }, *update_size_expr_opt}};
2297
2336
0 commit comments