@@ -1080,6 +1080,62 @@ void smv_typecheckt::typecheck_expr_rec(exprt &expr, modet mode)
10801080 << " abs expects integer" ;
10811081 }
10821082 }
1083+ else if (expr.id () == ID_smv_bit_selection) // word[high:low]
1084+ {
1085+ auto &op = to_ternary_expr (expr).op0 ();
1086+
1087+ typecheck_expr_rec (op, mode);
1088+
1089+ if (op.type ().id () != ID_unsignedbv && op.type ().id () != ID_signedbv)
1090+ {
1091+ throw errort ().with_location (op.source_location ())
1092+ << " bit selection expects word" ;
1093+ }
1094+
1095+ auto &high = to_ternary_expr (expr).op1 ();
1096+
1097+ typecheck_expr_rec (high, OTHER);
1098+
1099+ // high must be an integer constant
1100+ if (high.type ().id () != ID_range && high.type ().id () != ID_natural)
1101+ {
1102+ throw errort ().with_location (expr.find_source_location ())
1103+ << " bit-select high must be integer, but got "
1104+ << to_string (high.type ());
1105+ }
1106+
1107+ if (high.id () != ID_constant)
1108+ throw errort ().with_location (expr.find_source_location ())
1109+ << " bit-select high must be constant" ;
1110+
1111+ auto high_int = numeric_cast_v<mp_integer>(to_constant_expr (high));
1112+
1113+ auto &low = to_ternary_expr (expr).op2 ();
1114+
1115+ typecheck_expr_rec (low, OTHER);
1116+
1117+ // low must be an integer constant
1118+ if (low.type ().id () != ID_range && low.type ().id () != ID_natural)
1119+ {
1120+ throw errort ().with_location (expr.find_source_location ())
1121+ << " bit-select low must be integer, but got " << to_string (low.type ());
1122+ }
1123+
1124+ if (low.id () != ID_constant)
1125+ throw errort ().with_location (expr.find_source_location ())
1126+ << " bit-select low must be constant" ;
1127+
1128+ auto low_int = numeric_cast_v<mp_integer>(to_constant_expr (low));
1129+
1130+ if (low_int > high_int)
1131+ throw errort ().with_location (expr.find_source_location ())
1132+ << " bit-select high must not be smaller than low" ;
1133+
1134+ auto width = numeric_cast_v<std::size_t >(high_int - low_int + 1 );
1135+
1136+ // always unsigned, even if op is signed
1137+ expr.type () = unsignedbv_typet{width};
1138+ }
10831139 else if (expr.id () == ID_smv_bool)
10841140 {
10851141 auto &op = to_unary_expr (expr).op ();
@@ -1500,6 +1556,13 @@ void smv_typecheckt::lower_node(exprt &expr) const
15001556 auto &implies = to_smv_bitimplies_expr (expr);
15011557 expr = bitor_exprt{bitnot_exprt{implies.op0 ()}, implies.op1 ()};
15021558 }
1559+ else if (expr.id () == ID_smv_bit_selection)
1560+ {
1561+ // we'll lower to extractbits
1562+ auto &bit_selection = to_ternary_expr (expr);
1563+ expr = extractbits_exprt{
1564+ bit_selection.op0 (), bit_selection.op2 (), bit_selection.type ()};
1565+ }
15031566
15041567 // lower the type
15051568 lower (expr.type ());
0 commit comments