@@ -1550,17 +1550,14 @@ static exprt lower_byte_update_array_vector_unbounded(
1550
1550
plus_exprt{last_index, from_integer (1 , last_index.type ())}}};
1551
1551
1552
1552
// The actual value of a partial update at the end.
1553
- exprt last_update_value = lower_byte_operators (
1553
+ exprt last_update_value = lower_byte_update (
1554
1554
byte_update_exprt{
1555
1555
src.id (),
1556
1556
index_exprt{src.op (), last_index},
1557
- from_integer (0 , src.offset ().type ()),
1558
- byte_extract_exprt{extract_opcode,
1559
- value_as_byte_array,
1560
- mult_exprt{typecast_exprt::conditional_cast (
1561
- last_index, subtype_size.type ()),
1562
- subtype_size},
1563
- array_typet{bv_typet{8 }, tail_size}}},
1557
+ unary_minus_exprt{mult_exprt{
1558
+ typecast_exprt::conditional_cast (last_index, subtype_size.type ()),
1559
+ subtype_size}},
1560
+ value_as_byte_array},
1564
1561
ns);
1565
1562
1566
1563
if_exprt array_comprehension_body{
@@ -1601,10 +1598,6 @@ static exprt lower_byte_update_array_vector_non_const(
1601
1598
const optionalt<exprt> &non_const_update_bound,
1602
1599
const namespacet &ns)
1603
1600
{
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;
1607
-
1608
1601
// do all arithmetic below using index/offset types - the array theory
1609
1602
// back-end is really picky about indices having the same type
1610
1603
auto subtype_size_opt = size_of_expr (subtype, ns);
@@ -1625,6 +1618,8 @@ static exprt lower_byte_update_array_vector_non_const(
1625
1618
1626
1619
// compute the number of bytes (from the update value) that are going to be
1627
1620
// consumed for updating the first element
1621
+ const exprt update_size =
1622
+ from_integer (value_as_byte_array.operands ().size (), subtype_size.type ());
1628
1623
exprt initial_bytes = minus_exprt{subtype_size, update_offset};
1629
1624
exprt update_bound;
1630
1625
if (non_const_update_bound.has_value ())
@@ -1637,26 +1632,23 @@ static exprt lower_byte_update_array_vector_non_const(
1637
1632
DATA_INVARIANT (
1638
1633
value_as_byte_array.id () == ID_array,
1639
1634
" value should be an array expression if the update bound is constant" );
1640
- update_bound =
1641
- from_integer (value_as_byte_array.operands ().size (), initial_bytes.type ());
1635
+ update_bound = update_size;
1642
1636
}
1643
1637
initial_bytes =
1644
1638
if_exprt{binary_predicate_exprt{initial_bytes, ID_lt, update_bound},
1645
1639
initial_bytes,
1646
1640
update_bound};
1647
1641
simplify (initial_bytes, ns);
1648
1642
1649
- // encode the first update: update the original element at first_index with
1650
- // initial_bytes-many bytes extracted from value_as_byte_array
1651
- exprt first_update_value = lower_byte_operators (
1643
+ // encode the first update: update the original element at first_index (the
1644
+ // actual update will only be initial_bytes-many bytes from
1645
+ // value_as_byte_array)
1646
+ exprt first_update_value = lower_byte_update (
1652
1647
byte_update_exprt{
1653
1648
src.id (),
1654
1649
index_exprt{src.op (), first_index},
1655
1650
update_offset,
1656
- byte_extract_exprt{extract_opcode,
1657
- value_as_byte_array,
1658
- from_integer (0 , src.offset ().type ()),
1659
- array_typet{bv_typet{8 }, initial_bytes}}},
1651
+ value_as_byte_array},
1660
1652
ns);
1661
1653
1662
1654
if (value_as_byte_array.id () != ID_array)
@@ -1691,56 +1683,44 @@ static exprt lower_byte_update_array_vector_non_const(
1691
1683
1692
1684
with_exprt result{src.op (), first_index, first_update_value};
1693
1685
1694
- std::size_t i = 1 ;
1695
- for (; offset + step_size <= value_as_byte_array.operands ().size ();
1696
- offset += step_size, ++i)
1697
- {
1686
+ auto lower_byte_update_array_vector_non_const_one_element =
1687
+ [&src,
1688
+ &first_index,
1689
+ &initial_bytes,
1690
+ &subtype_size,
1691
+ &value_as_byte_array,
1692
+ &ns,
1693
+ &result](std::size_t i) -> void {
1698
1694
exprt where = simplify_expr (
1699
1695
plus_exprt{first_index, from_integer (i, first_index.type ())}, ns);
1700
1696
1701
- exprt offset_expr = simplify_expr (
1702
- plus_exprt{
1697
+ exprt neg_offset_expr = simplify_expr (
1698
+ unary_minus_exprt{ plus_exprt{
1703
1699
initial_bytes,
1704
- mult_exprt{subtype_size, from_integer (i - 1 , subtype_size.type ())}},
1700
+ mult_exprt{subtype_size, from_integer (i - 1 , subtype_size.type ())}}} ,
1705
1701
ns);
1706
1702
1707
- exprt element = lower_byte_operators (
1703
+ exprt element = lower_byte_update (
1708
1704
byte_update_exprt{
1709
1705
src.id (),
1710
1706
index_exprt{src.op (), where},
1711
- from_integer (0 , src.offset ().type ()),
1712
- byte_extract_exprt{extract_opcode,
1713
- value_as_byte_array,
1714
- std::move (offset_expr),
1715
- array_typet{bv_typet{8 }, subtype_size}}},
1707
+ neg_offset_expr,
1708
+ value_as_byte_array},
1716
1709
ns);
1717
1710
1718
1711
result.add_to_operands (std::move (where), std::move (element));
1712
+ };
1713
+
1714
+ std::size_t i = 1 ;
1715
+ for (; offset + step_size <= value_as_byte_array.operands ().size ();
1716
+ offset += step_size, ++i)
1717
+ {
1718
+ lower_byte_update_array_vector_non_const_one_element (i);
1719
1719
}
1720
1720
1721
1721
// do the tail
1722
1722
if (offset < value_as_byte_array.operands ().size ())
1723
- {
1724
- const std::size_t tail_size =
1725
- value_as_byte_array.operands ().size () - offset;
1726
-
1727
- exprt where = simplify_expr (
1728
- plus_exprt{first_index, from_integer (i, first_index.type ())}, ns);
1729
-
1730
- exprt element = lower_byte_operators (
1731
- byte_update_exprt{
1732
- src.id (),
1733
- index_exprt{src.op (), where},
1734
- from_integer (0 , src.offset ().type ()),
1735
- byte_extract_exprt{
1736
- extract_opcode,
1737
- value_as_byte_array,
1738
- from_integer (offset, src.offset ().type ()),
1739
- array_typet{bv_typet{8 }, from_integer (tail_size, size_type ())}}},
1740
- ns);
1741
-
1742
- result.add_to_operands (std::move (where), std::move (element));
1743
- }
1723
+ lower_byte_update_array_vector_non_const_one_element (i);
1744
1724
1745
1725
return simplify_expr (std::move (result), ns);
1746
1726
}
@@ -2218,11 +2198,17 @@ static exprt lower_byte_update(
2218
2198
const binary_predicate_exprt offset_ge_zero{
2219
2199
offset_times_eight, ID_ge, from_integer (0 , offset_type)};
2220
2200
2221
- if_exprt mask_shifted{offset_ge_zero,
2222
- shl_exprt{mask, offset_times_eight},
2223
- lshr_exprt{mask, offset_times_eight}};
2201
+ if_exprt mask_shifted{
2202
+ offset_ge_zero,
2203
+ shl_exprt{mask, offset_times_eight},
2204
+ lshr_exprt{mask, unary_minus_exprt{offset_times_eight}}};
2224
2205
if (!is_little_endian)
2206
+ {
2225
2207
mask_shifted.true_case ().swap (mask_shifted.false_case ());
2208
+ to_shift_expr (mask_shifted.true_case ())
2209
+ .distance ()
2210
+ .swap (to_shift_expr (mask_shifted.false_case ()).distance ());
2211
+ }
2226
2212
2227
2213
// original_bits &= ~mask
2228
2214
bitand_exprt bitand_expr{val_before, bitnot_exprt{mask_shifted}};
@@ -2249,11 +2235,17 @@ static exprt lower_byte_update(
2249
2235
zero_extended = value;
2250
2236
2251
2237
// shift the 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}};
2238
+ if_exprt value_shifted{
2239
+ offset_ge_zero,
2240
+ shl_exprt{zero_extended, offset_times_eight},
2241
+ lshr_exprt{zero_extended, unary_minus_exprt{offset_times_eight}}};
2255
2242
if (!is_little_endian)
2243
+ {
2256
2244
value_shifted.true_case ().swap (value_shifted.false_case ());
2245
+ to_shift_expr (value_shifted.true_case ())
2246
+ .distance ()
2247
+ .swap (to_shift_expr (value_shifted.false_case ()).distance ());
2248
+ }
2257
2249
2258
2250
// original_bits |= newvalue
2259
2251
bitor_exprt bitor_expr{bitand_expr, value_shifted};
0 commit comments