@@ -872,6 +872,64 @@ exprt smt2_parsert::function_application()
872
872
UNREACHABLE;
873
873
}
874
874
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
+
875
933
exprt smt2_parsert::expression ()
876
934
{
877
935
switch (next_token ())
@@ -1045,27 +1103,17 @@ void smt2_parsert::setup_expressions()
1045
1103
return binary (ID_minus, op);
1046
1104
};
1047
1105
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 ); };
1053
1108
expressions[" /" ] = [this ] { return binary (ID_div, operands ()); };
1054
1109
expressions[" div" ] = [this ] { return binary (ID_div, operands ()); };
1055
1110
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 ); };
1067
1113
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 ); };
1069
1117
1070
1118
expressions[" %" ] = [this ] { return binary (ID_mod, operands ()); };
1071
1119
0 commit comments