@@ -164,7 +164,7 @@ void update_internal_field(
164164
165165void build_goto_trace (
166166 const symex_target_equationt &target,
167- symex_target_equationt::SSA_stepst::const_iterator end_step ,
167+ ssa_step_predicatet is_last_step_to_keep ,
168168 const prop_convt &prop_conv,
169169 const namespacet &ns,
170170 goto_tracet &goto_trace)
@@ -173,21 +173,28 @@ void build_goto_trace(
173173 // Furthermore, read-events need to occur before write
174174 // events with the same clock.
175175
176- typedef std::map<mp_integer, goto_tracet::stepst> time_mapt;
176+ typedef symex_target_equationt::SSA_stepst::const_iterator ssa_step_iteratort;
177+ typedef std::map<mp_integer, std::vector<ssa_step_iteratort>> time_mapt;
177178 time_mapt time_map;
178179
179180 mp_integer current_time=0 ;
180181
181- const goto_trace_stept *end_ptr= nullptr ;
182- bool end_step_seen= false ;
182+ ssa_step_iteratort last_step_to_keep = target. SSA_steps . end () ;
183+ bool last_step_was_kept = false ;
183184
184- for (symex_target_equationt::SSA_stepst::const_iterator
185- it=target.SSA_steps .begin ();
186- it!=target.SSA_steps .end ();
185+ // First sort the SSA steps by time, in the process dropping steps
186+ // we definitely don't want to retain in the final trace:
187+
188+ for (ssa_step_iteratort it = target.SSA_steps .begin ();
189+ it != target.SSA_steps .end ();
187190 it++)
188191 {
189- if (it==end_step)
190- end_step_seen=true ;
192+ if (
193+ last_step_to_keep == target.SSA_steps .end () &&
194+ is_last_step_to_keep (it, prop_conv))
195+ {
196+ last_step_to_keep = it;
197+ }
191198
192199 const symex_target_equationt::SSA_stept &SSA_step=*it;
193200
@@ -227,12 +234,21 @@ void build_goto_trace(
227234
228235 if (time_before<0 )
229236 {
230- time_mapt::iterator entry=
231- time_map.insert (std::make_pair (
232- current_time,
233- goto_tracet::stepst ())).first ;
234- entry->second .splice (entry->second .end (), time_map[time_before]);
235- time_map.erase (time_before);
237+ time_mapt::const_iterator time_before_steps_it =
238+ time_map.find (time_before);
239+
240+ if (time_before_steps_it != time_map.end ())
241+ {
242+ std::vector<ssa_step_iteratort> ¤t_time_steps =
243+ time_map[current_time];
244+
245+ current_time_steps.insert (
246+ current_time_steps.end (),
247+ time_before_steps_it->second .begin (),
248+ time_before_steps_it->second .end ());
249+
250+ time_map.erase (time_before_steps_it);
251+ }
236252 }
237253
238254 continue ;
@@ -248,97 +264,128 @@ void build_goto_trace(
248264 continue ;
249265 }
250266
251- goto_tracet::stepst &steps=time_map[current_time];
252- steps.push_back (goto_trace_stept ());
253- goto_trace_stept &goto_trace_step=steps.back ();
254- if (!end_step_seen)
255- end_ptr=&goto_trace_step;
256-
257- goto_trace_step.thread_nr =SSA_step.source .thread_nr ;
258- goto_trace_step.pc =SSA_step.source .pc ;
259- goto_trace_step.comment =SSA_step.comment ;
260- if (SSA_step.ssa_lhs .is_not_nil ())
261- goto_trace_step.lhs_object =
262- ssa_exprt (SSA_step.ssa_lhs .get_original_expr ());
263- else
264- goto_trace_step.lhs_object .make_nil ();
265- goto_trace_step.type =SSA_step.type ;
266- goto_trace_step.hidden =SSA_step.hidden ;
267- goto_trace_step.format_string =SSA_step.format_string ;
268- goto_trace_step.io_id =SSA_step.io_id ;
269- goto_trace_step.formatted =SSA_step.formatted ;
270- goto_trace_step.identifier =SSA_step.identifier ;
271-
272- // update internal field for specific variables in the counterexample
273- update_internal_field (SSA_step, goto_trace_step, ns);
274-
275- goto_trace_step.assignment_type =
276- (it->is_assignment ()&&
277- (SSA_step.assignment_type ==
278- symex_targett::assignment_typet::VISIBLE_ACTUAL_PARAMETER ||
279- SSA_step.assignment_type ==
280- symex_targett::assignment_typet::HIDDEN_ACTUAL_PARAMETER))?
281- goto_trace_stept::assignment_typet::ACTUAL_PARAMETER:
282- goto_trace_stept::assignment_typet::STATE;
267+ if (it == last_step_to_keep)
268+ {
269+ last_step_was_kept = true ;
270+ }
283271
284- if (SSA_step.original_full_lhs .is_not_nil ())
285- goto_trace_step.full_lhs =
286- build_full_lhs_rec (
287- prop_conv, ns, SSA_step.original_full_lhs , SSA_step.ssa_full_lhs );
272+ time_map[current_time].push_back (it);
273+ }
288274
289- if (SSA_step.ssa_lhs .is_not_nil ())
290- goto_trace_step.lhs_object_value =prop_conv.get (SSA_step.ssa_lhs );
275+ INVARIANT (
276+ last_step_to_keep == target.SSA_steps .end () || last_step_was_kept,
277+ " last step in SSA trace to keep must not be filtered out as a sync "
278+ " instruction, not-taken branch, PHI node, or similar" );
291279
292- if (SSA_step.ssa_full_lhs .is_not_nil ())
293- {
294- goto_trace_step.full_lhs_value =prop_conv.get (SSA_step.ssa_full_lhs );
295- simplify (goto_trace_step.full_lhs_value , ns);
296- }
280+ // Now build the GOTO trace, ordered by time, then by SSA trace order.
281+
282+ // produce the step numbers
283+ unsigned step_nr = 0 ;
297284
298- for (const auto &j : SSA_step.converted_io_args )
285+ for (const auto &time_and_ssa_steps : time_map)
286+ {
287+ for (const auto ssa_step_it : time_and_ssa_steps.second )
299288 {
300- if (j.is_constant () ||
301- j.id ()==ID_string_constant)
302- goto_trace_step.io_args .push_back (j);
289+ const auto &SSA_step = *ssa_step_it;
290+ goto_trace.steps .push_back (goto_trace_stept ());
291+ goto_trace_stept &goto_trace_step = goto_trace.steps .back ();
292+
293+ goto_trace_step.step_nr = ++step_nr;
294+
295+ goto_trace_step.thread_nr = SSA_step.source .thread_nr ;
296+ goto_trace_step.pc = SSA_step.source .pc ;
297+ goto_trace_step.comment = SSA_step.comment ;
298+ if (SSA_step.ssa_lhs .is_not_nil ())
299+ {
300+ goto_trace_step.lhs_object =
301+ ssa_exprt (SSA_step.ssa_lhs .get_original_expr ());
302+ }
303303 else
304304 {
305- exprt tmp=prop_conv.get (j);
306- goto_trace_step.io_args .push_back (tmp);
305+ goto_trace_step.lhs_object .make_nil ();
306+ }
307+ goto_trace_step.type = SSA_step.type ;
308+ goto_trace_step.hidden = SSA_step.hidden ;
309+ goto_trace_step.format_string = SSA_step.format_string ;
310+ goto_trace_step.io_id = SSA_step.io_id ;
311+ goto_trace_step.formatted = SSA_step.formatted ;
312+ goto_trace_step.identifier = SSA_step.identifier ;
313+
314+ // update internal field for specific variables in the counterexample
315+ update_internal_field (SSA_step, goto_trace_step, ns);
316+
317+ goto_trace_step.assignment_type =
318+ (SSA_step.is_assignment () &&
319+ (SSA_step.assignment_type ==
320+ symex_targett::assignment_typet::VISIBLE_ACTUAL_PARAMETER ||
321+ SSA_step.assignment_type ==
322+ symex_targett::assignment_typet::HIDDEN_ACTUAL_PARAMETER))
323+ ? goto_trace_stept::assignment_typet::ACTUAL_PARAMETER
324+ : goto_trace_stept::assignment_typet::STATE;
325+
326+ if (SSA_step.original_full_lhs .is_not_nil ())
327+ {
328+ goto_trace_step.full_lhs = build_full_lhs_rec (
329+ prop_conv, ns, SSA_step.original_full_lhs , SSA_step.ssa_full_lhs );
307330 }
308- }
309331
310- if (SSA_step.is_assert () ||
311- SSA_step.is_assume () ||
312- SSA_step.is_goto ())
313- {
314- goto_trace_step.cond_expr =SSA_step.cond_expr ;
332+ if (SSA_step.ssa_lhs .is_not_nil ())
333+ goto_trace_step.lhs_object_value = prop_conv.get (SSA_step.ssa_lhs );
334+
335+ if (SSA_step.ssa_full_lhs .is_not_nil ())
336+ {
337+ goto_trace_step.full_lhs_value = prop_conv.get (SSA_step.ssa_full_lhs );
338+ simplify (goto_trace_step.full_lhs_value , ns);
339+ }
340+
341+ for (const auto &j : SSA_step.converted_io_args )
342+ {
343+ if (j.is_constant () || j.id () == ID_string_constant)
344+ {
345+ goto_trace_step.io_args .push_back (j);
346+ }
347+ else
348+ {
349+ exprt tmp = prop_conv.get (j);
350+ goto_trace_step.io_args .push_back (tmp);
351+ }
352+ }
315353
316- goto_trace_step.cond_value =
317- prop_conv.l_get (SSA_step.cond_literal ).is_true ();
354+ if (SSA_step.is_assert () || SSA_step.is_assume () || SSA_step.is_goto ())
355+ {
356+ goto_trace_step.cond_expr = SSA_step.cond_expr ;
357+
358+ goto_trace_step.cond_value =
359+ prop_conv.l_get (SSA_step.cond_literal ).is_true ();
360+ }
361+
362+ if (ssa_step_it == last_step_to_keep)
363+ return ;
318364 }
319365 }
366+ }
320367
321- // Now assemble into a single goto_trace.
322- // This exploits sorted-ness of the map.
323- for (auto &t_it : time_map)
324- goto_trace.steps .splice (goto_trace.steps .end (), t_it.second );
325-
326- // cut off the trace at the desired end
327- for (goto_tracet::stepst::iterator
328- s_it1=goto_trace.steps .begin ();
329- s_it1!=goto_trace.steps .end ();
330- ++s_it1)
331- if (end_step_seen && end_ptr==&(*s_it1))
332- {
333- goto_trace.trim_after (s_it1);
334- break ;
335- }
368+ void build_goto_trace (
369+ const symex_target_equationt &target,
370+ symex_target_equationt::SSA_stepst::const_iterator last_step_to_keep,
371+ const prop_convt &prop_conv,
372+ const namespacet &ns,
373+ goto_tracet &goto_trace)
374+ {
375+ const auto is_last_step_to_keep = [last_step_to_keep](
376+ symex_target_equationt::SSA_stepst::const_iterator it, const prop_convt &) {
377+ return last_step_to_keep == it;
378+ };
336379
337- // produce the step numbers
338- unsigned step_nr=0 ;
380+ return build_goto_trace (
381+ target, is_last_step_to_keep, prop_conv, ns, goto_trace);
382+ }
339383
340- for (auto &s_it : goto_trace.steps )
341- s_it.step_nr =++step_nr;
384+ static bool is_failed_assertion_step (
385+ symex_target_equationt::SSA_stepst::const_iterator step,
386+ const prop_convt &prop_conv)
387+ {
388+ return step->is_assert () && prop_conv.l_get (step->cond_literal ).is_false ();
342389}
343390
344391void build_goto_trace (
@@ -347,17 +394,5 @@ void build_goto_trace(
347394 const namespacet &ns,
348395 goto_tracet &goto_trace)
349396{
350- build_goto_trace (
351- target, target.SSA_steps .end (), prop_conv, ns, goto_trace);
352-
353- // Now delete anything after first failed assertion
354- for (goto_tracet::stepst::iterator
355- s_it1=goto_trace.steps .begin ();
356- s_it1!=goto_trace.steps .end ();
357- s_it1++)
358- if (s_it1->is_assert () && !s_it1->cond_value )
359- {
360- goto_trace.trim_after (s_it1);
361- break ;
362- }
397+ build_goto_trace (target, is_failed_assertion_step, prop_conv, ns, goto_trace);
363398}
0 commit comments