@@ -173,17 +173,20 @@ void build_goto_trace(
173
173
// Furthermore, read-events need to occur before write
174
174
// events with the same clock.
175
175
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;
177
178
time_mapt time_map;
178
179
179
180
mp_integer current_time=0 ;
180
181
181
- const goto_trace_stept *end_ptr=nullptr ;
182
182
bool end_step_seen=false ;
183
+ ssa_step_iteratort last_step_in_goto_trace = target.SSA_steps .end ();
183
184
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 ();
187
190
it++)
188
191
{
189
192
if (it==end_step)
@@ -227,12 +230,21 @@ void build_goto_trace(
227
230
228
231
if (time_before<0 )
229
232
{
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
+ }
236
248
}
237
249
238
250
continue ;
@@ -248,97 +260,94 @@ void build_goto_trace(
248
260
continue ;
249
261
}
250
262
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);
283
264
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
+ }
288
268
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.
291
270
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 ;
297
273
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 )
299
277
{
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 ());
303
290
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 ())
304
320
{
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 );
307
323
}
308
- }
309
324
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
+ }
315
336
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 ;
320
342
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
+ }
325
346
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 ;
335
349
}
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
+ }
342
351
}
343
352
344
353
void build_goto_trace (
0 commit comments