18
18
#include < util/string2int.h>
19
19
#include < util/invariant.h>
20
20
#include < util/std_types.h>
21
+ #include < util/code_visitor.h>
21
22
#include < json/json_parser.h>
22
23
23
24
#include < goto-programs/class_hierarchy.h>
@@ -453,134 +454,111 @@ static const symbolt& add_or_get_symbol(symbol_tablet& symbol_table,
453
454
// /
454
455
// / TODO: check for mismatches in startThread and endThread.
455
456
// /
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
458
458
// / \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)
460
460
{
461
+ PRECONDITION (code.get_statement ()==ID_function_call);
461
462
namespacet ns (symbol_table);
462
463
const std::string& next_thread_id=" __CPROVER_next_thread_id" ;
463
464
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);
465
468
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" )
467
472
{
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;
559
522
}
560
- else if (statement==ID_block )
523
+ else if (fname == " org.cprover.CProver.endThread:(I)V " )
561
524
{
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;
566
548
}
567
- else if (statement==ID_label )
549
+ else if (fname == " org.cprover.CProver.getCurrentThreadID:()I " )
568
550
{
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;
570
558
}
559
+ return ;
571
560
}
572
561
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
- }
584
562
585
563
bool java_bytecode_languaget::final (symbol_tablet &symbol_table)
586
564
{
@@ -591,7 +569,13 @@ bool java_bytecode_languaget::final(symbol_tablet &symbol_table)
591
569
replace_string_methods (symbol_table);
592
570
593
571
// 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);
595
579
596
580
java_bytecode_synchronizet synchronizer (symbol_table);
597
581
0 commit comments