@@ -879,6 +879,64 @@ exprt smt2_parsert::function_application()
879879 UNREACHABLE;
880880}
881881
882+ exprt smt2_parsert::bv_division (
883+ const exprt::operandst &operands,
884+ bool is_signed)
885+ {
886+ if (operands.size () != 2 )
887+ throw error () << " bitvector division expects two operands" ;
888+
889+ // SMT-LIB2 defines the result of division by 0 to be 1....1
890+ auto divisor = symbol_exprt (" divisor" , operands[1 ].type ());
891+ auto divisor_is_zero = equal_exprt (divisor, from_integer (0 , divisor.type ()));
892+ auto all_ones = to_unsignedbv_type (operands[0 ].type ()).largest_expr ();
893+
894+ exprt division_result;
895+
896+ if (is_signed)
897+ {
898+ auto signed_operands = cast_bv_to_signed ({operands[0 ], divisor});
899+ division_result =
900+ cast_bv_to_unsigned (div_exprt (signed_operands[0 ], signed_operands[1 ]));
901+ }
902+ else
903+ division_result = div_exprt (operands[0 ], divisor);
904+
905+ return let_exprt (
906+ {divisor},
907+ {operands[1 ]},
908+ if_exprt (divisor_is_zero, all_ones, division_result));
909+ }
910+
911+ exprt smt2_parsert::bv_mod (const exprt::operandst &operands, bool is_signed)
912+ {
913+ if (operands.size () != 2 )
914+ throw error () << " bitvector modulo expects two operands" ;
915+
916+ // SMT-LIB2 defines the result of "lhs modulo 0" to be "lhs"
917+ auto dividend = symbol_exprt (" dividend" , operands[0 ].type ());
918+ auto divisor = symbol_exprt (" divisor" , operands[1 ].type ());
919+ auto divisor_is_zero = equal_exprt (divisor, from_integer (0 , divisor.type ()));
920+
921+ exprt mod_result;
922+
923+ // bvurem and bvsrem match our mod_exprt.
924+ // bvsmod doesn't.
925+ if (is_signed)
926+ {
927+ auto signed_operands = cast_bv_to_signed ({dividend, divisor});
928+ mod_result =
929+ cast_bv_to_unsigned (mod_exprt (signed_operands[0 ], signed_operands[1 ]));
930+ }
931+ else
932+ mod_result = mod_exprt (dividend, divisor);
933+
934+ return let_exprt (
935+ {dividend, divisor},
936+ {operands[0 ], operands[1 ]},
937+ if_exprt (divisor_is_zero, dividend, mod_result));
938+ }
939+
882940exprt smt2_parsert::expression ()
883941{
884942 switch (next_token ())
@@ -1053,27 +1111,17 @@ void smt2_parsert::setup_expressions()
10531111 return binary (ID_minus, op);
10541112 };
10551113
1056- expressions[" bvsdiv" ] = [this ] {
1057- return cast_bv_to_unsigned (binary (ID_div, cast_bv_to_signed (operands ())));
1058- };
1059-
1060- expressions[" bvudiv" ] = [this ] { return binary (ID_div, operands ()); };
1114+ expressions[" bvsdiv" ] = [this ] { return bv_division (operands (), true ); };
1115+ expressions[" bvudiv" ] = [this ] { return bv_division (operands (), false ); };
10611116 expressions[" /" ] = [this ] { return binary (ID_div, operands ()); };
10621117 expressions[" div" ] = [this ] { return binary (ID_div, operands ()); };
10631118
1064- expressions[" bvsrem" ] = [this ] {
1065- // 2's complement signed remainder (sign follows dividend)
1066- // This matches our ID_mod, and what C does since C99.
1067- return cast_bv_to_unsigned (binary (ID_mod, cast_bv_to_signed (operands ())));
1068- };
1069-
1070- expressions[" bvsmod" ] = [this ] {
1071- // 2's complement signed remainder (sign follows divisor)
1072- // We don't have that.
1073- return cast_bv_to_unsigned (binary (ID_mod, cast_bv_to_signed (operands ())));
1074- };
1119+ expressions[" bvsrem" ] = [this ] { return bv_mod (operands (), true ); };
1120+ expressions[" bvurem" ] = [this ] { return bv_mod (operands (), false ); };
10751121
1076- expressions[" bvurem" ] = [this ] { return binary (ID_mod, operands ()); };
1122+ // 2's complement signed remainder (sign follows divisor)
1123+ // We don't have that.
1124+ expressions[" bvsmod" ] = [this ] { return bv_mod (operands (), true ); };
10771125
10781126 expressions[" %" ] = [this ] { return binary (ID_mod, operands ()); };
10791127
0 commit comments