@@ -344,23 +344,33 @@ void goto_convertt::convert_label(
344
344
345
345
goto_programt tmp;
346
346
347
- // magic thread creation label?
347
+ // magic thread creation label.
348
+ // The "__CPROVER_ASYNC_" signals the start of a sequence of instructions
349
+ // that can be executed in parallel, i.e, a new thread.
348
350
if (has_prefix (id2string (label), " __CPROVER_ASYNC_" ))
349
351
{
350
- // this is like a START_THREAD
351
- codet tmp_code (ID_start_thread);
352
- tmp_code.copy_to_operands (code.op0 ());
353
- tmp_code.add_source_location ()=code.source_location ();
354
- convert (tmp_code, tmp);
352
+ // the body of the thread is expected to be
353
+ // in the operand.
354
+ INVARIANT (code.op0 ().is_not_nil (),
355
+ " op0 in magic thread creation label is null" );
356
+
357
+ // replace the magic thread creation label with a
358
+ // thread block (START_THREAD...END_THREAD).
359
+ code_blockt thread_body;
360
+ thread_body.add (to_code (code.op0 ()));
361
+ thread_body.add_source_location ()=code.source_location ();
362
+ generate_thread_block (thread_body, dest);
355
363
}
356
364
else
365
+ {
357
366
convert (to_code (code.op0 ()), tmp);
358
367
359
- goto_programt::targett target=tmp.instructions .begin ();
360
- dest.destructive_append (tmp);
368
+ goto_programt::targett target=tmp.instructions .begin ();
369
+ dest.destructive_append (tmp);
361
370
362
- targets.labels .insert ({label, {target, targets.destructor_stack }});
363
- target->labels .push_front (label);
371
+ targets.labels .insert ({label, {target, targets.destructor_stack }});
372
+ target->labels .push_front (label);
373
+ }
364
374
}
365
375
366
376
void goto_convertt::convert_gcc_local_label (
@@ -1539,39 +1549,14 @@ void goto_convertt::convert_start_thread(
1539
1549
const codet &code,
1540
1550
goto_programt &dest)
1541
1551
{
1542
- if (code.operands ().size ()!=1 )
1543
- {
1544
- error ().source_location =code.find_source_location ();
1545
- error () << " start_thread expects one operand" << eom;
1546
- throw 0 ;
1547
- }
1548
-
1549
1552
goto_programt::targett start_thread=
1550
1553
dest.add_instruction (START_THREAD);
1551
-
1552
1554
start_thread->source_location =code.source_location ();
1555
+ start_thread->code =code;
1553
1556
1554
- {
1555
- // start_thread label;
1556
- // goto tmp;
1557
- // label: op0-code
1558
- // end_thread
1559
- // tmp: skip
1560
-
1561
- goto_programt::targett goto_instruction=dest.add_instruction (GOTO);
1562
- goto_instruction->guard =true_exprt ();
1563
- goto_instruction->source_location =code.source_location ();
1564
-
1565
- goto_programt tmp;
1566
- convert (to_code (code.op0 ()), tmp);
1567
- goto_programt::targett end_thread=tmp.add_instruction (END_THREAD);
1568
- end_thread->source_location =code.source_location ();
1569
-
1570
- start_thread->targets .push_back (tmp.instructions .begin ());
1571
- dest.destructive_append (tmp);
1572
- goto_instruction->targets .push_back (dest.add_instruction (SKIP));
1573
- dest.instructions .back ().source_location =code.source_location ();
1574
- }
1557
+ // remember it to do target later
1558
+ targets.gotos .push_back (
1559
+ std::make_pair (start_thread, targets.destructor_stack ));
1575
1560
}
1576
1561
1577
1562
void goto_convertt::convert_end_thread (
@@ -2242,3 +2227,43 @@ void goto_convert(
2242
2227
2243
2228
::goto_convert (to_code(symbol.value), symbol_table, dest, message_handler);
2244
2229
}
2230
+
2231
+ // / Generates the necessary goto-instructions to represent a thread-block.
2232
+ // / Specifically, the following instructions are generated:
2233
+ // /
2234
+ // / A: START_THREAD : C
2235
+ // / B: GOTO Z
2236
+ // / C: SKIP
2237
+ // / D: {THREAD BODY}
2238
+ // / E: END_THREAD
2239
+ // / Z: SKIP
2240
+ // /
2241
+ // / \param thread_body: sequence of codet's that can be executed
2242
+ // / in parallel.
2243
+ // / \param [out] dest: resulting goto-instructions.
2244
+ void goto_convertt::generate_thread_block (
2245
+ const code_blockt &thread_body,
2246
+ goto_programt &dest)
2247
+ {
2248
+ goto_programt preamble, body, postamble;
2249
+
2250
+ goto_programt::targett c=body.add_instruction ();
2251
+ c->make_skip ();
2252
+ convert (thread_body, body);
2253
+
2254
+ goto_programt::targett e=postamble.add_instruction (END_THREAD);
2255
+ e->source_location =thread_body.source_location ();
2256
+ goto_programt::targett z=postamble.add_instruction ();
2257
+ z->make_skip ();
2258
+
2259
+ goto_programt::targett a=preamble.add_instruction (START_THREAD);
2260
+ a->source_location =thread_body.source_location ();
2261
+ a->targets .push_back (c);
2262
+ goto_programt::targett b=preamble.add_instruction ();
2263
+ b->source_location =thread_body.source_location ();
2264
+ b->make_goto (z);
2265
+
2266
+ dest.destructive_append (preamble);
2267
+ dest.destructive_append (body);
2268
+ dest.destructive_append (postamble);
2269
+ }
0 commit comments