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