@@ -11,6 +11,7 @@ Author: Daniel Kroening, kroening@kroening.com
1111#include " smt2_format.h"
1212
1313#include < util/arith_tools.h>
14+ #include < util/ieee_float.h>
1415#include < util/range.h>
1516
1617#include < numeric>
@@ -398,6 +399,74 @@ exprt smt2_parsert::binary(irep_idt id, const exprt::operandst &op)
398399 return binary_exprt (op[0 ], id, op[1 ], op[0 ].type ());
399400}
400401
402+ exprt smt2_parsert::function_application_ieee_float_op (
403+ const irep_idt &id,
404+ const exprt::operandst &op)
405+ {
406+ if (op.size () != 3 )
407+ {
408+ std::ostringstream message;
409+ message << id << " takes three operands" ;
410+ throw error (message);
411+ }
412+
413+ if (op[1 ].type ().id () != ID_floatbv || op[2 ].type ().id () != ID_floatbv)
414+ {
415+ std::ostringstream message;
416+ message << id << " takes FloatingPoint operands" ;
417+ throw error (message);
418+ }
419+
420+ if (op[1 ].type () != op[2 ].type ())
421+ {
422+ std::ostringstream message;
423+ message << id << " takes FloatingPoint operands with matching sort, "
424+ << " but got " << smt2_format (op[1 ].type ()) << " vs "
425+ << smt2_format (op[2 ].type ());
426+ throw error (message);
427+ }
428+
429+ // clang-format off
430+ const irep_idt expr_id =
431+ id == " fp.add" ? ID_floatbv_plus :
432+ id == " fp.sub" ? ID_floatbv_minus :
433+ id == " fp.mul" ? ID_floatbv_mult :
434+ id == " fp.div" ? ID_floatbv_div :
435+ throw error (" unsupported floating-point operation" );
436+ // clang-format on
437+
438+ return std::move (ieee_float_op_exprt (op[1 ], expr_id, op[2 ], op[0 ]));
439+ }
440+
441+ exprt smt2_parsert::function_application_fp (const exprt::operandst &op)
442+ {
443+ // floating-point from bit-vectors
444+ if (op.size () != 3 )
445+ throw error (" fp takes three operands" );
446+
447+ if (op[0 ].type ().id () != ID_unsignedbv)
448+ throw error (" fp takes BitVec as first operand" );
449+
450+ if (op[1 ].type ().id () != ID_unsignedbv)
451+ throw error (" fp takes BitVec as second operand" );
452+
453+ if (op[2 ].type ().id () != ID_unsignedbv)
454+ throw error (" fp takes BitVec as third operand" );
455+
456+ if (to_unsignedbv_type (op[0 ].type ()).get_width () != 1 )
457+ throw error (" fp takes BitVec of size 1 as first operand" );
458+
459+ const auto width_e = to_unsignedbv_type (op[1 ].type ()).get_width ();
460+ const auto width_f = to_unsignedbv_type (op[2 ].type ()).get_width ();
461+
462+ // stitch the bits together
463+ concatenation_exprt c (bv_typet (width_e + width_f + 1 ));
464+ c.operands () = {op[0 ], op[1 ], op[2 ]};
465+
466+ return std::move (
467+ typecast_exprt (c, ieee_float_spect (width_f, width_e).to_type ()));
468+ }
469+
401470exprt smt2_parsert::function_application ()
402471{
403472 switch (next_token ())
@@ -674,6 +743,35 @@ exprt smt2_parsert::function_application()
674743
675744 return with_exprt (op[0 ], op[1 ], op[2 ]);
676745 }
746+ else if (id == " fp.isNaN" )
747+ {
748+ if (op.size () != 1 )
749+ throw error (" fp.isNaN takes one operand" );
750+
751+ if (op[0 ].type ().id () != ID_floatbv)
752+ throw error (" fp.isNaN takes FloatingPoint operand" );
753+
754+ return unary_predicate_exprt (ID_isnan, op[0 ]);
755+ }
756+ else if (id == " fp.isInf" )
757+ {
758+ if (op.size () != 1 )
759+ throw error (" fp.isInf takes one operand" );
760+
761+ if (op[0 ].type ().id () != ID_floatbv)
762+ throw error (" fp.isInf takes FloatingPoint operand" );
763+
764+ return unary_predicate_exprt (ID_isinf, op[0 ]);
765+ }
766+ else if (id == " fp" )
767+ {
768+ return function_application_fp (op);
769+ }
770+ else if (
771+ id == " fp.add" || id == " fp.mul" || id == " fp.sub" || id == " fp.div" )
772+ {
773+ return function_application_ieee_float_op (id, op);
774+ }
677775 else
678776 {
679777 // rummage through id_map
@@ -864,6 +962,32 @@ exprt smt2_parsert::expression()
864962 return true_exprt ();
865963 else if (identifier==ID_false)
866964 return false_exprt ();
965+ else if (identifier == " roundNearestTiesToEven" )
966+ {
967+ // we encode as 32-bit unsignedbv
968+ return from_integer (ieee_floatt::ROUND_TO_EVEN, unsignedbv_typet (32 ));
969+ }
970+ else if (identifier == " roundNearestTiesToAway" )
971+ {
972+ throw error (" unsupported rounding mode" );
973+ }
974+ else if (identifier == " roundTowardPositive" )
975+ {
976+ // we encode as 32-bit unsignedbv
977+ return from_integer (
978+ ieee_floatt::ROUND_TO_PLUS_INF, unsignedbv_typet (32 ));
979+ }
980+ else if (identifier == " roundTowardNegative" )
981+ {
982+ // we encode as 32-bit unsignedbv
983+ return from_integer (
984+ ieee_floatt::ROUND_TO_MINUS_INF, unsignedbv_typet (32 ));
985+ }
986+ else if (identifier == " roundTowardZero" )
987+ {
988+ // we encode as 32-bit unsignedbv
989+ return from_integer (ieee_floatt::ROUND_TO_ZERO, unsignedbv_typet (32 ));
990+ }
867991 else
868992 {
869993 // rummage through id_map
@@ -959,6 +1083,24 @@ typet smt2_parsert::sort()
9591083
9601084 return unsignedbv_typet (width);
9611085 }
1086+ else if (buffer == " FloatingPoint" )
1087+ {
1088+ if (next_token () != NUMERAL)
1089+ throw error (" expected numeral as bit-width" );
1090+
1091+ const auto width_e = std::stoll (buffer);
1092+
1093+ if (next_token () != NUMERAL)
1094+ throw error (" expected numeral as bit-width" );
1095+
1096+ const auto width_f = std::stoll (buffer);
1097+
1098+ // consume the ')'
1099+ if (next_token () != CLOSE)
1100+ throw error (" expected ')' at end of sort" );
1101+
1102+ return ieee_float_spect (width_f - 1 , width_e).to_type ();
1103+ }
9621104 else
9631105 {
9641106 std::ostringstream msg;
0 commit comments