8
8
9
9
#include " boolbv.h"
10
10
11
- #include < cassert>
12
-
11
+ #include < util/invariant.h>
13
12
#include < util/prefix.h>
14
13
#include < util/string2int.h>
15
14
@@ -59,7 +58,7 @@ literalt boolbvt::convert_overflow(const exprt &expr)
59
58
if (operands[0 ].type ()!=operands[1 ].type ())
60
59
throw " operand type mismatch on overflow-*" ;
61
60
62
- assert (bv0.size ()==bv1.size ());
61
+ DATA_INVARIANT (bv0.size ()==bv1.size (), " operands size mismatch " );
63
62
std::size_t old_size=bv0.size ();
64
63
std::size_t new_size=old_size*2 ;
65
64
@@ -86,7 +85,7 @@ literalt boolbvt::convert_overflow(const exprt &expr)
86
85
bv_overflow.reserve (old_size);
87
86
88
87
// get top result bits, plus one more
89
- assert (old_size!=0 );
88
+ DATA_INVARIANT (old_size!=0 , " zero-size operand " );
90
89
for (std::size_t i=old_size-1 ; i<result.size (); i++)
91
90
bv_overflow.push_back (result[i]);
92
91
@@ -96,6 +95,72 @@ literalt boolbvt::convert_overflow(const exprt &expr)
96
95
return !prop.lor (all_one, all_zero);
97
96
}
98
97
}
98
+ else if (expr.id () == ID_overflow_shl)
99
+ {
100
+ if (operands.size () != 2 )
101
+ throw " operator " + expr.id_string () + " takes two operands" ;
102
+
103
+ const bvt &bv0=convert_bv (operands[0 ]);
104
+ const bvt &bv1=convert_bv (operands[1 ]);
105
+
106
+ std::size_t old_size = bv0.size ();
107
+ std::size_t new_size = old_size * 2 ;
108
+
109
+ bv_utilst::representationt rep=
110
+ operands[0 ].type ().id ()==ID_signedbv?bv_utilst::representationt::SIGNED:
111
+ bv_utilst::representationt::UNSIGNED;
112
+
113
+ bvt bv_ext=bv_utils.extension (bv0, new_size, rep);
114
+
115
+ bvt result=bv_utils.shift (bv_ext, bv_utilst::shiftt::LEFT, bv1);
116
+
117
+ // a negative shift is undefined; yet this isn't an overflow
118
+ literalt neg_shift =
119
+ operands[1 ].type ().id () == ID_unsignedbv ?
120
+ const_literal (false ) :
121
+ bv1.back (); // sign bit
122
+
123
+ // an undefined shift of a non-zero value always results in overflow; the
124
+ // use of unsigned comparision is safe here as we cover the signed negative
125
+ // case via neg_shift
126
+ literalt undef =
127
+ bv_utils.rel (
128
+ bv1,
129
+ ID_gt,
130
+ bv_utils.build_constant (old_size, bv1.size ()),
131
+ bv_utilst::representationt::UNSIGNED);
132
+
133
+ literalt overflow;
134
+
135
+ if (rep == bv_utilst::representationt::UNSIGNED)
136
+ {
137
+ // get top result bits
138
+ result.erase (result.begin (), result.begin () + old_size);
139
+
140
+ // one of the top bits is non-zero
141
+ overflow=prop.lor (result);
142
+ }
143
+ else
144
+ {
145
+ // get top result bits plus sign bit
146
+ DATA_INVARIANT (old_size != 0 , " zero-size operand" );
147
+ result.erase (result.begin (), result.begin () + old_size - 1 );
148
+
149
+ // the sign bit has changed
150
+ literalt sign_change=!prop.lequal (bv0.back (), result.front ());
151
+
152
+ // these need to be either all 1's or all 0's
153
+ literalt all_one=prop.land (result);
154
+ literalt all_zero=!prop.lor (result);
155
+
156
+ overflow=prop.lor (sign_change, !prop.lor (all_one, all_zero));
157
+ }
158
+
159
+ // a negative shift isn't an overflow; else check the conditions built
160
+ // above
161
+ return
162
+ prop.land (!neg_shift, prop.lselect (undef, prop.lor (bv0), overflow));
163
+ }
99
164
else if (expr.id ()==ID_overflow_unary_minus)
100
165
{
101
166
if (operands.size ()!=1 )
0 commit comments