@@ -1319,15 +1319,24 @@ codet java_bytecode_convert_methodt::convert_instructions(
1319
1319
typet element_type=data_ptr.type ().subtype ();
1320
1320
const dereference_exprt element (data_plus_offset, element_type);
1321
1321
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
+
1323
1332
codet bounds_check=
1324
1333
get_array_bounds_check (deref, op[1 ], i_it->source_location );
1325
1334
bounds_check.add_source_location ()=i_it->source_location ;
1326
- c .move_to_operands (bounds_check);
1335
+ block .move_to_operands (bounds_check);
1327
1336
code_assignt array_put (element, op[2 ]);
1328
1337
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 ;
1331
1340
}
1332
1341
else if (statement==patternt (" ?store" ))
1333
1342
{
@@ -1336,12 +1345,24 @@ codet java_bytecode_convert_methodt::convert_instructions(
1336
1345
1337
1346
exprt var=
1338
1347
variable (arg0, statement[0 ], i_it->address , NO_CAST);
1348
+ const irep_idt &var_name=to_symbol_expr (var).get_identifier ();
1339
1349
1340
1350
exprt toassign=op[0 ];
1341
1351
if (' a' ==statement[0 ] && toassign.type ()!=var.type ())
1342
1352
toassign=typecast_exprt (toassign, var.type ());
1343
1353
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;
1345
1366
}
1346
1367
else if (statement==patternt (" ?aload" ))
1347
1368
{
@@ -1587,13 +1608,25 @@ codet java_bytecode_convert_methodt::convert_instructions(
1587
1608
}
1588
1609
else if (statement==" iinc" )
1589
1610
{
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
+
1590
1622
code_assignt code_assign;
1591
1623
code_assign.lhs ()=
1592
1624
variable (arg0, ' i' , i_it->address , NO_CAST);
1593
1625
code_assign.rhs ()=plus_exprt (
1594
1626
variable (arg0, ' i' , i_it->address , CAST_AS_NEEDED),
1595
1627
typecast_exprt (arg1, java_int_type ()));
1596
- c=code_assign;
1628
+ block.copy_to_operands (code_assign);
1629
+ c=block;
1597
1630
}
1598
1631
else if (statement==patternt (" ?xor" ))
1599
1632
{
@@ -1828,7 +1861,15 @@ codet java_bytecode_convert_methodt::convert_instructions(
1828
1861
else if (statement==" putfield" )
1829
1862
{
1830
1863
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;
1832
1873
}
1833
1874
else if (statement==" putstatic" )
1834
1875
{
@@ -1841,7 +1882,17 @@ codet java_bytecode_convert_methodt::convert_instructions(
1841
1882
lazy_methods->add_needed_class (
1842
1883
to_symbol_type (arg0.type ()).get_identifier ());
1843
1884
}
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;
1845
1896
}
1846
1897
else if (statement==patternt (" ?2?" )) // i2c etc.
1847
1898
{
@@ -1860,6 +1911,7 @@ codet java_bytecode_convert_methodt::convert_instructions(
1860
1911
1861
1912
const exprt tmp=tmp_variable (" new" , ref_type);
1862
1913
c=code_assignt (tmp, java_new_expr);
1914
+ c.add_source_location ()=i_it->source_location ;
1863
1915
results[0 ]=tmp;
1864
1916
}
1865
1917
else if (statement==" newarray" ||
@@ -2443,3 +2495,81 @@ void java_bytecode_convert_method(
2443
2495
2444
2496
java_bytecode_convert_method (class_symbol, method);
2445
2497
}
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