Skip to content

Commit bfd1e57

Browse files
committed
SMT2 parser: add further variants of to_fp
SMT-LIB to_fp has a number of variants, and this commit adds two of them to enable the use of cprover_smt2 with CBMC.
1 parent 0b0c342 commit bfd1e57

File tree

1 file changed

+67
-28
lines changed

1 file changed

+67
-28
lines changed

src/solvers/smt2/smt2_parser.cpp

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -699,44 +699,83 @@ exprt smt2_parsert::function_application()
699699
if(next_token() != smt2_tokenizert::CLOSE)
700700
throw error("expected ')' after to_fp");
701701

702-
auto rounding_mode = expression();
702+
// width_f *includes* the hidden bit
703+
const ieee_float_spect spec(width_f - 1, width_e);
703704

704-
if(next_token() != smt2_tokenizert::NUMERAL)
705-
throw error("expected number after to_fp");
705+
auto rounding_mode = expression();
706706

707-
auto real_number = smt2_tokenizer.get_buffer();
707+
auto source_op = expression();
708708

709709
if(next_token() != smt2_tokenizert::CLOSE)
710710
throw error("expected ')' at the end of to_fp");
711711

712-
mp_integer significand, exponent;
713-
714-
auto dot_pos = real_number.find('.');
715-
if(dot_pos == std::string::npos)
712+
// There are several options for the source operand:
713+
// 1) real or integer
714+
// 2) bit-vector, which is interpreted as signed 2's complement
715+
// 3) another floating-point format
716+
if(
717+
source_op.type().id() == ID_real ||
718+
source_op.type().id() == ID_integer)
716719
{
717-
exponent = 0;
718-
significand = string2integer(real_number);
720+
// For now, we can only do this when
721+
// the source operand is a constant.
722+
if(source_op.id() == ID_constant)
723+
{
724+
mp_integer significand, exponent;
725+
726+
const auto &real_number =
727+
id2string(to_constant_expr(source_op).get_value());
728+
auto dot_pos = real_number.find('.');
729+
if(dot_pos == std::string::npos)
730+
{
731+
exponent = 0;
732+
significand = string2integer(real_number);
733+
}
734+
else
735+
{
736+
// remove the '.'
737+
std::string significand_str;
738+
significand_str.reserve(real_number.size());
739+
for(auto ch : real_number)
740+
{
741+
if(ch != '.')
742+
significand_str += ch;
743+
}
744+
745+
exponent =
746+
mp_integer(dot_pos) - mp_integer(real_number.size()) + 1;
747+
significand = string2integer(significand_str);
748+
}
749+
750+
ieee_floatt a(
751+
spec,
752+
static_cast<ieee_floatt::rounding_modet>(
753+
numeric_cast_v<int>(to_constant_expr(rounding_mode))));
754+
a.from_base10(significand, exponent);
755+
return a.to_expr();
756+
}
757+
else
758+
throw error()
759+
<< "to_fp for non-constant real expressions is not implemented";
719760
}
720-
else
761+
else if(source_op.type().id() == ID_unsignedbv)
721762
{
722-
// remove the '.', if any
723-
std::string significand_str;
724-
significand_str.reserve(real_number.size());
725-
for(auto ch : real_number)
726-
if(ch != '.')
727-
significand_str += ch;
728-
729-
exponent = mp_integer(dot_pos) - mp_integer(real_number.size()) + 1;
730-
significand = string2integer(significand_str);
763+
// The operand is hard-wired to be interpreted as a signed number.
764+
return floatbv_typecast_exprt(
765+
typecast_exprt(
766+
source_op,
767+
signedbv_typet(
768+
to_unsignedbv_type(source_op.type()).get_width())),
769+
rounding_mode,
770+
spec.to_type());
731771
}
732-
733-
// width_f *includes* the hidden bit
734-
ieee_float_spect spec(width_f - 1, width_e);
735-
ieee_floatt a(spec);
736-
a.rounding_mode = static_cast<ieee_floatt::rounding_modet>(
737-
numeric_cast_v<int>(to_constant_expr(rounding_mode)));
738-
a.from_base10(significand, exponent);
739-
return a.to_expr();
772+
else if(source_op.type().id() == ID_floatbv)
773+
{
774+
return floatbv_typecast_exprt(
775+
source_op, rounding_mode, spec.to_type());
776+
}
777+
else
778+
throw error() << "unexpected sort given as operand to to_fp";
740779
}
741780
else
742781
{

0 commit comments

Comments
 (0)