@@ -1780,21 +1780,21 @@ void smt2_convt::convert_expr(const exprt &expr)
17801780 type.id ()==ID_signedbv ||
17811781 type.id ()==ID_bv)
17821782 {
1783- if (shift_expr.id () == ID_ashr)
1784- out << " (bvashr " ;
1785- else if (shift_expr.id () == ID_lshr)
1786- out << " (bvlshr " ;
1787- else if (shift_expr.id () == ID_shl)
1788- out << " (bvshl " ;
1789- else
1790- UNREACHABLE;
1791-
1792- convert_expr (shift_expr.op ());
1793- out << " " ;
1794-
17951783 // SMT2 requires the shift distance to have the same width as
17961784 // the value that is shifted -- odd!
17971785
1786+ auto emit_operator = [this ](const exprt &shift_expr)
1787+ {
1788+ if (shift_expr.id () == ID_ashr)
1789+ out << " (bvashr " ;
1790+ else if (shift_expr.id () == ID_lshr)
1791+ out << " (bvlshr " ;
1792+ else if (shift_expr.id () == ID_shl)
1793+ out << " (bvshl " ;
1794+ else
1795+ UNREACHABLE;
1796+ };
1797+
17981798 const auto &distance_type = shift_expr.distance ().type ();
17991799 if (distance_type.id () == ID_integer || distance_type.id () == ID_natural)
18001800 {
@@ -1804,29 +1804,70 @@ void smt2_convt::convert_expr(const exprt &expr)
18041804 // shift distance must be bit vector
18051805 std::size_t width_op0 = boolbv_width (shift_expr.op ().type ());
18061806 exprt tmp=from_integer (i, unsignedbv_typet (width_op0));
1807+
1808+ emit_operator (shift_expr);
1809+ convert_expr (shift_expr.op ());
1810+ out << ' ' ;
18071811 convert_expr (tmp);
1812+ out << ' )' ; // bv*sh
18081813 }
18091814 else if (
18101815 distance_type.id () == ID_signedbv ||
18111816 distance_type.id () == ID_unsignedbv ||
18121817 distance_type.id () == ID_c_enum || distance_type.id () == ID_c_bool)
18131818 {
1814- std::size_t width_op0 = boolbv_width (shift_expr.op ().type ());
1815- std::size_t width_op1 = boolbv_width (distance_type);
1819+ std::size_t width_op = boolbv_width (shift_expr.op ().type ());
1820+ std::size_t width_distance = boolbv_width (distance_type);
1821+ std::size_t width_result = boolbv_width (shift_expr.type ());
1822+
1823+ if (width_result != width_op)
1824+ UNEXPECTEDCASE (
1825+ " unsupported result width for " + shift_expr.id_string ());
18161826
1817- if (width_op0==width_op1)
1827+ // we use the larger of the two widths
1828+ if (width_op == width_distance)
1829+ {
1830+ emit_operator (shift_expr);
1831+ convert_expr (shift_expr.op ());
1832+ out << ' ' ;
18181833 convert_expr (shift_expr.distance ());
1819- else if (width_op0>width_op1)
1834+ out << ' )' ; // bv*sh
1835+ }
1836+ else if (width_op > width_distance)
18201837 {
1821- out << " ((_ zero_extend " << width_op0-width_op1 << " ) " ;
1838+ emit_operator (shift_expr);
1839+ convert_expr (shift_expr.op ());
1840+ out << ' ' ;
1841+ out << " ((_ zero_extend " << width_op - width_distance << " ) " ;
18221842 convert_expr (shift_expr.distance ());
1823- out << " )" ; // zero_extend
1843+ out << ' )' ; // zero_extend
1844+ out << ' )' ; // bv*sh
18241845 }
1825- else // width_op0<width_op1
1846+ else // width_op<width_distance -- distance is wider
18261847 {
1827- out << " ((_ extract " << width_op0-1 << " 0) " ;
1848+ // enlarge the shift to match the distance operand,
1849+ // then extract again
1850+ out << " ((_ extract " << width_op - 1 << " 0) " ;
1851+ emit_operator (shift_expr);
1852+
1853+ // use sign extension when needed
1854+ if (shift_expr.op ().type ().id () == ID_signedbv)
1855+ {
1856+ out << " ((_ sign_extend " << width_distance - width_op << " ) " ;
1857+ convert_expr (shift_expr.op ());
1858+ out << ' )' ; // sign_extend
1859+ }
1860+ else
1861+ {
1862+ out << " ((_ zero_extend " << width_distance - width_op << " ) " ;
1863+ convert_expr (shift_expr.op ());
1864+ out << ' )' ; // zero_extend
1865+ }
1866+
1867+ out << ' ' ;
18281868 convert_expr (shift_expr.distance ());
1829- out << " )" ; // extract
1869+ out << ' )' ; // bv*sh
1870+ out << ' )' ; // extract
18301871 }
18311872 }
18321873 else
@@ -1835,8 +1876,6 @@ void smt2_convt::convert_expr(const exprt &expr)
18351876 " unsupported distance type for " + shift_expr.id_string () + " : " +
18361877 distance_type.id_string ());
18371878 }
1838-
1839- out << " )" ; // bv*sh
18401879 }
18411880 else
18421881 UNEXPECTEDCASE (
0 commit comments