@@ -411,6 +411,29 @@ exprt smt2_incremental_decision_proceduret::get_expr(
411
411
get_value_response->pairs ()[0 ].get ().value (), type);
412
412
}
413
413
414
+ // This is a fall back which builds resulting expression based on getting the
415
+ // values of its operands. It is used during trace building in the case where
416
+ // certain kinds of expression appear on the left hand side of an
417
+ // assignment. For example in the following trace assignment -
418
+ // `byte_extract_little_endian(x, offset) = 1`
419
+ // `::get` will be called on `byte_extract_little_endian(x, offset)` and
420
+ // we build a resulting expression where `x` and `offset` are substituted
421
+ // with their values.
422
+ static exprt build_expr_based_on_getting_operands (
423
+ const exprt &expr,
424
+ const stack_decision_proceduret &decision_procedure)
425
+ {
426
+ exprt copy = expr;
427
+ for (auto &op : copy.operands ())
428
+ {
429
+ exprt eval_op = decision_procedure.get (op);
430
+ if (eval_op.is_nil ())
431
+ return nil_exprt{};
432
+ op = std::move (eval_op);
433
+ }
434
+ return copy;
435
+ }
436
+
414
437
exprt smt2_incremental_decision_proceduret::get (const exprt &expr) const
415
438
{
416
439
log .conditional_output (log .debug (), [&](messaget::mstreamt &debug) {
@@ -431,29 +454,31 @@ exprt smt2_incremental_decision_proceduret::get(const exprt &expr) const
431
454
return {};
432
455
return smt_array_theoryt::select (*array, *index );
433
456
}
434
- return get_identifier (
435
- expr, expression_handle_identifiers, expression_identifiers);
436
- }();
437
- if (!descriptor)
438
- {
457
+ if (
458
+ auto identifier_descriptor = get_identifier (
459
+ expr, expression_handle_identifiers, expression_identifiers))
460
+ {
461
+ return identifier_descriptor;
462
+ }
439
463
if (gather_dependent_expressions (expr).empty ())
440
464
{
441
465
INVARIANT (
442
466
objects_are_already_tracked (expr, object_map),
443
467
" Objects in expressions being read should already be tracked from "
444
468
" point of being set/handled." );
445
- descriptor = ::convert_expr_to_smt (
469
+ return ::convert_expr_to_smt (
446
470
expr,
447
471
object_map,
448
472
pointer_sizes_map,
449
473
object_size_function.make_application ,
450
474
is_dynamic_object_function.make_application );
451
475
}
452
- else
476
+ return {};
477
+ }();
478
+ if (!descriptor)
479
+ {
480
+ if (const auto symbol_expr = expr_try_dynamic_cast<symbol_exprt>(expr))
453
481
{
454
- const auto symbol_expr = expr_try_dynamic_cast<symbol_exprt>(expr);
455
- INVARIANT (
456
- symbol_expr, " Unhandled expressions are expected to be symbols" );
457
482
// Note this case is currently expected to be encountered during trace
458
483
// generation for -
459
484
// * Steps which were removed via --slice-formula.
@@ -466,6 +491,7 @@ exprt smt2_incremental_decision_proceduret::get(const exprt &expr) const
466
491
<< symbol_expr->get_identifier () << messaget::eom;
467
492
return expr;
468
493
}
494
+ return build_expr_based_on_getting_operands (expr, *this );
469
495
}
470
496
if (const auto array_type = type_try_dynamic_cast<array_typet>(expr.type ()))
471
497
{
0 commit comments