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