@@ -5,6 +5,7 @@ Author: Qinheping Hu
5
5
6
6
#include " expr_enumerator.h"
7
7
8
+ #include < util/bitvector_types.h>
8
9
#include < util/format_expr.h>
9
10
#include < util/simplify_expr.h>
10
11
#include < util/std_expr.h>
@@ -310,70 +311,95 @@ bool binary_functional_enumeratort::is_equivalence_class_representation(
310
311
return true ;
311
312
}
312
313
313
- exprt binary_functional_enumeratort::instantiate (const expr_listt &exprs) const
314
+ // Handle mix of unsigned and signed leafs in one expression.
315
+ // From the C99 standard, section 6.3.1.8:
316
+ // "if the operand that has unsigned integer type has rank greater or equal to
317
+ // the rank of the type of the other operand, then the operand with signed
318
+ // integer type is converted to the type of the operand with unsigned integer
319
+ // type."
320
+ static std::pair<const exprt, const exprt>
321
+ widen_bitvector (const exprt &lhs, const exprt &rhs)
314
322
{
315
- INVARIANT (
316
- exprs.size () == 2 ,
317
- " number of arguments should be 2: " + integer2string (exprs.size ()));
318
- if (op_id == ID_equal)
323
+ // Widening conversion.
324
+ if (
325
+ lhs.type () != rhs.type () &&
326
+ (lhs.type ().id () == ID_unsignedbv || lhs.type ().id () == ID_signedbv) &&
327
+ (rhs.type ().id () == ID_unsignedbv || rhs.type ().id () == ID_signedbv))
319
328
{
320
- auto &lhs = exprs.front ();
321
- auto &rhs = exprs.back ();
322
-
323
- // Widening conversion.
324
- if (
325
- lhs.type () != rhs.type () &&
326
- (lhs.type ().id () == ID_unsignedbv || lhs.type ().id () == ID_signedbv) &&
327
- (rhs.type ().id () == ID_unsignedbv || rhs.type ().id () == ID_signedbv))
329
+ const auto &lhs_type = type_try_dynamic_cast<bitvector_typet>(lhs.type ());
330
+ const auto &rhs_type = type_try_dynamic_cast<bitvector_typet>(rhs.type ());
331
+
332
+ // Same rank, unsigned win.
333
+ if (lhs_type->get_width () == rhs_type->get_width ())
328
334
{
329
- const auto &lhs_type = type_try_dynamic_cast<bitvector_typet>(lhs.type ());
330
- const auto &rhs_type = type_try_dynamic_cast<bitvector_typet>(rhs.type ());
331
- if (lhs_type->get_width () >= rhs_type->get_width ())
332
- return equal_exprt (lhs, typecast_exprt (rhs, lhs.type ()));
335
+ if ((lhs.type ().id () == ID_unsignedbv || rhs.type ().id () == ID_unsignedbv))
336
+ {
337
+ return std::pair<const exprt, const exprt>(
338
+ typecast_exprt::conditional_cast (
339
+ lhs, unsignedbv_typet (lhs_type->get_width ())),
340
+ typecast_exprt::conditional_cast (
341
+ rhs, unsignedbv_typet (lhs_type->get_width ())));
342
+ }
333
343
else
334
- return equal_exprt (typecast_exprt (lhs, rhs.type ()), rhs);
344
+ {
345
+ return std::pair<const exprt, const exprt>(
346
+ typecast_exprt::conditional_cast (
347
+ lhs, signedbv_typet (lhs_type->get_width ())),
348
+ typecast_exprt::conditional_cast (
349
+ rhs, signedbv_typet (lhs_type->get_width ())));
350
+ }
335
351
}
336
352
337
- return equal_exprt (exprs.front (), exprs.back ());
338
- }
339
- if (op_id == ID_notequal)
340
- {
341
- auto &lhs = exprs.front ();
342
- auto &rhs = exprs.back ();
343
-
344
- // Widening conversion.
345
- if (
346
- lhs.type () != rhs.type () &&
347
- (lhs.type ().id () == ID_unsignedbv || lhs.type ().id () == ID_signedbv) &&
348
- (rhs.type ().id () == ID_unsignedbv || rhs.type ().id () == ID_signedbv))
353
+ // Different rank, higher rank win.
354
+ if (lhs_type->get_width () > rhs_type->get_width ())
349
355
{
350
- const auto &lhs_type = type_try_dynamic_cast<bitvector_typet>(lhs.type ());
351
- const auto &rhs_type = type_try_dynamic_cast<bitvector_typet>(rhs.type ());
352
- if (lhs_type->get_width () >= rhs_type->get_width ())
353
- return notequal_exprt (lhs, typecast_exprt (rhs, lhs.type ()));
354
- else
355
- return notequal_exprt (typecast_exprt (lhs, rhs.type ()), rhs);
356
+ return std::pair<const exprt, const exprt>(
357
+ lhs, typecast_exprt::conditional_cast (rhs, *lhs_type));
356
358
}
357
-
358
- return notequal_exprt (exprs.front (), exprs.back ());
359
+ else
360
+ {
361
+ return std::pair<const exprt, const exprt>(
362
+ typecast_exprt::conditional_cast (lhs, *rhs_type), rhs);
363
+ }
364
+ }
365
+ // no need of bitvector conversion.
366
+ else
367
+ {
368
+ return std::pair<const exprt, const exprt>(lhs, rhs);
359
369
}
370
+ }
371
+
372
+ exprt binary_functional_enumeratort::instantiate (const expr_listt &exprs) const
373
+ {
374
+ INVARIANT (
375
+ exprs.size () == 2 ,
376
+ " number of arguments should be 2: " + integer2string (exprs.size ()));
377
+
378
+ // Make two operands the same type if they are of different bitvector types.
379
+ auto operands = widen_bitvector (exprs.front (), exprs.back ());
380
+
381
+ if (op_id == ID_equal)
382
+ return equal_exprt (operands.first , operands.second );
383
+ if (op_id == ID_notequal)
384
+ return notequal_exprt (operands.first , operands.second );
360
385
if (op_id == ID_le)
361
- return less_than_or_equal_exprt (exprs. front (), exprs. back () );
386
+ return less_than_or_equal_exprt (operands. first , operands. second );
362
387
if (op_id == ID_lt)
363
- return less_than_exprt (exprs. front (), exprs. back () );
388
+ return less_than_exprt (operands. first , operands. second );
364
389
if (op_id == ID_gt)
365
- return greater_than_exprt (exprs. front (), exprs. back () );
390
+ return greater_than_exprt (operands. first , operands. second );
366
391
if (op_id == ID_ge)
367
- return greater_than_or_equal_exprt (exprs. front (), exprs. back () );
392
+ return greater_than_or_equal_exprt (operands. first , operands. second );
368
393
if (op_id == ID_and)
369
394
return and_exprt (exprs.front (), exprs.back ());
370
395
if (op_id == ID_or)
371
396
return or_exprt (exprs.front (), exprs.back ());
372
397
if (op_id == ID_plus)
373
- return plus_exprt (exprs. front (), exprs. back () );
398
+ return plus_exprt (operands. first , operands. second );
374
399
if (op_id == ID_minus)
375
- return minus_exprt (exprs.front (), exprs.back ());
376
- return binary_exprt (exprs.front (), op_id, exprs.back ());
400
+ return minus_exprt (operands.first , operands.second );
401
+
402
+ return binary_exprt (operands.first , op_id, operands.second );
377
403
}
378
404
379
405
expr_sett alternatives_enumeratort::enumerate (const std::size_t size) const
0 commit comments