@@ -1310,6 +1310,142 @@ static smt_termt convert_expr_to_smt(
13101310 mult_overflow.pretty ());
13111311}
13121312
1313+ static smt_termt convert_expr_to_smt (
1314+ const saturating_plus_exprt &saturating_plus,
1315+ const sub_expression_mapt &converted)
1316+ {
1317+ const auto &op_type = saturating_plus.type ();
1318+ const smt_termt &left = converted.at (saturating_plus.lhs ());
1319+ const smt_termt &right = converted.at (saturating_plus.rhs ());
1320+
1321+ if (const auto signed_type = type_try_dynamic_cast<signedbv_typet>(op_type))
1322+ {
1323+ const std::size_t width = signed_type->get_width ();
1324+
1325+ // Compute sum with one extra bit using sign extension
1326+ const auto extended_left = smt_bit_vector_theoryt::sign_extend (1 )(left);
1327+ const auto extended_right = smt_bit_vector_theoryt::sign_extend (1 )(right);
1328+ const auto sum = smt_bit_vector_theoryt::add (extended_left, extended_right);
1329+
1330+ // Extract the top bit (sign bit of extended result) and the original sign bit
1331+ const auto top_bit = smt_bit_vector_theoryt::extract (width, width)(sum);
1332+ const auto sign_bit = smt_bit_vector_theoryt::extract (width - 1 , width - 1 )(sum);
1333+
1334+ // If the top two bits are equal, no overflow occurred
1335+ const auto no_overflow = smt_core_theoryt::equal (top_bit, sign_bit);
1336+
1337+ // Extract the result (lower bits)
1338+ const auto result = smt_bit_vector_theoryt::extract (width - 1 , 0 )(sum);
1339+
1340+ // If overflow occurred, check if it's positive or negative overflow
1341+ const auto is_positive_overflow = smt_core_theoryt::equal (
1342+ top_bit, smt_bit_vector_constant_termt{0 , 1 });
1343+
1344+ // Return MAX if positive overflow, MIN if negative overflow, otherwise result
1345+ return smt_core_theoryt::if_then_else (
1346+ no_overflow,
1347+ result,
1348+ smt_core_theoryt::if_then_else (
1349+ is_positive_overflow,
1350+ smt_bit_vector_constant_termt{power (2 , width - 1 ) - 1 , width}, // MAX
1351+ smt_bit_vector_constant_termt{power (2 , width - 1 ), width})); // MIN (as unsigned representation)
1352+ }
1353+ else if (const auto unsigned_type = type_try_dynamic_cast<unsignedbv_typet>(op_type))
1354+ {
1355+ const std::size_t width = unsigned_type->get_width ();
1356+
1357+ // Compute sum with one extra bit using zero extension
1358+ const auto extended_left = smt_bit_vector_theoryt::zero_extend (1 )(left);
1359+ const auto extended_right = smt_bit_vector_theoryt::zero_extend (1 )(right);
1360+ const auto sum = smt_bit_vector_theoryt::add (extended_left, extended_right);
1361+
1362+ // Check if the top bit is set (overflow occurred)
1363+ const auto overflow_bit = smt_bit_vector_theoryt::extract (width, width)(sum);
1364+ const auto no_overflow = smt_core_theoryt::equal (
1365+ overflow_bit, smt_bit_vector_constant_termt{0 , 1 });
1366+
1367+ // Extract the result (lower bits)
1368+ const auto result = smt_bit_vector_theoryt::extract (width - 1 , 0 )(sum);
1369+
1370+ // Return MAX if overflow, otherwise result
1371+ return smt_core_theoryt::if_then_else (
1372+ no_overflow,
1373+ result,
1374+ smt_bit_vector_constant_termt{power (2 , width) - 1 , width}); // MAX
1375+ }
1376+ UNIMPLEMENTED_FEATURE (
1377+ " Generation of SMT formula for saturating plus expression: " +
1378+ saturating_plus.pretty ());
1379+ }
1380+
1381+ static smt_termt convert_expr_to_smt (
1382+ const saturating_minus_exprt &saturating_minus,
1383+ const sub_expression_mapt &converted)
1384+ {
1385+ const auto &op_type = saturating_minus.type ();
1386+ const smt_termt &left = converted.at (saturating_minus.lhs ());
1387+ const smt_termt &right = converted.at (saturating_minus.rhs ());
1388+
1389+ if (const auto signed_type = type_try_dynamic_cast<signedbv_typet>(op_type))
1390+ {
1391+ const std::size_t width = signed_type->get_width ();
1392+
1393+ // Compute difference with one extra bit using sign extension
1394+ const auto extended_left = smt_bit_vector_theoryt::sign_extend (1 )(left);
1395+ const auto extended_right = smt_bit_vector_theoryt::sign_extend (1 )(right);
1396+ const auto diff = smt_bit_vector_theoryt::subtract (extended_left, extended_right);
1397+
1398+ // Extract the top bit (sign bit of extended result) and the original sign bit
1399+ const auto top_bit = smt_bit_vector_theoryt::extract (width, width)(diff);
1400+ const auto sign_bit = smt_bit_vector_theoryt::extract (width - 1 , width - 1 )(diff);
1401+
1402+ // If the top two bits are equal, no overflow occurred
1403+ const auto no_overflow = smt_core_theoryt::equal (top_bit, sign_bit);
1404+
1405+ // Extract the result (lower bits)
1406+ const auto result = smt_bit_vector_theoryt::extract (width - 1 , 0 )(diff);
1407+
1408+ // If overflow occurred, check if it's positive or negative overflow
1409+ const auto is_positive_overflow = smt_core_theoryt::equal (
1410+ top_bit, smt_bit_vector_constant_termt{0 , 1 });
1411+
1412+ // Return MAX if positive overflow, MIN if negative overflow, otherwise result
1413+ return smt_core_theoryt::if_then_else (
1414+ no_overflow,
1415+ result,
1416+ smt_core_theoryt::if_then_else (
1417+ is_positive_overflow,
1418+ smt_bit_vector_constant_termt{power (2 , width - 1 ) - 1 , width}, // MAX
1419+ smt_bit_vector_constant_termt{power (2 , width - 1 ), width})); // MIN (as unsigned representation)
1420+ }
1421+ else if (const auto unsigned_type = type_try_dynamic_cast<unsignedbv_typet>(op_type))
1422+ {
1423+ const std::size_t width = unsigned_type->get_width ();
1424+
1425+ // Compute difference with one extra bit using zero extension
1426+ const auto extended_left = smt_bit_vector_theoryt::zero_extend (1 )(left);
1427+ const auto extended_right = smt_bit_vector_theoryt::zero_extend (1 )(right);
1428+ const auto diff = smt_bit_vector_theoryt::subtract (extended_left, extended_right);
1429+
1430+ // Check if the top bit is set (underflow occurred)
1431+ const auto underflow_bit = smt_bit_vector_theoryt::extract (width, width)(diff);
1432+ const auto no_underflow = smt_core_theoryt::equal (
1433+ underflow_bit, smt_bit_vector_constant_termt{0 , 1 });
1434+
1435+ // Extract the result (lower bits)
1436+ const auto result = smt_bit_vector_theoryt::extract (width - 1 , 0 )(diff);
1437+
1438+ // Return MIN (0) if underflow, otherwise result
1439+ return smt_core_theoryt::if_then_else (
1440+ no_underflow,
1441+ result,
1442+ smt_bit_vector_constant_termt{0 , width}); // MIN
1443+ }
1444+ UNIMPLEMENTED_FEATURE (
1445+ " Generation of SMT formula for saturating minus expression: " +
1446+ saturating_minus.pretty ());
1447+ }
1448+
13131449static smt_termt convert_expr_to_smt (
13141450 const pointer_object_exprt &pointer_object,
13151451 const sub_expression_mapt &converted)
@@ -1774,6 +1910,18 @@ static smt_termt dispatch_expr_to_smt_conversion(
17741910 {
17751911 return convert_expr_to_smt (*shl_overflow, converted);
17761912 }
1913+ if (
1914+ const auto saturating_plus =
1915+ expr_try_dynamic_cast<saturating_plus_exprt>(expr))
1916+ {
1917+ return convert_expr_to_smt (*saturating_plus, converted);
1918+ }
1919+ if (
1920+ const auto saturating_minus =
1921+ expr_try_dynamic_cast<saturating_minus_exprt>(expr))
1922+ {
1923+ return convert_expr_to_smt (*saturating_minus, converted);
1924+ }
17771925 if (const auto array_construction = expr_try_dynamic_cast<array_exprt>(expr))
17781926 {
17791927 return convert_expr_to_smt (*array_construction, converted);
0 commit comments