@@ -18,6 +18,7 @@ Author: Daniel Kroening, kroening@kroening.com
1818#include < util/string2int.h>
1919#include < util/invariant.h>
2020#include < util/std_types.h>
21+ #include < util/code_visitor.h>
2122#include < json/json_parser.h>
2223
2324#include < goto-programs/class_hierarchy.h>
@@ -453,134 +454,111 @@ static const symbolt& add_or_get_symbol(symbol_tablet& symbol_table,
453454// /
454455// / TODO: check for mismatches in startThread and endThread.
455456// /
456- // / \param code: codet, should be ID_function_call, ID_block or ID_label
457- // / else ignored.
457+ // / \param code: codet, should be ID_function_call
458458// / \param symbol_table: a symbol table
459- void java_bytecode_languaget::convert_threadblock (codet& code, symbol_tablet& symbol_table)
459+ void java_bytecode_languaget::convert_threadblock (codet & code, symbol_tablet & symbol_table)
460460{
461+ PRECONDITION (code.get_statement ()==ID_function_call);
461462 namespacet ns (symbol_table);
462463 const std::string& next_thread_id=" __CPROVER_next_thread_id" ;
463464 const std::string& thread_id=" __CPROVER_thread_id" ;
464- const irep_idt &statement=code.get_statement ();
465+ std::string fname=" " ;
466+ code_function_callt &f_code=to_code_function_call (code);
467+ from_expr (f_code.function (), fname, ns);
465468
466- if (statement==ID_function_call)
469+ // get function name and see if it
470+ // matches org.cprover.start() or org.cprover.end()
471+ if (fname == " org.cprover.CProver.startThread:(I)V" )
467472 {
468- // get function name and see if it
469- // matches org.cprover.start() or org.cprover.end()
470- std::string fname=" " ;
471- code_function_callt &f_code=to_code_function_call (code);
472- from_expr (f_code.function (), fname, ns);
473- if (fname == " org.cprover.CProver.startThread:(I)V" )
474- {
475- INVARIANT (f_code.arguments ().size ()==1 ,
476- " ERROR: CProver.startThread invalid number of arguments" );
477-
478- // build id's, used to construct appropriate labels.
479- const exprt &expr=f_code.arguments ()[0 ];
480- const std::string& v_str=expr.op0 ().get_string (ID_value);
481- mp_integer v=binary2integer (v_str, false );
482- const std::string &lbl1 = " TS_1_" +integer2string (v);
483- const std::string &lbl2 = " TS_2_" +integer2string (v);
484-
485- // instrument the following code:
486- //
487- // A: START_THREAD : TS_1_<ID>
488- // B: goto : TS_2_<ID>
489- // C: label (TS_1_<ID>)
490- // C.1 codet(ID_atomic_begin)
491- // D: __CPROVER_thread_id=__CPROVER_next_thread_id
492- // E: __CPROVER_next_thread_id+=1;
493- // E.1 codet(ID_atomic_end)
494-
495- const symbolt& next_symbol=
496- add_or_get_symbol (symbol_table, next_thread_id, true , false );
497- const symbolt& current_symbol=
498- add_or_get_symbol (symbol_table, thread_id, false , true );
499-
500- codet tmp_a (ID_start_thread);
501- tmp_a.set (ID_destination, lbl1);
502- code_gotot tmp_b (lbl2);
503- code_labelt tmp_c (lbl1);
504- tmp_c.op0 ()=codet (ID_skip);
505-
506- exprt plus (ID_plus, java_int_type ());
507- plus.copy_to_operands (next_symbol.symbol_expr ());
508- plus.copy_to_operands (from_integer (1 , java_int_type ()));
509- code_assignt tmp_d (current_symbol.symbol_expr (), next_symbol.symbol_expr ());
510- code_assignt tmp_e (next_symbol.symbol_expr (), plus);
511-
512- code_blockt block;
513- block.add (tmp_a);
514- block.add (tmp_b);
515- block.add (tmp_c);
516- block.add (codet (ID_atomic_begin));
517- block.add (tmp_d);
518- block.add (tmp_e);
519- block.add (codet (ID_atomic_end));
520-
521- block.add_source_location ()=code.source_location ();
522- code=block;
523- }
524- else if (fname == " org.cprover.CProver.endThread:(I)V" )
525- {
526- INVARIANT (f_code.arguments ().size ()==1 ,
527- " ERROR: CProver.endThread invalid number of arguments" );
528-
529- // build id, used to construct appropriate labels.
530- const exprt &expr=f_code.arguments ()[0 ];
531- const std::string& v_str=expr.op0 ().get_string (ID_value);
532- mp_integer v=binary2integer (v_str, false );
533- const std::string &lbl2 = " TS_2_" +integer2string (v);
534-
535- // instrument the following code:
536- // F: END_THREAD
537- // G: label (TS_2_<ID>)
538- codet tmp_f (ID_end_thread);
539- code_labelt tmp_g (lbl2);
540- tmp_g.op0 ()=codet (ID_skip);
541-
542- code_blockt block;
543- block.add (tmp_f);
544- block.add (tmp_g);
545-
546- block.add_source_location ()=code.source_location ();
547- code=block;
548- }
549- else if (fname == " org.cprover.CProver.getCurrentThreadID:()I" )
550- {
551- INVARIANT (f_code.arguments ().size ()==0 ,
552- " ERROR: CProver.getCurrentThreadID invalid number of arguments" );
553- const symbolt& current_symbol=
554- add_or_get_symbol (symbol_table, thread_id, false , true );
555- code_assignt code_assign (f_code.lhs (), current_symbol.symbol_expr ());
556- code_assign.add_source_location ()=code.source_location ();
557- code=code_assign;
558- }
473+ INVARIANT (f_code.arguments ().size ()==1 ,
474+ " ERROR: CProver.startThread invalid number of arguments" );
475+
476+ // build id's, used to construct appropriate labels.
477+ const exprt &expr=f_code.arguments ()[0 ];
478+ const std::string& v_str=expr.op0 ().get_string (ID_value);
479+ mp_integer v=binary2integer (v_str, false );
480+ // java does not have labels so this this is safe.
481+ const std::string &lbl1=" TS_1_" +integer2string (v);
482+ const std::string &lbl2=" TS_2_" +integer2string (v);
483+
484+ // instrument the following code:
485+ //
486+ // A: codet(ID_start_thread) --> TS_1_<ID>
487+ // B: goto : TS_2_<ID>
488+ // C: label (TS_1_<ID>)
489+ // C.1 codet(ID_atomic_begin)
490+ // D: __CPROVER_thread_id=__CPROVER_next_thread_id
491+ // E: __CPROVER_next_thread_id+=1;
492+ // E.1 codet(ID_atomic_end)
493+
494+ const symbolt& next_symbol=
495+ add_or_get_symbol (symbol_table, next_thread_id, true , false );
496+ const symbolt& current_symbol=
497+ add_or_get_symbol (symbol_table, thread_id, false , true );
498+
499+ codet tmp_a (ID_start_thread);
500+ tmp_a.set (ID_destination, lbl1);
501+ code_gotot tmp_b (lbl2);
502+ code_labelt tmp_c (lbl1);
503+ tmp_c.op0 ()=codet (ID_skip);
504+
505+ exprt plus (ID_plus, java_int_type ());
506+ plus.copy_to_operands (next_symbol.symbol_expr ());
507+ plus.copy_to_operands (from_integer (1 , java_int_type ()));
508+ code_assignt tmp_d (current_symbol.symbol_expr (), next_symbol.symbol_expr ());
509+ code_assignt tmp_e (next_symbol.symbol_expr (), plus);
510+
511+ code_blockt block;
512+ block.add (tmp_a);
513+ block.add (tmp_b);
514+ block.add (tmp_c);
515+ block.add (codet (ID_atomic_begin));
516+ block.add (tmp_d);
517+ block.add (tmp_e);
518+ block.add (codet (ID_atomic_end));
519+
520+ block.add_source_location ()=code.source_location ();
521+ code=block;
559522 }
560- else if (statement==ID_block )
523+ else if (fname == " org.cprover.CProver.endThread:(I)V " )
561524 {
562- // now convert block
563- code_blockt& block_code = to_code_block (code);
564- for (exprt& op : block_code.operands ())
565- convert_threadblock (to_code (op), symbol_table);
525+ INVARIANT (f_code.arguments ().size ()==1 ,
526+ " ERROR: CProver.endThread invalid number of arguments" );
527+
528+ // build id, used to construct appropriate labels.
529+ const exprt &expr=f_code.arguments ()[0 ];
530+ const std::string& v_str=expr.op0 ().get_string (ID_value);
531+ mp_integer v=binary2integer (v_str, false );
532+ // java does not have labels so this this is safe.
533+ const std::string &lbl2=" TS_2_" +integer2string (v);
534+
535+ // instrument the following code:
536+ // F: codet(ID_end_thread)
537+ // G: label (TS_2_<ID>)
538+ codet tmp_f (ID_end_thread);
539+ code_labelt tmp_g (lbl2);
540+ tmp_g.op0 ()=codet (ID_skip);
541+
542+ code_blockt block;
543+ block.add (tmp_f);
544+ block.add (tmp_g);
545+
546+ block.add_source_location ()=code.source_location ();
547+ code=block;
566548 }
567- else if (statement==ID_label )
549+ else if (fname == " org.cprover.CProver.getCurrentThreadID:()I " )
568550 {
569- convert_threadblock (to_code (code.op0 ()), symbol_table);
551+ INVARIANT (f_code.arguments ().size ()==0 ,
552+ " ERROR: CProver.getCurrentThreadID invalid number of arguments" );
553+ const symbolt& current_symbol=
554+ add_or_get_symbol (symbol_table, thread_id, false , true );
555+ code_assignt code_assign (f_code.lhs (), current_symbol.symbol_expr ());
556+ code_assign.add_source_location ()=code.source_location ();
557+ code=code_assign;
570558 }
559+ return ;
571560}
572561
573- void java_bytecode_languaget::replace_thread_blocks (symbol_tablet& symbol_table)
574- {
575- forall_symbols (symbol, symbol_table.symbols )
576- {
577- if (symbol->second .type .id ()==ID_code && symbol->second .value .is_not_nil ())
578- {
579- symbolt &w_symbol=*symbol_table.get_writeable (symbol->second .name );
580- convert_threadblock (to_code (w_symbol.value ), symbol_table);
581- }
582- }
583- }
584562
585563bool java_bytecode_languaget::final (symbol_tablet &symbol_table)
586564{
@@ -591,7 +569,13 @@ bool java_bytecode_languaget::final(symbol_tablet &symbol_table)
591569 replace_string_methods (symbol_table);
592570
593571 // Deal with org.cprover.CProver.startThread() and endThread()
594- replace_thread_blocks (symbol_table);
572+ code_visitort::callmapt map;
573+ code_visitort::callbackt f=
574+ std::bind (&java_bytecode_languaget::convert_threadblock,
575+ this , std::placeholders::_1, symbol_table);
576+ map.insert ({ID_function_call, f});
577+ code_visitort thread_block_visitor (map);
578+ thread_block_visitor.visit_symbols (symbol_table);
595579
596580 java_bytecode_synchronizet synchronizer (symbol_table);
597581
0 commit comments