@@ -1310,6 +1310,150 @@ 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 =
1333+ smt_bit_vector_theoryt::extract (width - 1 , width - 1 )(sum);
1334+
1335+ // If the top two bits are equal, no overflow occurred
1336+ const auto no_overflow = smt_core_theoryt::equal (top_bit, sign_bit);
1337+
1338+ // Extract the result (lower bits)
1339+ const auto result = smt_bit_vector_theoryt::extract (width - 1 , 0 )(sum);
1340+
1341+ // If overflow occurred, check if it's positive or negative overflow
1342+ const auto is_positive_overflow =
1343+ smt_core_theoryt::equal (top_bit, smt_bit_vector_constant_termt{0 , 1 });
1344+
1345+ // Return MAX if positive overflow, MIN if negative overflow, otherwise result
1346+ return smt_core_theoryt::if_then_else (
1347+ no_overflow,
1348+ result,
1349+ smt_core_theoryt::if_then_else (
1350+ is_positive_overflow,
1351+ smt_bit_vector_constant_termt{power (2 , width - 1 ) - 1 , width}, // MAX
1352+ smt_bit_vector_constant_termt{
1353+ power (2 , width - 1 ), width})); // MIN (as unsigned representation)
1354+ }
1355+ else if (
1356+ const auto unsigned_type = type_try_dynamic_cast<unsignedbv_typet>(op_type))
1357+ {
1358+ const std::size_t width = unsigned_type->get_width ();
1359+
1360+ // Compute sum with one extra bit using zero extension
1361+ const auto extended_left = smt_bit_vector_theoryt::zero_extend (1 )(left);
1362+ const auto extended_right = smt_bit_vector_theoryt::zero_extend (1 )(right);
1363+ const auto sum = smt_bit_vector_theoryt::add (extended_left, extended_right);
1364+
1365+ // Check if the top bit is set (overflow occurred)
1366+ const auto overflow_bit =
1367+ smt_bit_vector_theoryt::extract (width, width)(sum);
1368+ const auto no_overflow = smt_core_theoryt::equal (
1369+ overflow_bit, smt_bit_vector_constant_termt{0 , 1 });
1370+
1371+ // Extract the result (lower bits)
1372+ const auto result = smt_bit_vector_theoryt::extract (width - 1 , 0 )(sum);
1373+
1374+ // Return MAX if overflow, otherwise result
1375+ return smt_core_theoryt::if_then_else (
1376+ no_overflow,
1377+ result,
1378+ smt_bit_vector_constant_termt{power (2 , width) - 1 , width}); // MAX
1379+ }
1380+ UNIMPLEMENTED_FEATURE (
1381+ " Generation of SMT formula for saturating plus expression: " +
1382+ saturating_plus.pretty ());
1383+ }
1384+
1385+ static smt_termt convert_expr_to_smt (
1386+ const saturating_minus_exprt &saturating_minus,
1387+ const sub_expression_mapt &converted)
1388+ {
1389+ const auto &op_type = saturating_minus.type ();
1390+ const smt_termt &left = converted.at (saturating_minus.lhs ());
1391+ const smt_termt &right = converted.at (saturating_minus.rhs ());
1392+
1393+ if (const auto signed_type = type_try_dynamic_cast<signedbv_typet>(op_type))
1394+ {
1395+ const std::size_t width = signed_type->get_width ();
1396+
1397+ // Compute difference with one extra bit using sign extension
1398+ const auto extended_left = smt_bit_vector_theoryt::sign_extend (1 )(left);
1399+ const auto extended_right = smt_bit_vector_theoryt::sign_extend (1 )(right);
1400+ const auto diff =
1401+ smt_bit_vector_theoryt::subtract (extended_left, extended_right);
1402+
1403+ // Extract the top bit (sign bit of extended result) and the original sign bit
1404+ const auto top_bit = smt_bit_vector_theoryt::extract (width, width)(diff);
1405+ const auto sign_bit =
1406+ smt_bit_vector_theoryt::extract (width - 1 , width - 1 )(diff);
1407+
1408+ // If the top two bits are equal, no overflow occurred
1409+ const auto no_overflow = smt_core_theoryt::equal (top_bit, sign_bit);
1410+
1411+ // Extract the result (lower bits)
1412+ const auto result = smt_bit_vector_theoryt::extract (width - 1 , 0 )(diff);
1413+
1414+ // If overflow occurred, check if it's positive or negative overflow
1415+ const auto is_positive_overflow =
1416+ smt_core_theoryt::equal (top_bit, smt_bit_vector_constant_termt{0 , 1 });
1417+
1418+ // Return MAX if positive overflow, MIN if negative overflow, otherwise result
1419+ return smt_core_theoryt::if_then_else (
1420+ no_overflow,
1421+ result,
1422+ smt_core_theoryt::if_then_else (
1423+ is_positive_overflow,
1424+ smt_bit_vector_constant_termt{power (2 , width - 1 ) - 1 , width}, // MAX
1425+ smt_bit_vector_constant_termt{
1426+ power (2 , width - 1 ), width})); // MIN (as unsigned representation)
1427+ }
1428+ else if (
1429+ const auto unsigned_type = type_try_dynamic_cast<unsignedbv_typet>(op_type))
1430+ {
1431+ const std::size_t width = unsigned_type->get_width ();
1432+
1433+ // Compute difference with one extra bit using zero extension
1434+ const auto extended_left = smt_bit_vector_theoryt::zero_extend (1 )(left);
1435+ const auto extended_right = smt_bit_vector_theoryt::zero_extend (1 )(right);
1436+ const auto diff =
1437+ smt_bit_vector_theoryt::subtract (extended_left, extended_right);
1438+
1439+ // Check if the top bit is set (underflow occurred)
1440+ const auto underflow_bit =
1441+ smt_bit_vector_theoryt::extract (width, width)(diff);
1442+ const auto no_underflow = smt_core_theoryt::equal (
1443+ underflow_bit, smt_bit_vector_constant_termt{0 , 1 });
1444+
1445+ // Extract the result (lower bits)
1446+ const auto result = smt_bit_vector_theoryt::extract (width - 1 , 0 )(diff);
1447+
1448+ // Return MIN (0) if underflow, otherwise result
1449+ return smt_core_theoryt::if_then_else (
1450+ no_underflow, result, smt_bit_vector_constant_termt{0 , width}); // MIN
1451+ }
1452+ UNIMPLEMENTED_FEATURE (
1453+ " Generation of SMT formula for saturating minus expression: " +
1454+ saturating_minus.pretty ());
1455+ }
1456+
13131457static smt_termt convert_expr_to_smt (
13141458 const pointer_object_exprt &pointer_object,
13151459 const sub_expression_mapt &converted)
@@ -1774,6 +1918,18 @@ static smt_termt dispatch_expr_to_smt_conversion(
17741918 {
17751919 return convert_expr_to_smt (*shl_overflow, converted);
17761920 }
1921+ if (
1922+ const auto saturating_plus =
1923+ expr_try_dynamic_cast<saturating_plus_exprt>(expr))
1924+ {
1925+ return convert_expr_to_smt (*saturating_plus, converted);
1926+ }
1927+ if (
1928+ const auto saturating_minus =
1929+ expr_try_dynamic_cast<saturating_minus_exprt>(expr))
1930+ {
1931+ return convert_expr_to_smt (*saturating_minus, converted);
1932+ }
17771933 if (const auto array_construction = expr_try_dynamic_cast<array_exprt>(expr))
17781934 {
17791935 return convert_expr_to_smt (*array_construction, converted);
0 commit comments