@@ -2209,6 +2209,81 @@ void smt2_convt::convert_expr(const exprt &expr)
22092209 " overflow check should not be performed on unsupported type" ,
22102210 op_type.id_string ());
22112211 }
2212+ else if (expr.id () == ID_saturating_plus || expr.id () == ID_saturating_minus)
2213+ {
2214+ const bool subtract = expr.id () == ID_saturating_minus;
2215+ const auto &op_type = expr.type ();
2216+ const auto &op0 = to_binary_expr (expr).op0 ();
2217+ const auto &op1 = to_binary_expr (expr).op1 ();
2218+
2219+ if (op_type.id () == ID_signedbv)
2220+ {
2221+ auto width = to_signedbv_type (op_type).get_width ();
2222+
2223+ // compute sum with one extra bit
2224+ out << " (let ((?sum (" ;
2225+ out << (subtract ? " bvsub" : " bvadd" );
2226+ out << " ((_ sign_extend 1) " ;
2227+ convert_expr (op0);
2228+ out << " )" ;
2229+ out << " ((_ sign_extend 1) " ;
2230+ convert_expr (op1);
2231+ out << " )))) " ; // sign_extend, bvadd/sub
2232+
2233+ // pick one of MAX, MIN, or the sum
2234+ out << " (ite (= "
2235+ " ((_ extract "
2236+ << width << " " << width
2237+ << " ) ?sum) "
2238+ " ((_ extract "
2239+ << (width - 1 ) << " " << (width - 1 ) << " ) ?sum)" ;
2240+ out << " ) " ; // =
2241+
2242+ // no overflow and no underflow case, return the sum
2243+ out << " ((_ extract " << width - 1 << " 0) ?sum) " ;
2244+
2245+ // MAX
2246+ out << " (ite (= ((_ extract " << width << " " << width << " ) ?sum) #b0) " ;
2247+ convert_expr (to_signedbv_type (op_type).largest_expr ());
2248+
2249+ // MIN
2250+ convert_expr (to_signedbv_type (op_type).smallest_expr ());
2251+ out << " )))" ; // ite, ite, let
2252+ }
2253+ else if (op_type.id () == ID_unsignedbv)
2254+ {
2255+ auto width = to_unsignedbv_type (op_type).get_width ();
2256+
2257+ // compute sum with one extra bit
2258+ out << " (let ((?sum (" << (subtract ? " bvsub" : " bvadd" );
2259+ out << " ((_ zero_extend 1) " ;
2260+ convert_expr (op0);
2261+ out << " )" ;
2262+ out << " ((_ zero_extend 1) " ;
2263+ convert_expr (op1);
2264+ out << " ))))" ; // zero_extend, bvsub/bvadd
2265+
2266+ // pick one of MAX, MIN, or the sum
2267+ out << " (ite (= ((_ extract " << width << " " << width << " ) ?sum) #b0) " ;
2268+
2269+ // no overflow and no underflow case, return the sum
2270+ out << " ((_ extract " << width - 1 << " 0) ?sum) " ;
2271+
2272+ // overflow when adding, underflow when subtracting
2273+ if (subtract)
2274+ convert_expr (to_unsignedbv_type (op_type).smallest_expr ());
2275+ else
2276+ convert_expr (to_unsignedbv_type (op_type).largest_expr ());
2277+
2278+ // MIN
2279+ out << " ))" ; // ite, let
2280+ }
2281+ else
2282+ INVARIANT_WITH_DIAGNOSTICS (
2283+ false ,
2284+ " saturating_plus/minus on unsupported type" ,
2285+ op_type.id_string ());
2286+ }
22122287 else if (expr.id ()==ID_array)
22132288 {
22142289 defined_expressionst::const_iterator it=defined_expressions.find (expr);
0 commit comments