Skip to content

Commit 13644d9

Browse files
authored
Merge pull request #4074 from diffblue/fix-smt2-binary
Fix use of binary irep in smt2_conv
2 parents 51a717a + a73ac9d commit 13644d9

File tree

4 files changed

+107
-35
lines changed

4 files changed

+107
-35
lines changed

src/solvers/smt2/smt2_conv.cpp

+52-34
Original file line numberDiff line numberDiff line change
@@ -275,11 +275,15 @@ constant_exprt smt2_convt::parse_literal(
275275
parse_literal(src.get_sub()[2], unsignedbv_typet(floatbv_type.get_e()));
276276
constant_exprt s3 =
277277
parse_literal(src.get_sub()[3], unsignedbv_typet(floatbv_type.get_f()));
278+
279+
const auto s1_int = numeric_cast_v<mp_integer>(s1);
280+
const auto s2_int = numeric_cast_v<mp_integer>(s2);
281+
const auto s3_int = numeric_cast_v<mp_integer>(s3);
282+
278283
// stitch the bits together
279-
std::string bits=id2string(s1.get_value())+
280-
id2string(s2.get_value())+
281-
id2string(s3.get_value());
282-
value=binary2integer(bits, false);
284+
value = bitwise_or(
285+
s1_int << (floatbv_type.get_e() + floatbv_type.get_f()),
286+
bitwise_or((s2_int << floatbv_type.get_f()), s3_int));
283287
}
284288
else
285289
value=0;
@@ -318,10 +322,12 @@ constant_exprt smt2_convt::parse_literal(
318322
}
319323
else if(type.id()==ID_c_enum_tag)
320324
{
321-
return
322-
from_integer(
323-
value,
324-
ns.follow_tag(to_c_enum_tag_type(type)));
325+
constant_exprt result =
326+
from_integer(value, ns.follow_tag(to_c_enum_tag_type(type)));
327+
328+
// restore the c_enum_tag type
329+
result.type() = type;
330+
return result;
325331
}
326332
else if(type.id()==ID_fixedbv ||
327333
type.id()==ID_floatbv)
@@ -331,7 +337,9 @@ constant_exprt smt2_convt::parse_literal(
331337
}
332338
else if(type.id()==ID_integer ||
333339
type.id()==ID_range)
340+
{
334341
return from_integer(value, type);
342+
}
335343
else
336344
INVARIANT(
337345
false,
@@ -384,25 +392,24 @@ exprt smt2_convt::parse_union(
384392
return union_exprt(first.get_name(), converted, type);
385393
}
386394

387-
exprt smt2_convt::parse_struct(
388-
const irept &src,
389-
const struct_typet &type)
395+
struct_exprt
396+
smt2_convt::parse_struct(const irept &src, const struct_typet &type)
390397
{
391398
const struct_typet::componentst &components =
392399
type.components();
393400

394401
struct_exprt result(exprt::operandst(components.size(), nil_exprt()), type);
395402

396403
if(components.empty())
397-
return std::move(result);
404+
return result;
398405

399406
if(use_datatypes)
400407
{
401408
// Structs look like:
402409
// (mk-struct.1 <component0> <component1> ... <componentN>)
403410

404411
if(src.get_sub().size()!=components.size()+1)
405-
return std::move(result); // give up
412+
return result; // give up
406413

407414
for(std::size_t i=0; i<components.size(); i++)
408415
{
@@ -414,13 +421,12 @@ exprt smt2_convt::parse_struct(
414421
{
415422
// These are just flattened, i.e., we expect to see a monster bit vector.
416423
std::size_t total_width=boolbv_width(type);
417-
exprt l = parse_literal(src, unsignedbv_typet(total_width));
418-
if(!l.is_constant())
419-
return nil_exprt();
424+
const auto l = parse_literal(src, unsignedbv_typet(total_width));
420425

421-
irep_idt binary=to_constant_expr(l).get_value();
422-
if(binary.size()!=total_width)
423-
return nil_exprt();
426+
const irep_idt binary =
427+
integer2binary(numeric_cast_v<mp_integer>(l), total_width);
428+
429+
CHECK_RETURN(binary.size() == total_width);
424430

425431
std::size_t offset=0;
426432

@@ -443,20 +449,17 @@ exprt smt2_convt::parse_struct(
443449
}
444450
}
445451

446-
return std::move(result);
452+
return result;
447453
}
448454

449-
exprt smt2_convt::parse_rec(const irept &src, const typet &_type)
455+
exprt smt2_convt::parse_rec(const irept &src, const typet &type)
450456
{
451-
const typet &type=ns.follow(_type);
452-
453-
if(type.id()==ID_signedbv ||
454-
type.id()==ID_unsignedbv ||
455-
type.id()==ID_integer ||
456-
type.id()==ID_rational ||
457-
type.id()==ID_real ||
458-
type.id()==ID_fixedbv ||
459-
type.id()==ID_floatbv)
457+
if(
458+
type.id() == ID_signedbv || type.id() == ID_unsignedbv ||
459+
type.id() == ID_integer || type.id() == ID_rational ||
460+
type.id() == ID_real || type.id() == ID_c_enum ||
461+
type.id() == ID_c_enum_tag || type.id() == ID_fixedbv ||
462+
type.id() == ID_floatbv)
460463
{
461464
return parse_literal(src, type);
462465
}
@@ -486,10 +489,25 @@ exprt smt2_convt::parse_rec(const irept &src, const typet &_type)
486489
{
487490
return parse_struct(src, to_struct_type(type));
488491
}
492+
else if(type.id() == ID_struct_tag)
493+
{
494+
auto struct_expr =
495+
parse_struct(src, ns.follow_tag(to_struct_tag_type(type)));
496+
// restore the tag type
497+
struct_expr.type() = type;
498+
return std::move(struct_expr);
499+
}
489500
else if(type.id()==ID_union)
490501
{
491502
return parse_union(src, to_union_type(type));
492503
}
504+
else if(type.id() == ID_union_tag)
505+
{
506+
auto union_expr = parse_union(src, ns.follow_tag(to_union_tag_type(type)));
507+
// restore the tag type
508+
union_expr.type() = type;
509+
return union_expr;
510+
}
493511
else if(type.id()==ID_array)
494512
{
495513
return parse_array(src, to_array_type(type));
@@ -2371,15 +2389,15 @@ void smt2_convt::convert_typecast(const typecast_exprt &expr)
23712389
significand = 1;
23722390
exponent = 0;
23732391
a.build(significand, exponent);
2374-
val.set(ID_value, integer2binary(a.pack(), a.spec.width()));
2392+
val.set_value(integer2bvrep(a.pack(), a.spec.width()));
23752393

23762394
convert_constant(val);
23772395
out << " ";
23782396

23792397
significand = 0;
23802398
exponent = 0;
23812399
a.build(significand, exponent);
2382-
val.set(ID_value, integer2binary(a.pack(), a.spec.width()));
2400+
val.set_value(integer2bvrep(a.pack(), a.spec.width()));
23832401

23842402
convert_constant(val);
23852403
out << ")";
@@ -2780,7 +2798,7 @@ void smt2_convt::convert_constant(const constant_exprt &expr)
27802798
}
27812799
else if(expr_type.id()==ID_pointer)
27822800
{
2783-
const irep_idt &value=expr.get(ID_value);
2801+
const irep_idt &value = expr.get_value();
27842802

27852803
if(value==ID_NULL)
27862804
{
@@ -3110,7 +3128,7 @@ void smt2_convt::convert_rounding_mode_FPA(const exprt &expr)
31103128
{
31113129
const constant_exprt &cexpr=to_constant_expr(expr);
31123130

3113-
mp_integer value=binary2integer(id2string(cexpr.get_value()), false);
3131+
mp_integer value = numeric_cast_v<mp_integer>(cexpr);
31143132

31153133
if(value==0)
31163134
out << "roundNearestTiesToEven";

src/solvers/smt2/smt2_conv.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ class smt2_convt:public prop_convt
237237

238238
// Parsing solver responses
239239
constant_exprt parse_literal(const irept &, const typet &type);
240-
exprt parse_struct(const irept &s, const struct_typet &type);
240+
struct_exprt parse_struct(const irept &s, const struct_typet &type);
241241
exprt parse_union(const irept &s, const union_typet &type);
242242
exprt parse_array(const irept &s, const array_typet &type);
243243
exprt parse_rec(const irept &s, const typet &type);

src/solvers/smt2/smt2_parser.cpp

+53
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,25 @@ exprt smt2_parsert::binary(irep_idt id, const exprt::operandst &op)
394394
return binary_exprt(op[0], id, op[1], op[0].type());
395395
}
396396

397+
exprt smt2_parsert::function_application_ieee_float_eq(
398+
const exprt::operandst &op)
399+
{
400+
if(op.size() != 2)
401+
throw error() << "FloatingPoint equality takes two operands";
402+
403+
if(op[0].type().id() != ID_floatbv || op[1].type().id() != ID_floatbv)
404+
throw error() << "FloatingPoint equality takes FloatingPoint operands";
405+
406+
if(op[0].type() != op[1].type())
407+
{
408+
throw error() << "FloatingPoint equality takes FloatingPoint operands with "
409+
<< "matching sort, but got " << smt2_format(op[0].type())
410+
<< " vs " << smt2_format(op[1].type());
411+
}
412+
413+
return ieee_float_equal_exprt(op[0], op[1]);
414+
}
415+
397416
exprt smt2_parsert::function_application_ieee_float_op(
398417
const irep_idt &id,
399418
const exprt::operandst &op)
@@ -745,6 +764,16 @@ exprt smt2_parsert::function_application()
745764

746765
return unary_predicate_exprt(ID_isinf, op[0]);
747766
}
767+
else if(id == "fp.isNormal")
768+
{
769+
if(op.size() != 1)
770+
throw error("fp.isNormal takes one operand");
771+
772+
if(op[0].type().id() != ID_floatbv)
773+
throw error("fp.isNormal takes FloatingPoint operand");
774+
775+
return isnormal_exprt(op[0]);
776+
}
748777
else if(id == "fp")
749778
{
750779
return function_application_fp(op);
@@ -754,6 +783,30 @@ exprt smt2_parsert::function_application()
754783
{
755784
return function_application_ieee_float_op(id, op);
756785
}
786+
else if(id == "fp.eq")
787+
{
788+
return function_application_ieee_float_eq(op);
789+
}
790+
else if(id == "fp.leq")
791+
{
792+
return binary_predicate(ID_le, op);
793+
}
794+
else if(id == "fp.lt")
795+
{
796+
return binary_predicate(ID_lt, op);
797+
}
798+
else if(id == "fp.geq")
799+
{
800+
return binary_predicate(ID_ge, op);
801+
}
802+
else if(id == "fp.gt")
803+
{
804+
return binary_predicate(ID_gt, op);
805+
}
806+
else if(id == "fp.neg")
807+
{
808+
return unary(ID_unary_minus, op);
809+
}
757810
else
758811
{
759812
// rummage through id_map

src/solvers/smt2/smt2_parser.h

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ class smt2_parsert
122122
exprt function_application_ieee_float_op(
123123
const irep_idt &,
124124
const exprt::operandst &);
125+
exprt function_application_ieee_float_eq(const exprt::operandst &);
125126
exprt function_application_fp(const exprt::operandst &);
126127
typet sort();
127128
exprt::operandst operands();

0 commit comments

Comments
 (0)