@@ -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+ }
0 commit comments