@@ -872,6 +872,64 @@ exprt smt2_parsert::function_application()
872872 UNREACHABLE;
873873}
874874
875+ exprt smt2_parsert::bv_division (
876+ const exprt::operandst &operands,
877+ bool is_signed)
878+ {
879+ if (operands.size () != 2 )
880+ throw error () << " bitvector division expects two operands" ;
881+
882+ // SMT-LIB2 defines the result of division by 0 to be 1....1
883+ auto divisor = symbol_exprt (" divisor" , operands[1 ].type ());
884+ auto divisor_is_zero = equal_exprt (divisor, from_integer (0 , divisor.type ()));
885+ auto all_ones = to_unsignedbv_type (operands[0 ].type ()).largest_expr ();
886+
887+ exprt division_result;
888+
889+ if (is_signed)
890+ {
891+ auto signed_operands = cast_bv_to_signed ({operands[0 ], divisor});
892+ division_result =
893+ cast_bv_to_unsigned (div_exprt (signed_operands[0 ], signed_operands[1 ]));
894+ }
895+ else
896+ division_result = div_exprt (operands[0 ], divisor);
897+
898+ return let_exprt (
899+ {divisor},
900+ {operands[1 ]},
901+ if_exprt (divisor_is_zero, all_ones, division_result));
902+ }
903+
904+ exprt smt2_parsert::bv_mod (const exprt::operandst &operands, bool is_signed)
905+ {
906+ if (operands.size () != 2 )
907+ throw error () << " bitvector modulo expects two operands" ;
908+
909+ // SMT-LIB2 defines the result of "lhs modulo 0" to be "lhs"
910+ auto dividend = symbol_exprt (" dividend" , operands[0 ].type ());
911+ auto divisor = symbol_exprt (" divisor" , operands[1 ].type ());
912+ auto divisor_is_zero = equal_exprt (divisor, from_integer (0 , divisor.type ()));
913+
914+ exprt mod_result;
915+
916+ // bvurem and bvsrem match our mod_exprt.
917+ // bvsmod doesn't.
918+ if (is_signed)
919+ {
920+ auto signed_operands = cast_bv_to_signed ({dividend, divisor});
921+ mod_result =
922+ cast_bv_to_unsigned (mod_exprt (signed_operands[0 ], signed_operands[1 ]));
923+ }
924+ else
925+ mod_result = mod_exprt (dividend, divisor);
926+
927+ return let_exprt (
928+ {dividend, divisor},
929+ {operands[0 ], operands[1 ]},
930+ if_exprt (divisor_is_zero, dividend, mod_result));
931+ }
932+
875933exprt smt2_parsert::expression ()
876934{
877935 switch (next_token ())
@@ -1045,27 +1103,17 @@ void smt2_parsert::setup_expressions()
10451103 return binary (ID_minus, op);
10461104 };
10471105
1048- expressions[" bvsdiv" ] = [this ] {
1049- return cast_bv_to_unsigned (binary (ID_div, cast_bv_to_signed (operands ())));
1050- };
1051-
1052- expressions[" bvudiv" ] = [this ] { return binary (ID_div, operands ()); };
1106+ expressions[" bvsdiv" ] = [this ] { return bv_division (operands (), true ); };
1107+ expressions[" bvudiv" ] = [this ] { return bv_division (operands (), false ); };
10531108 expressions[" /" ] = [this ] { return binary (ID_div, operands ()); };
10541109 expressions[" div" ] = [this ] { return binary (ID_div, operands ()); };
10551110
1056- expressions[" bvsrem" ] = [this ] {
1057- // 2's complement signed remainder (sign follows dividend)
1058- // This matches our ID_mod, and what C does since C99.
1059- return cast_bv_to_unsigned (binary (ID_mod, cast_bv_to_signed (operands ())));
1060- };
1061-
1062- expressions[" bvsmod" ] = [this ] {
1063- // 2's complement signed remainder (sign follows divisor)
1064- // We don't have that.
1065- return cast_bv_to_unsigned (binary (ID_mod, cast_bv_to_signed (operands ())));
1066- };
1111+ expressions[" bvsrem" ] = [this ] { return bv_mod (operands (), true ); };
1112+ expressions[" bvurem" ] = [this ] { return bv_mod (operands (), false ); };
10671113
1068- expressions[" bvurem" ] = [this ] { return binary (ID_mod, operands ()); };
1114+ // 2's complement signed remainder (sign follows divisor)
1115+ // We don't have that.
1116+ expressions[" bvsmod" ] = [this ] { return bv_mod (operands (), true ); };
10691117
10701118 expressions[" %" ] = [this ] { return binary (ID_mod, operands ()); };
10711119
0 commit comments