@@ -173,17 +173,20 @@ 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 ;
182182 bool end_step_seen=false ;
183+ ssa_step_iteratort last_step_in_goto_trace = target.SSA_steps .end ();
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 {
189192 if (it==end_step)
@@ -227,12 +230,21 @@ void build_goto_trace(
227230
228231 if (time_before<0 )
229232 {
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);
233+ time_mapt::const_iterator time_before_steps_it =
234+ time_map.find (time_before);
235+
236+ if (time_before_steps_it != time_map.end ())
237+ {
238+ std::vector<ssa_step_iteratort> ¤t_time_steps =
239+ time_map[current_time];
240+
241+ current_time_steps.insert (
242+ current_time_steps.end (),
243+ time_before_steps_it->second .begin (),
244+ time_before_steps_it->second .end ());
245+
246+ time_map.erase (time_before_steps_it);
247+ }
236248 }
237249
238250 continue ;
@@ -248,97 +260,94 @@ void build_goto_trace(
248260 continue ;
249261 }
250262
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;
263+ time_map[current_time].push_back (it);
283264
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 );
265+ if (!end_step_seen)
266+ last_step_in_goto_trace = it;
267+ }
288268
289- if (SSA_step.ssa_lhs .is_not_nil ())
290- goto_trace_step.lhs_object_value =prop_conv.get (SSA_step.ssa_lhs );
269+ // Now build the GOTO trace, ordered by time, then by SSA trace order.
291270
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- }
271+ // produce the step numbers
272+ unsigned step_nr=0 ;
297273
298- for (const auto &j : SSA_step.converted_io_args )
274+ for (const auto &time_and_ssa_steps : time_map)
275+ {
276+ for (const auto ssa_step_it : time_and_ssa_steps.second )
299277 {
300- if (j.is_constant () ||
301- j.id ()==ID_string_constant)
302- goto_trace_step.io_args .push_back (j);
278+ const auto &SSA_step = *ssa_step_it;
279+ goto_trace.steps .push_back (goto_trace_stept ());
280+ goto_trace_stept &goto_trace_step = goto_trace.steps .back ();
281+
282+ goto_trace_step.step_nr = ++step_nr;
283+
284+ goto_trace_step.thread_nr =SSA_step.source .thread_nr ;
285+ goto_trace_step.pc =SSA_step.source .pc ;
286+ goto_trace_step.comment =SSA_step.comment ;
287+ if (SSA_step.ssa_lhs .is_not_nil ())
288+ goto_trace_step.lhs_object =
289+ ssa_exprt (SSA_step.ssa_lhs .get_original_expr ());
303290 else
291+ goto_trace_step.lhs_object .make_nil ();
292+ goto_trace_step.type =SSA_step.type ;
293+ goto_trace_step.hidden =SSA_step.hidden ;
294+ goto_trace_step.format_string =SSA_step.format_string ;
295+ goto_trace_step.io_id =SSA_step.io_id ;
296+ goto_trace_step.formatted =SSA_step.formatted ;
297+ goto_trace_step.identifier =SSA_step.identifier ;
298+
299+ // update internal field for specific variables in the counterexample
300+ update_internal_field (SSA_step, goto_trace_step, ns);
301+
302+ goto_trace_step.assignment_type =
303+ (SSA_step.is_assignment () &&
304+ (SSA_step.assignment_type ==
305+ symex_targett::assignment_typet::VISIBLE_ACTUAL_PARAMETER ||
306+ SSA_step.assignment_type ==
307+ symex_targett::assignment_typet::HIDDEN_ACTUAL_PARAMETER))?
308+ goto_trace_stept::assignment_typet::ACTUAL_PARAMETER:
309+ goto_trace_stept::assignment_typet::STATE;
310+
311+ if (SSA_step.original_full_lhs .is_not_nil ())
312+ goto_trace_step.full_lhs =
313+ build_full_lhs_rec (
314+ prop_conv, ns, SSA_step.original_full_lhs , SSA_step.ssa_full_lhs );
315+
316+ if (SSA_step.ssa_lhs .is_not_nil ())
317+ goto_trace_step.lhs_object_value =prop_conv.get (SSA_step.ssa_lhs );
318+
319+ if (SSA_step.ssa_full_lhs .is_not_nil ())
304320 {
305- exprt tmp =prop_conv.get (j );
306- goto_trace_step.io_args . push_back (tmp );
321+ goto_trace_step. full_lhs_value =prop_conv.get (SSA_step. ssa_full_lhs );
322+ simplify ( goto_trace_step.full_lhs_value , ns );
307323 }
308- }
309324
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 ;
325+ for (const auto &j : SSA_step.converted_io_args )
326+ {
327+ if (j.is_constant () ||
328+ j.id ()==ID_string_constant)
329+ goto_trace_step.io_args .push_back (j);
330+ else
331+ {
332+ exprt tmp=prop_conv.get (j);
333+ goto_trace_step.io_args .push_back (tmp);
334+ }
335+ }
315336
316- goto_trace_step.cond_value =
317- prop_conv.l_get (SSA_step.cond_literal ).is_true ();
318- }
319- }
337+ if (SSA_step.is_assert () ||
338+ SSA_step.is_assume () ||
339+ SSA_step.is_goto ())
340+ {
341+ goto_trace_step.cond_expr =SSA_step.cond_expr ;
320342
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 );
343+ goto_trace_step.cond_value =
344+ prop_conv.l_get (SSA_step.cond_literal ).is_true ();
345+ }
325346
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 ;
347+ if (ssa_step_it == last_step_in_goto_trace)
348+ return ;
335349 }
336-
337- // produce the step numbers
338- unsigned step_nr=0 ;
339-
340- for (auto &s_it : goto_trace.steps )
341- s_it.step_nr =++step_nr;
350+ }
342351}
343352
344353void build_goto_trace (
0 commit comments