10
10
11
11
#include < algorithm>
12
12
13
- #include " arith_tools.h"
14
13
#include " byte_operators.h"
15
14
#include " c_types.h"
16
15
#include " config.h"
17
- #include " endianness_map.h"
18
16
#include " expr_util.h"
19
17
#include " fixedbv.h"
20
18
#include " invariant.h"
27
25
#include " rational_tools.h"
28
26
#include " simplify_utils.h"
29
27
#include " std_expr.h"
30
- #include " string_constant.h"
31
28
#include " string_expr.h"
32
- #include " symbol.h"
33
29
34
30
// #define DEBUGX
35
31
@@ -1564,313 +1560,6 @@ simplify_exprt::resultt<> simplify_exprt::simplify_object(const exprt &expr)
1564
1560
return unchanged (expr);
1565
1561
}
1566
1562
1567
- optionalt<exprt> simplify_exprt::bits2expr (
1568
- const std::string &bits,
1569
- const typet &type,
1570
- bool little_endian)
1571
- {
1572
- // bits start at lowest memory address
1573
- auto type_bits = pointer_offset_bits (type, ns);
1574
-
1575
- if (!type_bits.has_value () || *type_bits != bits.size ())
1576
- return {};
1577
-
1578
- if (
1579
- type.id () == ID_unsignedbv || type.id () == ID_signedbv ||
1580
- type.id () == ID_floatbv || type.id () == ID_fixedbv ||
1581
- type.id () == ID_c_bit_field || type.id () == ID_pointer ||
1582
- type.id () == ID_bv)
1583
- {
1584
- endianness_mapt map (type, little_endian, ns);
1585
-
1586
- std::string tmp=bits;
1587
- for (std::string::size_type i=0 ; i<bits.size (); ++i)
1588
- tmp[i]=bits[map.map_bit (i)];
1589
-
1590
- std::reverse (tmp.begin (), tmp.end ());
1591
-
1592
- mp_integer i = binary2integer (tmp, false );
1593
- return constant_exprt (integer2bvrep (i, bits.size ()), type);
1594
- }
1595
- else if (type.id ()==ID_c_enum)
1596
- {
1597
- auto val = bits2expr (bits, to_c_enum_type (type).subtype (), little_endian);
1598
- if (val.has_value ())
1599
- {
1600
- val->type () = type;
1601
- return *val;
1602
- }
1603
- else
1604
- return {};
1605
- }
1606
- else if (type.id ()==ID_c_enum_tag)
1607
- {
1608
- auto val =
1609
- bits2expr (bits, ns.follow_tag (to_c_enum_tag_type (type)), little_endian);
1610
- if (val.has_value ())
1611
- {
1612
- val->type () = type;
1613
- return *val;
1614
- }
1615
- else
1616
- return {};
1617
- }
1618
- else if (type.id ()==ID_union)
1619
- {
1620
- // find a suitable member
1621
- const union_typet &union_type=to_union_type (type);
1622
- const union_typet::componentst &components=
1623
- union_type.components ();
1624
-
1625
- for (const auto &component : components)
1626
- {
1627
- auto val = bits2expr (bits, component.type (), little_endian);
1628
- if (!val.has_value ())
1629
- continue ;
1630
-
1631
- return union_exprt (component.get_name (), *val, type);
1632
- }
1633
- }
1634
- else if (type.id () == ID_union_tag)
1635
- {
1636
- auto val =
1637
- bits2expr (bits, ns.follow_tag (to_union_tag_type (type)), little_endian);
1638
- if (val.has_value ())
1639
- {
1640
- val->type () = type;
1641
- return *val;
1642
- }
1643
- else
1644
- return {};
1645
- }
1646
- else if (type.id ()==ID_struct)
1647
- {
1648
- const struct_typet &struct_type=to_struct_type (type);
1649
- const struct_typet::componentst &components=
1650
- struct_type.components ();
1651
-
1652
- struct_exprt result ({}, type);
1653
- result.reserve_operands (components.size ());
1654
-
1655
- mp_integer m_offset_bits=0 ;
1656
- for (const auto &component : components)
1657
- {
1658
- const auto m_size = pointer_offset_bits (component.type (), ns);
1659
- CHECK_RETURN (m_size.has_value () && *m_size>=0 );
1660
-
1661
- std::string comp_bits = std::string (
1662
- bits,
1663
- numeric_cast_v<std::size_t >(m_offset_bits),
1664
- numeric_cast_v<std::size_t >(*m_size));
1665
-
1666
- auto comp = bits2expr (comp_bits, component.type (), little_endian);
1667
- if (!comp.has_value ())
1668
- return {};
1669
- result.add_to_operands (std::move (*comp));
1670
-
1671
- m_offset_bits += *m_size;
1672
- }
1673
-
1674
- return std::move (result);
1675
- }
1676
- else if (type.id () == ID_struct_tag)
1677
- {
1678
- auto val =
1679
- bits2expr (bits, ns.follow_tag (to_struct_tag_type (type)), little_endian);
1680
- if (val.has_value ())
1681
- {
1682
- val->type () = type;
1683
- return *val;
1684
- }
1685
- else
1686
- return {};
1687
- }
1688
- else if (type.id ()==ID_array)
1689
- {
1690
- const array_typet &array_type=to_array_type (type);
1691
- const auto &size_expr = array_type.size ();
1692
-
1693
- PRECONDITION (size_expr.is_constant ());
1694
-
1695
- const std::size_t number_of_elements =
1696
- numeric_cast_v<std::size_t >(to_constant_expr (size_expr));
1697
-
1698
- const auto el_size_opt = pointer_offset_bits (array_type.subtype (), ns);
1699
- CHECK_RETURN (el_size_opt.has_value () && *el_size_opt > 0 );
1700
-
1701
- const std::size_t el_size = numeric_cast_v<std::size_t >(*el_size_opt);
1702
-
1703
- array_exprt result ({}, array_type);
1704
- result.reserve_operands (number_of_elements);
1705
-
1706
- for (std::size_t i = 0 ; i < number_of_elements; ++i)
1707
- {
1708
- std::string el_bits=std::string (bits, i*el_size, el_size);
1709
- auto el = bits2expr (el_bits, array_type.subtype (), little_endian);
1710
- if (!el.has_value ())
1711
- return {};
1712
- result.add_to_operands (std::move (*el));
1713
- }
1714
-
1715
- return std::move (result);
1716
- }
1717
- else if (type.id () == ID_vector)
1718
- {
1719
- const vector_typet &vector_type = to_vector_type (type);
1720
-
1721
- const std::size_t n_el = numeric_cast_v<std::size_t >(vector_type.size ());
1722
-
1723
- const auto el_size_opt = pointer_offset_bits (vector_type.subtype (), ns);
1724
- CHECK_RETURN (el_size_opt.has_value () && *el_size_opt > 0 );
1725
-
1726
- const std::size_t el_size = numeric_cast_v<std::size_t >(*el_size_opt);
1727
-
1728
- vector_exprt result ({}, vector_type);
1729
- result.reserve_operands (n_el);
1730
-
1731
- for (std::size_t i = 0 ; i < n_el; ++i)
1732
- {
1733
- std::string el_bits = std::string (bits, i * el_size, el_size);
1734
- auto el = bits2expr (el_bits, vector_type.subtype (), little_endian);
1735
- if (!el.has_value ())
1736
- return {};
1737
- result.add_to_operands (std::move (*el));
1738
- }
1739
-
1740
- return std::move (result);
1741
- }
1742
- else if (type.id () == ID_complex)
1743
- {
1744
- const complex_typet &complex_type = to_complex_type (type);
1745
-
1746
- const auto sub_size_opt = pointer_offset_bits (complex_type.subtype (), ns);
1747
- CHECK_RETURN (sub_size_opt.has_value () && *sub_size_opt > 0 );
1748
-
1749
- const std::size_t sub_size = numeric_cast_v<std::size_t >(*sub_size_opt);
1750
-
1751
- auto real = bits2expr (
1752
- bits.substr (0 , sub_size), complex_type.subtype (), little_endian);
1753
- auto imag =
1754
- bits2expr (bits.substr (sub_size), complex_type.subtype (), little_endian);
1755
- if (!real.has_value () || !imag.has_value ())
1756
- return {};
1757
-
1758
- return complex_exprt (*real, *imag, complex_type);
1759
- }
1760
-
1761
- return {};
1762
- }
1763
-
1764
- optionalt<std::string> simplify_exprt::expr2bits (
1765
- const exprt &expr,
1766
- bool little_endian)
1767
- {
1768
- // extract bits from lowest to highest memory address
1769
- const typet &type = expr.type ();
1770
-
1771
- if (expr.id ()==ID_constant)
1772
- {
1773
- const auto &value = to_constant_expr (expr).get_value ();
1774
-
1775
- if (
1776
- type.id () == ID_unsignedbv || type.id () == ID_signedbv ||
1777
- type.id () == ID_floatbv || type.id () == ID_fixedbv ||
1778
- type.id () == ID_c_bit_field || type.id () == ID_bv)
1779
- {
1780
- const auto width = to_bitvector_type (type).get_width ();
1781
-
1782
- endianness_mapt map (type, little_endian, ns);
1783
-
1784
- std::string result (width, ' ' );
1785
-
1786
- for (std::string::size_type i = 0 ; i < width; ++i)
1787
- result[map.map_bit (i)] = get_bvrep_bit (value, width, i) ? ' 1' : ' 0' ;
1788
-
1789
- return result;
1790
- }
1791
- else if (type.id () == ID_pointer)
1792
- {
1793
- if (value == ID_NULL && config.ansi_c .NULL_is_zero )
1794
- return std::string (' 0' , to_bitvector_type (type).get_width ());
1795
- else
1796
- return {};
1797
- }
1798
- else if (type.id () == ID_c_enum_tag)
1799
- {
1800
- const auto &c_enum_type = ns.follow_tag (to_c_enum_tag_type (type));
1801
- return expr2bits (constant_exprt (value, c_enum_type), little_endian);
1802
- }
1803
- else if (type.id () == ID_c_enum)
1804
- {
1805
- return expr2bits (
1806
- constant_exprt (value, to_c_enum_type (type).subtype ()), little_endian);
1807
- }
1808
- }
1809
- else if (expr.id () == ID_string_constant)
1810
- {
1811
- return expr2bits (to_string_constant (expr).to_array_expr (), little_endian);
1812
- }
1813
- else if (expr.id ()==ID_union)
1814
- {
1815
- return expr2bits (to_union_expr (expr).op (), little_endian);
1816
- }
1817
- else if (
1818
- expr.id () == ID_struct || expr.id () == ID_array || expr.id () == ID_vector ||
1819
- expr.id () == ID_complex)
1820
- {
1821
- std::string result;
1822
- forall_operands (it, expr)
1823
- {
1824
- auto tmp=expr2bits (*it, little_endian);
1825
- if (!tmp.has_value ())
1826
- return {}; // failed
1827
- result+=tmp.value ();
1828
- }
1829
-
1830
- return result;
1831
- }
1832
-
1833
- return {};
1834
- }
1835
-
1836
- optionalt<std::reference_wrapper<const array_exprt>>
1837
- try_get_string_data_array (const exprt &content, const namespacet &ns)
1838
- {
1839
- if (content.id () != ID_address_of)
1840
- {
1841
- return {};
1842
- }
1843
-
1844
- const auto &array_pointer = to_address_of_expr (content);
1845
-
1846
- if (array_pointer.object ().id () != ID_index)
1847
- {
1848
- return {};
1849
- }
1850
-
1851
- const auto &array_start = to_index_expr (array_pointer.object ());
1852
-
1853
- if (array_start.array ().id () != ID_symbol ||
1854
- array_start.array ().type ().id () != ID_array)
1855
- {
1856
- return {};
1857
- }
1858
-
1859
- const auto &array = to_symbol_expr (array_start.array ());
1860
-
1861
- const symbolt *symbol_ptr = nullptr ;
1862
-
1863
- if (ns.lookup (array.get_identifier (), symbol_ptr) ||
1864
- symbol_ptr->value .id () != ID_array)
1865
- {
1866
- return {};
1867
- }
1868
-
1869
- const auto &char_seq = to_array_expr (symbol_ptr->value );
1870
-
1871
- return optionalt<std::reference_wrapper<const array_exprt>>(char_seq);
1872
- }
1873
-
1874
1563
simplify_exprt::resultt<>
1875
1564
simplify_exprt::simplify_byte_extract (const byte_extract_exprt &expr)
1876
1565
{
@@ -1958,9 +1647,10 @@ simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
1958
1647
if (expr.op ().id ()==ID_array_of &&
1959
1648
to_array_of_expr (expr.op ()).op ().id ()==ID_constant)
1960
1649
{
1961
- const auto const_bits_opt=
1962
- expr2bits (to_array_of_expr (expr.op ()).op (),
1963
- byte_extract_id ()==ID_byte_extract_little_endian);
1650
+ const auto const_bits_opt = expr2bits (
1651
+ to_array_of_expr (expr.op ()).op (),
1652
+ byte_extract_id () == ID_byte_extract_little_endian,
1653
+ ns);
1964
1654
1965
1655
if (!const_bits_opt.has_value ())
1966
1656
return unchanged (expr);
@@ -1979,7 +1669,7 @@ simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
1979
1669
numeric_cast_v<std::size_t >(*el_size));
1980
1670
1981
1671
auto tmp = bits2expr (
1982
- el_bits, expr.type (), expr.id () == ID_byte_extract_little_endian);
1672
+ el_bits, expr.type (), expr.id () == ID_byte_extract_little_endian, ns );
1983
1673
1984
1674
if (tmp.has_value ())
1985
1675
return std::move (*tmp);
@@ -1998,8 +1688,8 @@ simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
1998
1688
}
1999
1689
2000
1690
// extract bits of a constant
2001
- const auto bits=
2002
- expr2bits (expr.op (), expr.id ()== ID_byte_extract_little_endian);
1691
+ const auto bits =
1692
+ expr2bits (expr.op (), expr.id () == ID_byte_extract_little_endian, ns );
2003
1693
2004
1694
// make sure we don't lose bits with structs containing flexible array members
2005
1695
const bool struct_has_flexible_array_member = has_subtype (
@@ -2028,7 +1718,7 @@ simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
2028
1718
numeric_cast_v<std::size_t >(*el_size));
2029
1719
2030
1720
auto tmp = bits2expr (
2031
- bits_cut, expr.type (), expr.id () == ID_byte_extract_little_endian);
1721
+ bits_cut, expr.type (), expr.id () == ID_byte_extract_little_endian, ns );
2032
1722
2033
1723
if (tmp.has_value ())
2034
1724
return std::move (*tmp);
0 commit comments