14
14
#include < util/arith_tools.h>
15
15
#include < util/c_types.h>
16
16
#include < util/config.h>
17
+ #include < util/expr_iterator.h>
17
18
#include < util/expr_util.h>
18
19
#include < util/fixedbv.h>
19
20
#include < util/format_expr.h>
@@ -612,24 +613,6 @@ void smt2_convt::convert_address_of_rec(
612
613
expr.id_string ());
613
614
}
614
615
615
- void smt2_convt::convert_byte_extract (const byte_extract_exprt &expr)
616
- {
617
- // we just run the flattener
618
- exprt flattened_expr = lower_byte_extract (expr, ns);
619
- unflatten (wheret::BEGIN, expr.type ());
620
- convert_expr (flattened_expr);
621
- unflatten (wheret::END, expr.type ());
622
- }
623
-
624
- void smt2_convt::convert_byte_update (const byte_update_exprt &expr)
625
- {
626
- // we just run the flattener
627
- exprt flattened_expr = lower_byte_update (expr, ns);
628
- unflatten (wheret::BEGIN, expr.type ());
629
- convert_expr (flattened_expr);
630
- unflatten (wheret::END, expr.type ());
631
- }
632
-
633
616
literalt smt2_convt::convert (const exprt &expr)
634
617
{
635
618
PRECONDITION (expr.type ().id () == ID_bool);
@@ -647,7 +630,7 @@ literalt smt2_convt::convert(const exprt &expr)
647
630
648
631
out << " \n " ;
649
632
650
- find_symbols (expr);
633
+ exprt prepared_expr = prepare_expr (expr);
651
634
652
635
literalt l (no_boolean_variables, false );
653
636
no_boolean_variables++;
@@ -656,7 +639,7 @@ literalt smt2_convt::convert(const exprt &expr)
656
639
out << " (define-fun " ;
657
640
convert_literal (l);
658
641
out << " () Bool " ;
659
- convert_expr (expr );
642
+ convert_expr (prepared_expr );
660
643
out << " )" << " \n " ;
661
644
662
645
return l;
@@ -1431,12 +1414,12 @@ void smt2_convt::convert_expr(const exprt &expr)
1431
1414
else if (expr.id ()==ID_byte_extract_little_endian ||
1432
1415
expr.id ()==ID_byte_extract_big_endian)
1433
1416
{
1434
- convert_byte_extract ( to_byte_extract_expr (expr) );
1417
+ INVARIANT ( false , " byte_extract ops should be lowered in prepare_expr " );
1435
1418
}
1436
1419
else if (expr.id ()==ID_byte_update_little_endian ||
1437
1420
expr.id ()==ID_byte_update_big_endian)
1438
1421
{
1439
- convert_byte_update ( to_byte_update_expr (expr) );
1422
+ INVARIANT ( false , " byte_update ops should be lowered in prepare_expr " );
1440
1423
}
1441
1424
else if (expr.id ()==ID_width)
1442
1425
{
@@ -4058,7 +4041,7 @@ void smt2_convt::set_to(const exprt &expr, bool value)
4058
4041
4059
4042
id.type =equal_expr.lhs ().type ();
4060
4043
find_symbols (id.type );
4061
- find_symbols (equal_expr.rhs ());
4044
+ exprt prepared_rhs = prepare_expr (equal_expr.rhs ());
4062
4045
4063
4046
std::string smt2_identifier=convert_identifier (identifier);
4064
4047
smt2_identifiers.insert (smt2_identifier);
@@ -4068,15 +4051,15 @@ void smt2_convt::set_to(const exprt &expr, bool value)
4068
4051
4069
4052
convert_type (equal_expr.lhs ().type ());
4070
4053
out << " " ;
4071
- convert_expr (equal_expr. rhs () );
4054
+ convert_expr (prepared_rhs );
4072
4055
4073
4056
out << " )" << " \n " ;
4074
4057
return ; // done
4075
4058
}
4076
4059
}
4077
4060
}
4078
4061
4079
- find_symbols (expr);
4062
+ exprt prepared_expr = prepare_expr (expr);
4080
4063
4081
4064
#if 0
4082
4065
out << "; CONV: "
@@ -4089,17 +4072,71 @@ void smt2_convt::set_to(const exprt &expr, bool value)
4089
4072
if (!value)
4090
4073
{
4091
4074
out << " (not " ;
4092
- convert_expr (expr );
4075
+ convert_expr (prepared_expr );
4093
4076
out << " )" ;
4094
4077
}
4095
4078
else
4096
- convert_expr (expr );
4079
+ convert_expr (prepared_expr );
4097
4080
4098
4081
out << " )" << " \n " ; // assert
4099
4082
4100
4083
return ;
4101
4084
}
4102
4085
4086
+ exprt smt2_convt::lower_byte_operators_rec (const exprt &expr)
4087
+ {
4088
+ exprt lowered_expr = expr;
4089
+
4090
+ for (auto it = lowered_expr.depth_begin (), itend = lowered_expr.depth_end ();
4091
+ it != itend;
4092
+ /* No ++it */ )
4093
+ {
4094
+ if (
4095
+ it->id () == ID_byte_extract_little_endian ||
4096
+ it->id () == ID_byte_extract_big_endian)
4097
+ {
4098
+ // Note we must recurse to get a fresh iterator because depth_iteratort
4099
+ // currently crashes if we try to recurse into an expression we've
4100
+ // altered.
4101
+ it.mutate () =
4102
+ lower_byte_operators_rec (
4103
+ lower_byte_extract (to_byte_extract_expr (*it), ns));
4104
+ it.next_sibling_or_parent ();
4105
+ }
4106
+ else if (
4107
+ it->id () == ID_byte_update_little_endian ||
4108
+ it->id () == ID_byte_update_big_endian)
4109
+ {
4110
+ // Note we must recurse to get a fresh iterator because depth_iteratort
4111
+ // currently crashes if we try to recurse into an expression we've
4112
+ // altered.
4113
+ it.mutate () =
4114
+ lower_byte_operators_rec (
4115
+ lower_byte_update (to_byte_update_expr (*it), ns));
4116
+ it.next_sibling_or_parent ();
4117
+ }
4118
+ else
4119
+ {
4120
+ ++it;
4121
+ }
4122
+ }
4123
+
4124
+ return lowered_expr;
4125
+ }
4126
+
4127
+ exprt smt2_convt::prepare_expr (const exprt &expr)
4128
+ {
4129
+ // First, replace byte operators, because they may introduce new array
4130
+ // expressions that must be seen by find_symbols:
4131
+ exprt lowered_expr = lower_byte_operators_rec (expr);
4132
+ INVARIANT (!has_byte_operator (lowered_expr), " should be gone" );
4133
+
4134
+ // Now create symbols for all composite expressions present in lowered_expr:
4135
+ find_symbols (lowered_expr);
4136
+
4137
+ return lowered_expr;
4138
+ }
4139
+
4103
4140
void smt2_convt::find_symbols (const exprt &expr)
4104
4141
{
4105
4142
// recursive call on type
0 commit comments