Skip to content

Commit 5f745a9

Browse files
committed
Move expr2bits, bits2expr, try_get_string_data_array to simplify_utils
They do not have any dependency on the simplify_exprt class (and thus don't need to be class members). Similarly, try_get_string_data_array has nothing to do with the simplify_exprt functions.
1 parent 0312102 commit 5f745a9

File tree

10 files changed

+385
-368
lines changed

10 files changed

+385
-368
lines changed

src/goto-symex/goto_symex.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Author: Daniel Kroening, [email protected]
2222
#include <util/mathematical_types.h>
2323
#include <util/pointer_offset_size.h>
2424
#include <util/simplify_expr.h>
25+
#include <util/simplify_utils.h>
2526
#include <util/string_expr.h>
2627
#include <util/string_utils.h>
2728

src/util/simplify_expr.cpp

Lines changed: 8 additions & 318 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@ Author: Daniel Kroening, [email protected]
1010

1111
#include <algorithm>
1212

13-
#include "arith_tools.h"
1413
#include "byte_operators.h"
1514
#include "c_types.h"
1615
#include "config.h"
17-
#include "endianness_map.h"
1816
#include "expr_util.h"
1917
#include "fixedbv.h"
2018
#include "invariant.h"
@@ -27,9 +25,7 @@ Author: Daniel Kroening, [email protected]
2725
#include "rational_tools.h"
2826
#include "simplify_utils.h"
2927
#include "std_expr.h"
30-
#include "string_constant.h"
3128
#include "string_expr.h"
32-
#include "symbol.h"
3329

3430
// #define DEBUGX
3531

@@ -1564,313 +1560,6 @@ simplify_exprt::resultt<> simplify_exprt::simplify_object(const exprt &expr)
15641560
return unchanged(expr);
15651561
}
15661562

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-
18741563
simplify_exprt::resultt<>
18751564
simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
18761565
{
@@ -1958,9 +1647,10 @@ simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
19581647
if(expr.op().id()==ID_array_of &&
19591648
to_array_of_expr(expr.op()).op().id()==ID_constant)
19601649
{
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);
19641654

19651655
if(!const_bits_opt.has_value())
19661656
return unchanged(expr);
@@ -1979,7 +1669,7 @@ simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
19791669
numeric_cast_v<std::size_t>(*el_size));
19801670

19811671
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);
19831673

19841674
if(tmp.has_value())
19851675
return std::move(*tmp);
@@ -1998,8 +1688,8 @@ simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
19981688
}
19991689

20001690
// 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);
20031693

20041694
// make sure we don't lose bits with structs containing flexible array members
20051695
const bool struct_has_flexible_array_member = has_subtype(
@@ -2028,7 +1718,7 @@ simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
20281718
numeric_cast_v<std::size_t>(*el_size));
20291719

20301720
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);
20321722

20331723
if(tmp.has_value())
20341724
return std::move(*tmp);

0 commit comments

Comments
 (0)