@@ -344,23 +344,33 @@ void goto_convertt::convert_label(
344344
345345 goto_programt tmp;
346346
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.
348350 if (has_prefix (id2string (label), " __CPROVER_ASYNC_" ))
349351 {
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);
355363 }
356364 else
365+ {
357366 convert (to_code (code.op0 ()), tmp);
358367
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);
361370
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+ }
364374}
365375
366376void goto_convertt::convert_gcc_local_label (
@@ -1539,39 +1549,14 @@ void goto_convertt::convert_start_thread(
15391549 const codet &code,
15401550 goto_programt &dest)
15411551{
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-
15491552 goto_programt::targett start_thread=
15501553 dest.add_instruction (START_THREAD);
1551-
15521554 start_thread->source_location =code.source_location ();
1555+ start_thread->code =code;
15531556
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 ));
15751560}
15761561
15771562void goto_convertt::convert_end_thread (
@@ -2242,3 +2227,43 @@ void goto_convert(
22422227
22432228 ::goto_convert (to_code(symbol.value), symbol_table, dest, message_handler);
22442229}
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