@@ -1203,6 +1203,62 @@ void smv_typecheckt::typecheck_expr_rec(exprt &expr, modet mode)
12031203 << " abs expects integer" ;
12041204 }
12051205 }
1206+ else if (expr.id () == ID_smv_bit_selection) // word[high:low]
1207+ {
1208+ auto &op = to_ternary_expr (expr).op0 ();
1209+
1210+ typecheck_expr_rec (op, mode);
1211+
1212+ if (op.type ().id () != ID_unsignedbv && op.type ().id () != ID_signedbv)
1213+ {
1214+ throw errort ().with_location (op.source_location ())
1215+ << " bit selection expects word" ;
1216+ }
1217+
1218+ auto &high = to_ternary_expr (expr).op1 ();
1219+
1220+ typecheck_expr_rec (high, OTHER);
1221+
1222+ // high must be an integer constant
1223+ if (high.type ().id () != ID_range && high.type ().id () != ID_natural)
1224+ {
1225+ throw errort ().with_location (expr.find_source_location ())
1226+ << " bit-select high must be integer, but got "
1227+ << to_string (high.type ());
1228+ }
1229+
1230+ if (high.id () != ID_constant)
1231+ throw errort ().with_location (expr.find_source_location ())
1232+ << " bit-select high must be constant" ;
1233+
1234+ auto high_int = numeric_cast_v<mp_integer>(to_constant_expr (high));
1235+
1236+ auto &low = to_ternary_expr (expr).op2 ();
1237+
1238+ typecheck_expr_rec (low, OTHER);
1239+
1240+ // low must be an integer constant
1241+ if (low.type ().id () != ID_range && low.type ().id () != ID_natural)
1242+ {
1243+ throw errort ().with_location (expr.find_source_location ())
1244+ << " bit-select low must be integer, but got " << to_string (low.type ());
1245+ }
1246+
1247+ if (low.id () != ID_constant)
1248+ throw errort ().with_location (expr.find_source_location ())
1249+ << " bit-select low must be constant" ;
1250+
1251+ auto low_int = numeric_cast_v<mp_integer>(to_constant_expr (low));
1252+
1253+ if (low_int > high_int)
1254+ throw errort ().with_location (expr.find_source_location ())
1255+ << " bit-select high must not be smaller than low" ;
1256+
1257+ auto width = numeric_cast_v<std::size_t >(high_int - low_int + 1 );
1258+
1259+ // always unsigned, even if op is signed
1260+ expr.type () = unsignedbv_typet{width};
1261+ }
12061262 else if (expr.id () == ID_smv_bool)
12071263 {
12081264 auto &op = to_unary_expr (expr).op ();
@@ -1623,6 +1679,13 @@ void smv_typecheckt::lower_node(exprt &expr) const
16231679 auto &implies = to_smv_bitimplies_expr (expr);
16241680 expr = bitor_exprt{bitnot_exprt{implies.op0 ()}, implies.op1 ()};
16251681 }
1682+ else if (expr.id () == ID_smv_bit_selection)
1683+ {
1684+ // we'll lower to extractbits
1685+ auto &bit_selection = to_ternary_expr (expr);
1686+ expr = extractbits_exprt{
1687+ bit_selection.op0 (), bit_selection.op2 (), bit_selection.type ()};
1688+ }
16261689
16271690 // lower the type
16281691 lower (expr.type ());
0 commit comments