@@ -879,6 +879,64 @@ exprt smt2_parsert::function_application()
879
879
UNREACHABLE;
880
880
}
881
881
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
+
882
940
exprt smt2_parsert::expression ()
883
941
{
884
942
switch (next_token ())
@@ -1053,27 +1111,17 @@ void smt2_parsert::setup_expressions()
1053
1111
return binary (ID_minus, op);
1054
1112
};
1055
1113
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 ); };
1061
1116
expressions[" /" ] = [this ] { return binary (ID_div, operands ()); };
1062
1117
expressions[" div" ] = [this ] { return binary (ID_div, operands ()); };
1063
1118
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 ); };
1075
1121
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 ); };
1077
1125
1078
1126
expressions[" %" ] = [this ] { return binary (ID_mod, operands ()); };
1079
1127
0 commit comments