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