@@ -1621,19 +1621,14 @@ static exprt lower_byte_update_array_vector_unbounded(
1621
1621
plus_exprt{last_index, from_integer (1 , last_index.type ())}}};
1622
1622
1623
1623
// The actual value of a partial update at the end.
1624
- exprt last_update_value = lower_byte_operators (
1624
+ exprt last_update_value = lower_byte_update (
1625
1625
byte_update_exprt{
1626
1626
src.id (),
1627
1627
index_exprt{src.op (), last_index},
1628
- from_integer (0 , src.offset ().type ()),
1629
- byte_extract_exprt{
1630
- extract_opcode,
1631
- value_as_byte_array,
1632
- mult_exprt{
1633
- typecast_exprt::conditional_cast (last_index, subtype_size.type ()),
1634
- subtype_size},
1635
- src.get_bits_per_byte (),
1636
- array_typet{bv_typet{src.get_bits_per_byte ()}, tail_size}},
1628
+ unary_minus_exprt{mult_exprt{
1629
+ typecast_exprt::conditional_cast (last_index, subtype_size.type ()),
1630
+ subtype_size}},
1631
+ value_as_byte_array,
1637
1632
src.get_bits_per_byte ()},
1638
1633
ns);
1639
1634
@@ -1675,10 +1670,6 @@ static exprt lower_byte_update_array_vector_non_const(
1675
1670
const optionalt<exprt> &non_const_update_bound,
1676
1671
const namespacet &ns)
1677
1672
{
1678
- const irep_idt extract_opcode = src.id () == ID_byte_update_little_endian
1679
- ? ID_byte_extract_little_endian
1680
- : ID_byte_extract_big_endian;
1681
-
1682
1673
// do all arithmetic below using index/offset types - the array theory
1683
1674
// back-end is really picky about indices having the same type
1684
1675
auto subtype_size_opt = size_of_expr (subtype, ns);
@@ -1699,6 +1690,8 @@ static exprt lower_byte_update_array_vector_non_const(
1699
1690
1700
1691
// compute the number of bytes (from the update value) that are going to be
1701
1692
// consumed for updating the first element
1693
+ const exprt update_size =
1694
+ from_integer (value_as_byte_array.operands ().size (), subtype_size.type ());
1702
1695
exprt initial_bytes = minus_exprt{subtype_size, update_offset};
1703
1696
exprt update_bound;
1704
1697
if (non_const_update_bound.has_value ())
@@ -1711,28 +1704,23 @@ static exprt lower_byte_update_array_vector_non_const(
1711
1704
DATA_INVARIANT (
1712
1705
value_as_byte_array.id () == ID_array,
1713
1706
" value should be an array expression if the update bound is constant" );
1714
- update_bound =
1715
- from_integer (value_as_byte_array.operands ().size (), initial_bytes.type ());
1707
+ update_bound = update_size;
1716
1708
}
1717
1709
initial_bytes =
1718
1710
if_exprt{binary_predicate_exprt{initial_bytes, ID_lt, update_bound},
1719
1711
initial_bytes,
1720
1712
update_bound};
1721
1713
simplify (initial_bytes, ns);
1722
1714
1723
- // encode the first update: update the original element at first_index with
1724
- // initial_bytes-many bytes extracted from value_as_byte_array
1725
- exprt first_update_value = lower_byte_operators (
1715
+ // encode the first update: update the original element at first_index (the
1716
+ // actual update will only be initial_bytes-many bytes from
1717
+ // value_as_byte_array)
1718
+ exprt first_update_value = lower_byte_update (
1726
1719
byte_update_exprt{
1727
1720
src.id (),
1728
1721
index_exprt{src.op (), first_index},
1729
1722
update_offset,
1730
- byte_extract_exprt{
1731
- extract_opcode,
1732
- value_as_byte_array,
1733
- from_integer (0 , src.offset ().type ()),
1734
- src.get_bits_per_byte (),
1735
- array_typet{bv_typet{src.get_bits_per_byte ()}, initial_bytes}},
1723
+ value_as_byte_array,
1736
1724
src.get_bits_per_byte ()},
1737
1725
ns);
1738
1726
@@ -1768,63 +1756,45 @@ static exprt lower_byte_update_array_vector_non_const(
1768
1756
1769
1757
with_exprt result{src.op (), first_index, first_update_value};
1770
1758
1771
- std::size_t i = 1 ;
1772
- for (; offset + step_size <= value_as_byte_array.operands ().size ();
1773
- offset += step_size, ++i)
1774
- {
1759
+ auto lower_byte_update_array_vector_non_const_one_element =
1760
+ [&src,
1761
+ &first_index,
1762
+ &initial_bytes,
1763
+ &subtype_size,
1764
+ &value_as_byte_array,
1765
+ &ns,
1766
+ &result](std::size_t i) -> void {
1775
1767
exprt where = simplify_expr (
1776
1768
plus_exprt{first_index, from_integer (i, first_index.type ())}, ns);
1777
1769
1778
- exprt offset_expr = simplify_expr (
1779
- plus_exprt{
1770
+ exprt neg_offset_expr = simplify_expr (
1771
+ unary_minus_exprt{ plus_exprt{
1780
1772
initial_bytes,
1781
- mult_exprt{subtype_size, from_integer (i - 1 , subtype_size.type ())}},
1773
+ mult_exprt{subtype_size, from_integer (i - 1 , subtype_size.type ())}}} ,
1782
1774
ns);
1783
1775
1784
- exprt element = lower_byte_operators (
1776
+ exprt element = lower_byte_update (
1785
1777
byte_update_exprt{
1786
1778
src.id (),
1787
1779
index_exprt{src.op (), where},
1788
- from_integer (0 , src.offset ().type ()),
1789
- byte_extract_exprt{
1790
- extract_opcode,
1791
- value_as_byte_array,
1792
- std::move (offset_expr),
1793
- src.get_bits_per_byte (),
1794
- array_typet{bv_typet{src.get_bits_per_byte ()}, subtype_size}},
1780
+ neg_offset_expr,
1781
+ value_as_byte_array,
1795
1782
src.get_bits_per_byte ()},
1796
1783
ns);
1797
1784
1798
1785
result.add_to_operands (std::move (where), std::move (element));
1786
+ };
1787
+
1788
+ std::size_t i = 1 ;
1789
+ for (; offset + step_size <= value_as_byte_array.operands ().size ();
1790
+ offset += step_size, ++i)
1791
+ {
1792
+ lower_byte_update_array_vector_non_const_one_element (i);
1799
1793
}
1800
1794
1801
1795
// do the tail
1802
1796
if (offset < value_as_byte_array.operands ().size ())
1803
- {
1804
- const std::size_t tail_size =
1805
- value_as_byte_array.operands ().size () - offset;
1806
-
1807
- exprt where = simplify_expr (
1808
- plus_exprt{first_index, from_integer (i, first_index.type ())}, ns);
1809
-
1810
- exprt element = lower_byte_operators (
1811
- byte_update_exprt{
1812
- src.id (),
1813
- index_exprt{src.op (), where},
1814
- from_integer (0 , src.offset ().type ()),
1815
- byte_extract_exprt{
1816
- extract_opcode,
1817
- value_as_byte_array,
1818
- from_integer (offset, src.offset ().type ()),
1819
- src.get_bits_per_byte (),
1820
- array_typet{
1821
- bv_typet{src.get_bits_per_byte ()},
1822
- from_integer (tail_size, size_type ())}},
1823
- src.get_bits_per_byte ()},
1824
- ns);
1825
-
1826
- result.add_to_operands (std::move (where), std::move (element));
1827
- }
1797
+ lower_byte_update_array_vector_non_const_one_element (i);
1828
1798
1829
1799
return simplify_expr (std::move (result), ns);
1830
1800
}
@@ -2333,9 +2303,14 @@ static exprt lower_byte_update(
2333
2303
if_exprt mask_shifted{
2334
2304
offset_ge_zero,
2335
2305
shl_exprt{mask, offset_in_bits},
2336
- lshr_exprt{mask, offset_in_bits}};
2306
+ lshr_exprt{mask, unary_minus_exprt{ offset_in_bits} }};
2337
2307
if (!is_little_endian)
2308
+ {
2338
2309
mask_shifted.true_case ().swap (mask_shifted.false_case ());
2310
+ to_shift_expr (mask_shifted.true_case ())
2311
+ .distance ()
2312
+ .swap (to_shift_expr (mask_shifted.false_case ()).distance ());
2313
+ }
2339
2314
2340
2315
// original_bits &= ~mask
2341
2316
bitand_exprt bitand_expr{val_before, bitnot_exprt{mask_shifted}};
@@ -2365,9 +2340,14 @@ static exprt lower_byte_update(
2365
2340
if_exprt value_shifted{
2366
2341
offset_ge_zero,
2367
2342
shl_exprt{zero_extended, offset_in_bits},
2368
- lshr_exprt{zero_extended, offset_in_bits}};
2343
+ lshr_exprt{zero_extended, unary_minus_exprt{ offset_in_bits} }};
2369
2344
if (!is_little_endian)
2345
+ {
2370
2346
value_shifted.true_case ().swap (value_shifted.false_case ());
2347
+ to_shift_expr (value_shifted.true_case ())
2348
+ .distance ()
2349
+ .swap (to_shift_expr (value_shifted.false_case ()).distance ());
2350
+ }
2371
2351
2372
2352
// original_bits |= newvalue
2373
2353
bitor_exprt bitor_expr{bitand_expr, value_shifted};
0 commit comments