@@ -32,6 +32,7 @@ dfcc_instrument_loopt::dfcc_instrument_loopt(
32
32
dfcc_spec_functionst &spec_functions,
33
33
dfcc_contract_clauses_codegent &contract_clauses_codegen)
34
34
: goto_model(goto_model),
35
+ message_handler(message_handler),
35
36
log(message_handler),
36
37
utils(utils),
37
38
library(library),
@@ -94,7 +95,7 @@ void dfcc_instrument_loopt::operator()(
94
95
.symbol_expr ();
95
96
96
97
// Temporary variables for storing the multidimensional decreases clause
97
- // at the start of and end of a loop body.
98
+ // at the start of and end of a loop body
98
99
exprt::operandst decreases_clauses = loop.decreases ;
99
100
std::vector<symbol_exprt> old_decreases_vars, new_decreases_vars;
100
101
for (const auto &clause : decreases_clauses)
@@ -121,10 +122,10 @@ void dfcc_instrument_loopt::operator()(
121
122
new_decreases_vars.push_back (new_decreases_var);
122
123
}
123
124
124
- // Convert the assigns clause to the required type.
125
+ // convert the assigns clause to the required type
125
126
exprt::operandst assigns (loop.assigns .begin (), loop.assigns .end ());
126
127
127
- // Add local statics to the assigns clause.
128
+ // add local statics to the assigns clause
128
129
for (auto &local_static : local_statics)
129
130
{
130
131
assigns.push_back (local_static);
@@ -146,24 +147,26 @@ void dfcc_instrument_loopt::operator()(
146
147
contract_clauses_codegen.gen_spec_assigns_instructions (
147
148
language_mode, assigns, assigns_instrs);
148
149
150
+ const symbol_exprt &addr_of_loop_write_set = loop.addr_of_write_set_var ;
149
151
spec_functions.generate_havoc_instructions (
150
152
function_id,
151
153
language_mode,
152
154
symbol_table.get_writeable_ref (function_id).module ,
153
155
assigns_instrs,
154
- loop. addr_of_write_set_var ,
156
+ addr_of_loop_write_set ,
155
157
havoc_instrs,
156
158
nof_targets);
157
159
spec_functions.to_spec_assigns_instructions (
158
- loop. addr_of_write_set_var , language_mode, assigns_instrs, nof_targets);
160
+ addr_of_loop_write_set , language_mode, assigns_instrs, nof_targets);
159
161
write_set_populate_instrs.copy_from (assigns_instrs);
160
162
161
- // Replace bound variables by fresh instances in quantified formulas.
163
+ // replace bound variables by fresh instances in quantified formulas
162
164
exprt invariant = loop.invariant ;
163
165
if (has_subexpr (invariant, ID_exists) || has_subexpr (invariant, ID_forall))
164
166
add_quantified_variable (symbol_table, invariant, language_mode);
165
167
166
168
// ---------- Add instrumented instructions ----------
169
+ const symbol_exprt &loop_write_set = loop.write_set_var ;
167
170
goto_programt::targett loop_latch =
168
171
loop.find_latch (goto_function.body ).value ();
169
172
@@ -176,8 +179,8 @@ void dfcc_instrument_loopt::operator()(
176
179
write_set_populate_instrs,
177
180
invariant,
178
181
assigns,
179
- loop. write_set_var ,
180
- loop. addr_of_write_set_var ,
182
+ loop_write_set ,
183
+ addr_of_loop_write_set ,
181
184
entered_loop,
182
185
initial_invariant,
183
186
in_base_case,
@@ -194,7 +197,7 @@ void dfcc_instrument_loopt::operator()(
194
197
havoc_instrs,
195
198
invariant,
196
199
decreases_clauses,
197
- loop. addr_of_write_set_var ,
200
+ addr_of_loop_write_set ,
198
201
outer_write_set,
199
202
initial_invariant,
200
203
in_base_case,
@@ -222,8 +225,9 @@ void dfcc_instrument_loopt::operator()(
222
225
cbmc_loop_id,
223
226
goto_function,
224
227
head,
225
- loop.write_set_var ,
226
- loop.addr_of_write_set_var ,
228
+ decreases_clauses,
229
+ loop_write_set,
230
+ addr_of_loop_write_set,
227
231
history_var_map,
228
232
entered_loop,
229
233
initial_invariant,
@@ -252,6 +256,7 @@ std::map<exprt, exprt> dfcc_instrument_loopt::add_prehead_instructions(
252
256
{
253
257
auto loop_head_location (loop_head->source_location ());
254
258
dfcc_remove_loop_tags (loop_head_location);
259
+ goto_convertt converter (symbol_table, message_handler);
255
260
256
261
// ```
257
262
// ... preamble ...
@@ -322,7 +327,7 @@ std::map<exprt, exprt> dfcc_instrument_loopt::add_prehead_instructions(
322
327
}
323
328
324
329
{
325
- // Create and populate the write set.
330
+ // create and populate the write set
326
331
// DECL loop_write_set
327
332
// DECL addr_of_loop_write_set
328
333
// ASSIGN write_set_ptr := address_of(write_set)
@@ -378,6 +383,7 @@ dfcc_instrument_loopt::add_step_instructions(
378
383
{
379
384
auto loop_head_location (loop_head->source_location ());
380
385
dfcc_remove_loop_tags (loop_head_location);
386
+ goto_convertt converter (symbol_table, message_handler);
381
387
382
388
// ```
383
389
// STEP: // Loop step block: havoc the loop state
@@ -402,20 +408,21 @@ dfcc_instrument_loopt::add_step_instructions(
402
408
403
409
{
404
410
// If we jump here, then the loop runs at least once,
405
- // so add the base case assertion: `assert(initial_invariant)`.
411
+ // so add the base case assertion: `assert(initial_invariant)`
406
412
source_locationt check_location (loop_head_location);
407
413
check_location.set_property_class (" loop_invariant_base" );
408
414
check_location.set_comment (
409
415
" Check invariant before entry for loop " +
410
416
id2string (check_location.get_function ()) + " ." +
411
417
std::to_string (cbmc_loop_id));
412
- step_instrs.add (
413
- goto_programt::make_assertion (initial_invariant, check_location));
418
+ code_assertt assertion{initial_invariant};
419
+ assertion.add_source_location () = check_location;
420
+ converter.goto_convert (assertion, step_instrs, language_mode);
414
421
}
415
422
416
423
{
417
- // Check assigns clause inclusion with parent write set
418
- // skip the check when if w_parent is NULL.
424
+ // check assigns clause inclusion with parent write set
425
+ // skip the check when if w_parent is NULL
419
426
auto goto_instruction = step_instrs.add (goto_programt::make_incomplete_goto (
420
427
equal_exprt (
421
428
outer_write_set,
@@ -472,17 +479,16 @@ dfcc_instrument_loopt::add_step_instructions(
472
479
goto_programt::make_assignment (in_loop_havoc_block, false_exprt{}));
473
480
}
474
481
475
- goto_convertt converter (symbol_table, log .get_message_handler ());
476
482
{
477
- // Assume the loop invariant after havocing the state.
483
+ // Assume the loop invariant after havocing the state
478
484
code_assumet assumption{invariant};
479
485
assumption.add_source_location () = loop_head_location;
480
486
converter.goto_convert (assumption, step_instrs, language_mode);
481
487
}
482
488
483
489
{
484
490
// Generate assignments to store the multidimensional decreases clause's
485
- // value just before the loop_head.
491
+ // value just before the loop_head
486
492
for (size_t i = 0 ; i < old_decreases_vars.size (); i++)
487
493
{
488
494
code_frontend_assignt old_decreases_assignment{
@@ -515,6 +521,7 @@ void dfcc_instrument_loopt::add_body_instructions(
515
521
{
516
522
auto loop_head_location (loop_head->source_location ());
517
523
dfcc_remove_loop_tags (loop_head_location);
524
+ goto_convertt converter (symbol_table, message_handler);
518
525
519
526
// HEAD: // Loop body block
520
527
// ... eval guard ...
@@ -532,7 +539,7 @@ void dfcc_instrument_loopt::add_body_instructions(
532
539
goto_programt pre_loop_latch_instrs;
533
540
534
541
{
535
- // Record that we entered the loop with `entered_loop = true`.
542
+ // Record that we entered the loop with `entered_loop = true`
536
543
pre_loop_latch_instrs.add (
537
544
goto_programt::make_assignment (entered_loop, true_exprt{}));
538
545
}
@@ -544,7 +551,6 @@ void dfcc_instrument_loopt::add_body_instructions(
544
551
step_case_target, in_base_case, loop_head_location));
545
552
}
546
553
547
- goto_convertt converter (symbol_table, log .get_message_handler ());
548
554
{
549
555
// Because of the unconditional jump above the following code is only
550
556
// reachable in the step case. Generate the inductive invariant check
@@ -562,7 +568,7 @@ void dfcc_instrument_loopt::add_body_instructions(
562
568
563
569
{
564
570
// Generate assignments to store the multidimensional decreases clause's
565
- // value after one iteration of the loop.
571
+ // value after one iteration of the loop
566
572
if (!decreases_clauses.empty ())
567
573
{
568
574
for (size_t i = 0 ; i < new_decreases_vars.size (); i++)
@@ -581,12 +587,14 @@ void dfcc_instrument_loopt::add_body_instructions(
581
587
" Check variant decreases after step for loop " +
582
588
id2string (check_location.get_function ()) + " ." +
583
589
std::to_string (cbmc_loop_id));
584
- pre_loop_latch_instrs. add ( goto_programt::make_assertion (
590
+ code_assertt monotonic_decreasing_assertion{
585
591
generate_lexicographic_less_than_check (
586
- new_decreases_vars, old_decreases_vars),
587
- check_location));
592
+ new_decreases_vars, old_decreases_vars)};
593
+ monotonic_decreasing_assertion.add_source_location () = check_location;
594
+ converter.goto_convert (
595
+ monotonic_decreasing_assertion, pre_loop_latch_instrs, language_mode);
588
596
589
- // Discard the temporary variables that store decreases clause's value.
597
+ // Discard the temporary variables that store decreases clause's value
590
598
for (size_t i = 0 ; i < old_decreases_vars.size (); i++)
591
599
{
592
600
pre_loop_latch_instrs.add (
@@ -601,7 +609,7 @@ void dfcc_instrument_loopt::add_body_instructions(
601
609
goto_function.body , loop_latch, pre_loop_latch_instrs);
602
610
603
611
{
604
- // Change the back edge into assume(false) or assume(!guard).
612
+ // change the back edge into assume(false) or assume(!guard)
605
613
loop_latch->turn_into_assume ();
606
614
loop_latch->condition_nonconst () = boolean_negate (loop_latch->condition ());
607
615
}
@@ -612,6 +620,7 @@ void dfcc_instrument_loopt::add_exit_instructions(
612
620
const std::size_t cbmc_loop_id,
613
621
goto_functionst::goto_functiont &goto_function,
614
622
goto_programt::targett loop_head,
623
+ const exprt::operandst &decreases_clauses,
615
624
const symbol_exprt &loop_write_set,
616
625
const symbol_exprt &addr_of_loop_write_set,
617
626
const std::map<exprt, exprt> &history_var_map,
@@ -621,7 +630,7 @@ void dfcc_instrument_loopt::add_exit_instructions(
621
630
const std::vector<symbol_exprt> &old_decreases_vars,
622
631
const std::vector<symbol_exprt> &new_decreases_vars)
623
632
{
624
- // Collect all exit targets of the loop.
633
+ // collect all exit targets of the loop
625
634
std::set<goto_programt::targett> exit_targets;
626
635
627
636
for (goto_programt::instructiont::targett target =
@@ -640,7 +649,7 @@ void dfcc_instrument_loopt::add_exit_instructions(
640
649
exit_targets.insert (exit_target);
641
650
}
642
651
643
- // For each exit target of the loop, insert a code block:
652
+ // For each exit target of the loop, insert a code block :
644
653
// ```
645
654
// EXIT:
646
655
// // check that step case was checked if loop can run once
@@ -656,8 +665,8 @@ void dfcc_instrument_loopt::add_exit_instructions(
656
665
{
657
666
goto_programt loop_exit_program;
658
667
659
- // Use the head location for this check as well so that all checks related
660
- // to a given loop are presented as coming from the loop head.
668
+ // use the head location for this check as well so that all checks related
669
+ // to a given loop are presented as coming from the loop head
661
670
source_locationt check_location = loop_head->source_location ();
662
671
check_location.set_property_class (" loop_step_unwinding" );
663
672
check_location.set_comment (
@@ -677,31 +686,34 @@ void dfcc_instrument_loopt::add_exit_instructions(
677
686
loop_exit_program.add (
678
687
goto_programt::make_dead (initial_invariant, exit_location));
679
688
680
- // Release the write set resources.
689
+ // Release the write set resources
681
690
loop_exit_program.add (goto_programt::make_function_call (
682
691
library.write_set_release_call (addr_of_loop_write_set, exit_location),
683
692
exit_location));
684
693
685
- // Mark write set as going out of scope.
694
+ // Kill write set
686
695
loop_exit_program.add (
687
696
goto_programt::make_dead (to_symbol_expr (loop_write_set), exit_location));
688
697
loop_exit_program.add (goto_programt::make_dead (
689
698
to_symbol_expr (addr_of_loop_write_set), exit_location));
690
699
691
- // Mark history variables as going out of scope.
700
+ // Kill history variables
692
701
for (const auto &v : history_var_map)
693
702
{
694
703
loop_exit_program.add (
695
704
goto_programt::make_dead (to_symbol_expr (v.second ), exit_location));
696
705
}
697
706
698
- // Mark decreases clause snapshots as gong out of scope.
699
- for (size_t i = 0 ; i < old_decreases_vars.size (); i++)
707
+ if (!decreases_clauses.empty ())
700
708
{
701
- loop_exit_program.add (
702
- goto_programt::make_dead (old_decreases_vars[i], exit_location));
703
- loop_exit_program.add (
704
- goto_programt::make_dead (new_decreases_vars[i], exit_location));
709
+ // Kill decreases clause snapshots
710
+ for (size_t i = 0 ; i < old_decreases_vars.size (); i++)
711
+ {
712
+ loop_exit_program.add (
713
+ goto_programt::make_dead (old_decreases_vars[i], exit_location));
714
+ loop_exit_program.add (
715
+ goto_programt::make_dead (new_decreases_vars[i], exit_location));
716
+ }
705
717
}
706
718
707
719
// Insert the exit block, preserving the loop end target.
0 commit comments