@@ -103,13 +103,14 @@ struct build_declaration_hops_inputst
103
103
node_indext end_scope_index = 0 ;
104
104
};
105
105
106
- void goto_convertt::build_declaration_hops (
106
+ goto_convertt::declaration_hop_instrumentationt
107
+ goto_convertt::build_declaration_hops (
107
108
goto_programt &program,
108
109
std::unordered_map<irep_idt, symbolt, irep_id_hash> &label_flags,
109
110
const build_declaration_hops_inputst &inputs)
110
111
{
111
112
// In the case of a goto jumping into a scope, the declarations (but not the
112
- // initialisations) need to be executed. This function performs a
113
+ // initialisations) need to be executed. This function prepares a
113
114
// transformation from code that looks like -
114
115
// {
115
116
// statement_block_a();
@@ -150,9 +151,14 @@ void goto_convertt::build_declaration_hops(
150
151
// __CPROVER_going_to::user_label = false;
151
152
// statement_block_e();
152
153
// }
154
+ //
155
+ // The actual insertion of instructions needs to be performed by the caller,
156
+ // which needs to use the result of this method.
153
157
154
158
PRECONDITION (inputs.label_scope_index != inputs.end_scope_index );
155
159
160
+ declaration_hop_instrumentationt instructions_to_add;
161
+
156
162
const auto flag = [&]() -> symbolt {
157
163
const auto existing_flag = label_flags.find (inputs.label );
158
164
if (existing_flag != label_flags.end ())
@@ -170,19 +176,20 @@ void goto_convertt::build_declaration_hops(
170
176
label_flags.emplace (inputs.label , new_flag);
171
177
172
178
// Create and initialise flag.
173
- goto_programt flag_creation;
174
- flag_creation .instructions .push_back (
179
+ instructions_to_add. emplace_back (
180
+ program .instructions .begin (),
175
181
goto_programt::make_decl (new_flag.symbol_expr (), label_location));
176
182
const auto make_clear_flag = [&]() -> goto_programt::instructiont {
177
183
return goto_programt::make_assignment (
178
184
new_flag.symbol_expr (), false_exprt{}, label_location);
179
185
};
180
- flag_creation. instructions . push_back ( make_clear_flag ());
181
- program.destructive_insert (program. instructions .begin (), flag_creation );
186
+ instructions_to_add. emplace_back (
187
+ program.instructions .begin (), make_clear_flag () );
182
188
183
189
// Clear flag on arrival at label.
184
190
auto clear_on_arrival = make_clear_flag ();
185
- program.insert_before_swap (inputs.label_instruction , clear_on_arrival);
191
+ instructions_to_add.emplace_back (
192
+ inputs.label_instruction , clear_on_arrival);
186
193
return new_flag;
187
194
}();
188
195
@@ -193,9 +200,7 @@ void goto_convertt::build_declaration_hops(
193
200
goto_location.set_hide ();
194
201
auto set_flag = goto_programt::make_assignment (
195
202
flag.symbol_expr (), true_exprt{}, goto_location);
196
- program.insert_before_swap (goto_instruction, set_flag);
197
- // Keep this iterator referring to the goto instruction, not the assignment.
198
- ++goto_instruction;
203
+ instructions_to_add.emplace_back (goto_instruction, set_flag);
199
204
}
200
205
201
206
auto target = inputs.label_instruction ;
@@ -216,6 +221,8 @@ void goto_convertt::build_declaration_hops(
216
221
declaration_location.set_hide ();
217
222
auto if_goto = goto_programt::make_goto (
218
223
target, flag.symbol_expr (), declaration_location);
224
+ // this isn't changing any previously existing instruction so we insert
225
+ // directly rather than going through instructions_to_add
219
226
program.instructions .insert (
220
227
std::next (declaration->instruction ), std::move (if_goto));
221
228
declaration->accounted_flags .insert (flag.name );
@@ -226,6 +233,8 @@ void goto_convertt::build_declaration_hops(
226
233
// Update the goto so that it goes to the first declaration rather than its
227
234
// original/final destination.
228
235
goto_instruction->set_target (target);
236
+
237
+ return instructions_to_add;
229
238
}
230
239
231
240
/* ****************************************************************** \
@@ -243,6 +252,7 @@ Function: goto_convertt::finish_gotos
243
252
void goto_convertt::finish_gotos (goto_programt &dest, const irep_idt &mode)
244
253
{
245
254
std::unordered_map<irep_idt, symbolt, irep_id_hash> label_flags;
255
+ declaration_hop_instrumentationt instructions_to_insert;
246
256
247
257
for (const auto &g_it : targets.gotos )
248
258
{
@@ -331,7 +341,9 @@ void goto_convertt::finish_gotos(goto_programt &dest, const irep_idt &mode)
331
341
inputs.label_instruction = l_it->second .first ;
332
342
inputs.label_scope_index = label_target;
333
343
inputs.end_scope_index = intersection_result.common_ancestor ;
334
- build_declaration_hops (dest, label_flags, inputs);
344
+ instructions_to_insert.splice (
345
+ instructions_to_insert.end (),
346
+ build_declaration_hops (dest, label_flags, inputs));
335
347
}
336
348
}
337
349
else
@@ -340,6 +352,13 @@ void goto_convertt::finish_gotos(goto_programt &dest, const irep_idt &mode)
340
352
}
341
353
}
342
354
355
+ for (auto r_it = instructions_to_insert.rbegin ();
356
+ r_it != instructions_to_insert.rend ();
357
+ ++r_it)
358
+ {
359
+ dest.insert_before_swap (r_it->first , r_it->second );
360
+ }
361
+
343
362
targets.gotos .clear ();
344
363
}
345
364
0 commit comments