Skip to content

Commit 04c30af

Browse files
authored
Merge pull request #2 from cesaro/feature/code_visitor
Implemented a new visitor, for codet.
2 parents eb671e9 + 3eeb335 commit 04c30af

File tree

3 files changed

+152
-117
lines changed

3 files changed

+152
-117
lines changed

src/java_bytecode/java_bytecode_language.cpp

Lines changed: 99 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Author: Daniel Kroening, [email protected]
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

585563
bool 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

src/java_bytecode/java_bytecode_language.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,7 @@ class java_bytecode_languaget:public languaget
106106
const std::string &module) override;
107107

108108
void replace_string_methods(symbol_tablet &context);
109-
void replace_thread_blocks(symbol_tablet &context);
110-
void convert_threadblock(codet& code, symbol_tablet &symbol_table);
109+
void convert_threadblock(codet &code, symbol_tablet &symbol_table);
111110

112111
virtual bool final(
113112
symbol_tablet &context) override;

src/util/code_visitor.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*******************************************************************\
2+
3+
Module: Misc Utilities
4+
5+
Author: Diffblue
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// code_visitor.h
11+
#ifndef CPROVER_UTIL_CODE_VISITOR_H
12+
#define CPROVER_UTIL_CODE_VISITOR_H
13+
14+
#include <cstdio>
15+
#include <map>
16+
#include <functional>
17+
#include "symbol_table.h"
18+
#include "std_code.h"
19+
20+
class code_visitort : public expr_visitort
21+
{
22+
public:
23+
typedef std::function<void(codet&)> callbackt;
24+
typedef std::map<irep_idt, callbackt> callmapt;
25+
26+
code_visitort(callmapt& cv) : call_map(cv) {}
27+
28+
void visit_symbols(symbol_tablet &symbol_table)
29+
{
30+
forall_symbols(symbol, symbol_table.symbols)
31+
{
32+
symbolt &w_symbol=*symbol_table.get_writeable(symbol->second.name);
33+
w_symbol.value.visit(*this);
34+
}
35+
}
36+
37+
void operator()(exprt &expr) final
38+
{
39+
if(expr.id()!=ID_code || !expr.is_not_nil())
40+
return;
41+
codet &code=to_code(expr);
42+
const irep_idt &statement=code.get_statement();
43+
auto it=call_map.find(statement);
44+
if(it!=call_map.end())
45+
it->second(code);
46+
};
47+
48+
private:
49+
callmapt &call_map;
50+
};
51+
52+
#endif // CPROVER_UTIL_CODE_VISITOR_H

0 commit comments

Comments
 (0)