Skip to content

Commit 0ce085f

Browse files
author
Matthias Güdemann
committed
Add temporary variables for values on stack for write operations
concerned bytecode instructions: - iinc - pustatic - putfield - ?store - ?astore
1 parent b5cbb7f commit 0ce085f

File tree

2 files changed

+151
-8
lines changed

2 files changed

+151
-8
lines changed

src/java_bytecode/java_bytecode_convert_method.cpp

Lines changed: 138 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,15 +1319,24 @@ codet java_bytecode_convert_methodt::convert_instructions(
13191319
typet element_type=data_ptr.type().subtype();
13201320
const dereference_exprt element(data_plus_offset, element_type);
13211321

1322-
c=code_blockt();
1322+
code_blockt block;
1323+
block.add_source_location()=i_it->source_location;
1324+
1325+
save_stack_entries(
1326+
"stack_astore",
1327+
element_type,
1328+
block,
1329+
bytecode_write_typet::ARRAY_REF,
1330+
"");
1331+
13231332
codet bounds_check=
13241333
get_array_bounds_check(deref, op[1], i_it->source_location);
13251334
bounds_check.add_source_location()=i_it->source_location;
1326-
c.move_to_operands(bounds_check);
1335+
block.move_to_operands(bounds_check);
13271336
code_assignt array_put(element, op[2]);
13281337
array_put.add_source_location()=i_it->source_location;
1329-
c.move_to_operands(array_put);
1330-
c.add_source_location()=i_it->source_location;
1338+
block.move_to_operands(array_put);
1339+
c=block;
13311340
}
13321341
else if(statement==patternt("?store"))
13331342
{
@@ -1336,12 +1345,24 @@ codet java_bytecode_convert_methodt::convert_instructions(
13361345

13371346
exprt var=
13381347
variable(arg0, statement[0], i_it->address, NO_CAST);
1348+
const irep_idt &var_name=to_symbol_expr(var).get_identifier();
13391349

13401350
exprt toassign=op[0];
13411351
if('a'==statement[0] && toassign.type()!=var.type())
13421352
toassign=typecast_exprt(toassign, var.type());
13431353

1344-
c=code_assignt(var, toassign);
1354+
code_blockt block;
1355+
1356+
save_stack_entries(
1357+
"stack_store",
1358+
toassign.type(),
1359+
block,
1360+
bytecode_write_typet::VARIABLE,
1361+
var_name);
1362+
code_assignt assign(var, toassign);
1363+
assign.add_source_location()=i_it->source_location;
1364+
block.copy_to_operands(assign);
1365+
c=block;
13451366
}
13461367
else if(statement==patternt("?aload"))
13471368
{
@@ -1587,13 +1608,25 @@ codet java_bytecode_convert_methodt::convert_instructions(
15871608
}
15881609
else if(statement=="iinc")
15891610
{
1611+
code_blockt block;
1612+
block.add_source_location()=i_it->source_location;
1613+
// search variable on stack
1614+
const exprt &locvar=variable(arg0, 'i', i_it->address, NO_CAST);
1615+
save_stack_entries(
1616+
"stack_iinc",
1617+
java_int_type(),
1618+
block,
1619+
bytecode_write_typet::VARIABLE,
1620+
to_symbol_expr(locvar).get_identifier());
1621+
15901622
code_assignt code_assign;
15911623
code_assign.lhs()=
15921624
variable(arg0, 'i', i_it->address, NO_CAST);
15931625
code_assign.rhs()=plus_exprt(
15941626
variable(arg0, 'i', i_it->address, CAST_AS_NEEDED),
15951627
typecast_exprt(arg1, java_int_type()));
1596-
c=code_assign;
1628+
block.copy_to_operands(code_assign);
1629+
c=block;
15971630
}
15981631
else if(statement==patternt("?xor"))
15991632
{
@@ -1828,7 +1861,15 @@ codet java_bytecode_convert_methodt::convert_instructions(
18281861
else if(statement=="putfield")
18291862
{
18301863
assert(op.size()==2 && results.size()==0);
1831-
c=code_assignt(to_member(op[0], arg0), op[1]);
1864+
code_blockt block;
1865+
save_stack_entries(
1866+
"stack_field",
1867+
op[1].type(),
1868+
block,
1869+
bytecode_write_typet::FIELD,
1870+
arg0.get(ID_component_name));
1871+
block.copy_to_operands(code_assignt(to_member(op[0], arg0), op[1]));
1872+
c=block;
18321873
}
18331874
else if(statement=="putstatic")
18341875
{
@@ -1841,7 +1882,17 @@ codet java_bytecode_convert_methodt::convert_instructions(
18411882
lazy_methods->add_needed_class(
18421883
to_symbol_type(arg0.type()).get_identifier());
18431884
}
1844-
c=code_assignt(symbol_expr, op[0]);
1885+
code_blockt block;
1886+
block.add_source_location()=i_it->source_location;
1887+
1888+
save_stack_entries(
1889+
"stack_static_field",
1890+
symbol_expr.type(),
1891+
block,
1892+
bytecode_write_typet::STATIC_FIELD,
1893+
symbol_expr.get_identifier());
1894+
block.copy_to_operands(code_assignt(symbol_expr, op[0]));
1895+
c=block;
18451896
}
18461897
else if(statement==patternt("?2?")) // i2c etc.
18471898
{
@@ -1860,6 +1911,7 @@ codet java_bytecode_convert_methodt::convert_instructions(
18601911

18611912
const exprt tmp=tmp_variable("new", ref_type);
18621913
c=code_assignt(tmp, java_new_expr);
1914+
c.add_source_location()=i_it->source_location;
18631915
results[0]=tmp;
18641916
}
18651917
else if(statement=="newarray" ||
@@ -2443,3 +2495,81 @@ void java_bytecode_convert_method(
24432495

24442496
java_bytecode_convert_method(class_symbol, method);
24452497
}
2498+
2499+
/*******************************************************************\
2500+
2501+
Function: java_bytecode_convert_methodt::save_stack_entries
2502+
2503+
Inputs:
2504+
2505+
Outputs:
2506+
2507+
Purpose: create temporary variables if a write instruction can have undesired
2508+
side-effects
2509+
2510+
\*******************************************************************/
2511+
2512+
void java_bytecode_convert_methodt::save_stack_entries(
2513+
const std::string &tmp_var_prefix,
2514+
const typet &tmp_var_type,
2515+
code_blockt &block,
2516+
const bytecode_write_typet write_type,
2517+
const irep_idt &identifier)
2518+
{
2519+
for(auto &stack_entry : stack)
2520+
{
2521+
// remove typecasts if existing
2522+
while(stack_entry.id()==ID_typecast)
2523+
stack_entry=to_typecast_expr(stack_entry).op();
2524+
2525+
// variables or static fields and symbol -> save symbols with same id
2526+
if((write_type==bytecode_write_typet::VARIABLE ||
2527+
write_type==bytecode_write_typet::STATIC_FIELD) &&
2528+
stack_entry.id()==ID_symbol)
2529+
{
2530+
const symbol_exprt &var=to_symbol_expr(stack_entry);
2531+
if(var.get_identifier()==identifier)
2532+
create_stack_tmp_var(tmp_var_prefix, tmp_var_type, block, stack_entry);
2533+
}
2534+
2535+
// array reference and dereference -> save all references on the stack
2536+
else if(write_type==bytecode_write_typet::ARRAY_REF &&
2537+
stack_entry.id()==ID_dereference)
2538+
create_stack_tmp_var(tmp_var_prefix, tmp_var_type, block, stack_entry);
2539+
2540+
// field and member access -> compare component name
2541+
else if(write_type==bytecode_write_typet::FIELD &&
2542+
stack_entry.id()==ID_member)
2543+
{
2544+
const irep_idt &entry_id=
2545+
to_member_expr(stack_entry).get_component_name();
2546+
if(entry_id==identifier)
2547+
create_stack_tmp_var(tmp_var_prefix, tmp_var_type, block, stack_entry);
2548+
}
2549+
}
2550+
}
2551+
2552+
/*******************************************************************\
2553+
2554+
Function: java_bytecode_convert_methodt::create_stack_tmp_var
2555+
2556+
Inputs:
2557+
2558+
Outputs:
2559+
2560+
Purpose: actually create a temporary variable to hold the value of a stack
2561+
entry
2562+
2563+
\*******************************************************************/
2564+
2565+
void java_bytecode_convert_methodt::create_stack_tmp_var(
2566+
const std::string &tmp_var_prefix,
2567+
const typet &tmp_var_type,
2568+
code_blockt &block,
2569+
exprt &stack_entry)
2570+
{
2571+
const exprt tmp_var=
2572+
tmp_variable(tmp_var_prefix, tmp_var_type);
2573+
block.copy_to_operands(code_assignt(tmp_var, stack_entry));
2574+
stack_entry=tmp_var;
2575+
}

src/java_bytecode/java_bytecode_convert_method_class.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,19 @@ class java_bytecode_convert_methodt:public messaget
215215
const code_typet &);
216216

217217
const bytecode_infot &get_bytecode_info(const irep_idt &statement);
218+
219+
enum class bytecode_write_typet { VARIABLE, ARRAY_REF, STATIC_FIELD, FIELD};
220+
void save_stack_entries(
221+
const std::string &,
222+
const typet &,
223+
code_blockt &,
224+
const bytecode_write_typet,
225+
const irep_idt &);
226+
void create_stack_tmp_var(
227+
const std::string &,
228+
const typet &,
229+
code_blockt &,
230+
exprt &);
218231
};
219232

220233
#endif

0 commit comments

Comments
 (0)