@@ -155,6 +155,13 @@ void goto_symext::symex_goto(statet &state)
155
155
state_pc=goto_target;
156
156
}
157
157
158
+ // Before any storing or splitting we need to copy the current state of
159
+ // level 2 names, as no matter which symex strategy we use .
160
+ symex_level2t::current_namest names = *state.level2 .current_names ;
161
+ state.level2 .local_generations = state.level2 .local_generations
162
+ ? *state.level2 .local_generations
163
+ : names;
164
+
158
165
// Normally the next instruction to execute would be state_pc and we save
159
166
// new_state_pc for later. But if we're executing from a saved state, then
160
167
// new_state_pc should be the state that we saved from earlier, so let's
@@ -201,6 +208,13 @@ void goto_symext::symex_goto(statet &state)
201
208
// pointing to; this needs to be inverted for the branch that we're saving,
202
209
// so let its truth value for `backwards` be the same as ours for `forward`.
203
210
211
+ jump_target.state .level2 .current_names = new symex_level2t::current_namest (
212
+ *jump_target.state .level2 .current_names );
213
+
214
+ jump_target.state .level2 .local_generations =
215
+ state.level2 .local_generations ? *state.level2 .local_generations
216
+ : *jump_target.state .level2 .current_names ;
217
+
204
218
log.debug () << " Saving next instruction '"
205
219
<< next_instruction.state .saved_target ->source_location << " '"
206
220
<< log.eom ;
@@ -221,7 +235,14 @@ void goto_symext::symex_goto(statet &state)
221
235
framet::goto_state_listt &goto_state_list =
222
236
state.top ().goto_state_map [new_state_pc];
223
237
224
- goto_state_list.emplace_back (state);
238
+ if (new_guard.is_true ())
239
+ {
240
+ goto_state_list.push_back (std::move (state));
241
+ }
242
+ else
243
+ {
244
+ goto_state_list.push_back (statet::goto_statet (state));
245
+ }
225
246
226
247
symex_transition (state, state_pc, backward);
227
248
@@ -472,6 +493,14 @@ static void merge_names(
472
493
// initialized and therefore an invalid target.
473
494
474
495
// These rules only apply to dynamic objects and locals.
496
+ INVARIANT (
497
+ !dest_state.guard .is_false (),
498
+ " if the destination state is currently unreachable we shouldn't be doing "
499
+ " a per-name merge" );
500
+ INVARIANT (
501
+ !goto_state.guard .is_false (),
502
+ " an unreachable state should never have been queued for merging" );
503
+
475
504
if (dest_state.guard .is_false ())
476
505
rhs = goto_state_rhs;
477
506
else if (goto_state.guard .is_false ())
@@ -515,21 +544,29 @@ static void merge_names(
515
544
}
516
545
517
546
void goto_symext::phi_function (
518
- const goto_statet &goto_state,
547
+ statet:: goto_statet &goto_state,
519
548
statet &dest_state)
520
549
{
550
+ // If our destination is unreachable just replace with the incoming state.
551
+ if (dest_state.guard .is_false ())
552
+ {
553
+ dest_state.level2 .local_generations = std::move (goto_state.level2 .local_generations );
554
+ dest_state.propagation = std::move (goto_state.propagation );
555
+ return ;
556
+ }
557
+
521
558
if (
522
- goto_state.level2 .current_names .empty () &&
523
- dest_state.level2 .current_names .empty ())
559
+ goto_state.level2 .get_current_names () .empty () &&
560
+ dest_state.level2 .get_current_names () .empty ())
524
561
return ;
525
562
526
563
guardt diff_guard = goto_state.guard ;
527
564
// this gets the diff between the guards
528
565
diff_guard -= dest_state.guard ;
529
566
530
567
for_each2 (
531
- goto_state.level2 .current_names ,
532
- dest_state.level2 .current_names ,
568
+ goto_state.level2 .get_current_names () ,
569
+ dest_state.level2 .get_current_names () ,
533
570
[&](const ssa_exprt &ssa, unsigned goto_count, unsigned dest_count) {
534
571
merge_names (
535
572
goto_state,
0 commit comments