@@ -2209,6 +2209,81 @@ void smt2_convt::convert_expr(const exprt &expr)
2209
2209
" overflow check should not be performed on unsupported type" ,
2210
2210
op_type.id_string ());
2211
2211
}
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
+ }
2212
2287
else if (expr.id ()==ID_array)
2213
2288
{
2214
2289
defined_expressionst::const_iterator it=defined_expressions.find (expr);
0 commit comments