39 #include <unordered_set> 51 for(std::size_t i=0; i<what.
size(); i++)
54 else if(
p[i]!=
'?' &&
p[i]!=what[i])
57 return p[what.
size()]==0;
86 const auto to_strip_str=
id2string(to_strip);
88 return to_strip_str.substr(6, std::string::npos);
97 return npos!=name.find(
"<init>") || npos!=name.find(
"<clinit>");
104 error() <<
"malformed bytecode (pop too high)" <<
eom;
110 for(std::size_t i=0; i<n; i++)
120 std::size_t residue_size=std::min(n,
stack.size());
129 for(std::size_t i=0; i<o.size(); i++)
140 const std::string &prefix,
149 tmp_symbol.
mode=ID_java;
150 tmp_symbol.
name=identifier;
151 tmp_symbol.
type=type;
155 result.set(ID_C_base_name, base_name);
182 irep_idt base_name=
"anonlocal::"+std::to_string(number_int)+type_char;
186 result.set(ID_C_base_name, base_name);
216 method_symbol.
name=method_identifier;
218 method_symbol.
mode=ID_java;
222 member_type.
set(ID_access, ID_public);
224 member_type.
set(ID_access, ID_protected);
226 member_type.
set(ID_access, ID_private);
228 member_type.
set(ID_access, ID_default);
235 member_type.
set(ID_constructor,
true);
250 this_p.
type()=object_ref_type;
252 parameters.insert(parameters.begin(), this_p);
255 method_symbol.
type=member_type;
256 symbol_table.
add(method_symbol);
269 typet member_type=old_sym.type;
283 std::ostringstream id_oss;
287 result.set(ID_C_base_name, v.name);
292 newv.start_pc=v.start_pc;
293 newv.length=v.length;
297 std::size_t param_index=0;
298 for(
const auto ¶m : parameters)
306 for(
auto ¶m : parameters)
310 if(param_index==0 && param.get_this())
314 param.set_base_name(base_name);
315 param.set_identifier(identifier);
320 base_name=
variables[param_index][0].symbol_expr.get(ID_C_base_name);
321 identifier=
variables[param_index][0].symbol_expr.get(ID_identifier);
323 if(base_name.
empty())
325 const typet &type=param.type();
327 base_name=
"arg"+std::to_string(param_index)+suffix;
331 param.set_base_name(base_name);
332 param.set_identifier(identifier);
338 parameter_symbol.
mode=ID_java;
339 parameter_symbol.
name=identifier;
340 parameter_symbol.
type=param.type();
346 variables[param_index][0].is_parameter=
true;
348 variables[param_index][0].length=std::numeric_limits<size_t>::max();
349 variables[param_index][0].is_parameter=
true;
351 assert(param_index>0);
367 method.
set(ID_is_virtual, is_virtual);
370 method.
set(ID_constructor,
true);
372 method.
type()=member_type;
380 method_symbol.
mode=ID_java;
391 method_symbol.
type=member_type;
393 method_symbol.
type.
set(ID_constructor,
true);
413 if(statement==p->mnemonic)
416 error() <<
"failed to find bytecode mnemonic `" 417 << statement <<
'\'' <<
eom;
436 throw "unhandled java comparison instruction";
450 fieldref.
get(ID_component_name),
455 const exprt &arraystruct,
466 bounds_checks.
operands().back().add_source_location()=original_sloc;
467 bounds_checks.
operands().back().add_source_location()
468 .set_comment(
"Array index < 0");
469 bounds_checks.
operands().back().add_source_location()
470 .set_property_class(
"array-index-out-of-bounds-low");
473 bounds_checks.
operands().back().add_source_location()=original_sloc;
474 bounds_checks.
operands().back().add_source_location()
475 .set_comment(
"Array index >= length");
476 bounds_checks.
operands().back().add_source_location()
477 .set_property_class(
"array-index-out-of-bounds-high");
480 return bounds_checks;
498 if(g.get_destination()==old_label)
499 g.set_destination(new_label);
526 unsigned address_start,
527 unsigned address_limit,
528 unsigned next_block_start_address)
536 next_block_start_address,
558 unsigned address_start,
559 unsigned address_limit,
560 unsigned next_block_start_address,
570 assert(!tree.
branch.empty());
573 const auto afterstart=
579 auto findstart=afterstart;
590 unsigned findlim_block_start_address=
592 next_block_start_address :
601 auto child_iter=this_block.
operands().begin();
604 while(child_iter!=this_block.
operands().end() &&
607 assert(child_iter!=this_block.
operands().end());
608 std::advance(child_iter, child_offset);
609 assert(child_iter!=this_block.
operands().end());
613 bool single_child(afterstart==findlim);
618 tree.
branch[child_offset],
622 findlim_block_start_address,
640 auto checkit=amap.
find(*findstart);
641 assert(checkit!=amap.end());
644 checkit!=amap.end() && (checkit->first)<(findlim_block_start_address);
647 for(
auto p : checkit->second.predecessors)
649 if(p<(*findstart) || p>=findlim_block_start_address)
651 debug() <<
"Warning: refusing to create lexical block spanning " 652 << (*findstart) <<
"-" << findlim_block_start_address
653 <<
" due to incoming edge " << p <<
" -> " 654 << checkit->first <<
eom;
664 const irep_idt child_label_name=child_label.get_label();
665 std::string new_label_str=
as_string(child_label_name);
667 irep_idt new_label_irep(new_label_str);
671 auto nblocks=std::distance(findstart, findlim);
673 debug() <<
"Combining " << std::distance(findstart, findlim)
674 <<
" blocks for addresses " << (*findstart) <<
"-" 675 << findlim_block_start_address <<
eom;
678 auto &this_block_children=this_block.
operands();
679 assert(tree.
branch.size()==this_block_children.size());
680 for(
auto blockidx=child_offset, blocklim=child_offset+nblocks;
691 auto delfirst=this_block_children.begin();
692 std::advance(delfirst, child_offset+1);
693 auto dellim=delfirst;
694 std::advance(dellim, nblocks-1);
695 this_block_children.erase(delfirst, dellim);
696 this_block_children[child_offset].swap(newlabel);
700 auto branchstart=tree.
branch.begin();
701 std::advance(branchstart, child_offset);
702 auto branchlim=branchstart;
703 std::advance(branchlim, nblocks);
704 for(
auto branchiter=branchstart; branchiter!=branchlim; ++branchiter)
705 newnode.
branch.push_back(std::move(*branchiter));
707 tree.
branch.erase(branchstart, branchlim);
709 assert(tree.
branch.size()==this_block_children.size());
712 std::advance(branchaddriter, child_offset);
713 auto branchaddrlim=branchaddriter;
714 std::advance(branchaddrlim, nblocks);
723 tree.
branch[child_offset]=std::move(newnode);
730 to_code(this_block_children[child_offset])).code());
736 std::map<irep_idt, java_bytecode_convert_methodt::variablet> &result)
738 if(e.
id()==ID_symbol)
743 symexpr.get_identifier(),
745 auto &var=findit.first->second;
748 var.symbol_expr=symexpr;
756 var.length+=(var.start_pc-pc);
761 var.length=std::max(var.length, (pc-var.start_pc)+1);
774 if(ty.
id()==ID_pointer)
793 std::set<unsigned> targets;
795 std::vector<unsigned> jsr_ret_targets;
796 std::vector<instructionst::const_iterator> ret_instructions;
798 for(instructionst::const_iterator
799 i_it=instructions.begin();
800 i_it!=instructions.end();
804 std::pair<address_mapt::iterator, bool> a_entry=
805 address_map.insert(std::make_pair(i_it->address, ins));
806 assert(a_entry.second);
809 assert(a_entry.first==--address_map.end());
811 if(i_it->statement!=
"goto" &&
812 i_it->statement!=
"return" &&
813 !(i_it->statement==
patternt(
"?return")) &&
814 i_it->statement!=
"athrow" &&
815 i_it->statement!=
"jsr" &&
816 i_it->statement!=
"jsr_w" &&
817 i_it->statement!=
"ret")
819 instructionst::const_iterator next=i_it;
820 if(++next!=instructions.end())
821 a_entry.first->second.successors.push_back(next->address);
824 if(i_it->statement==
"athrow" ||
825 i_it->statement==
"invokestatic" ||
826 i_it->statement==
"invokevirtual" ||
827 i_it->statement==
"invokespecial" ||
828 i_it->statement==
"invokeinterface")
834 if(i_it->address>=exception_row.start_pc &&
835 i_it->address<exception_row.end_pc)
837 a_entry.first->second.successors.push_back(
838 exception_row.handler_pc);
839 targets.insert(exception_row.handler_pc);
844 if(i_it->statement==
"goto" ||
845 i_it->statement==
patternt(
"if_?cmp??") ||
846 i_it->statement==
patternt(
"if??") ||
847 i_it->statement==
"ifnonnull" ||
848 i_it->statement==
"ifnull" ||
849 i_it->statement==
"jsr" ||
850 i_it->statement==
"jsr_w")
852 assert(!i_it->args.empty());
857 targets.insert(target);
859 a_entry.first->second.successors.push_back(target);
861 if(i_it->statement==
"jsr" ||
862 i_it->statement==
"jsr_w")
864 instructionst::const_iterator next=i_it+1;
866 next!=instructions.end() &&
867 "jsr without valid return address?");
868 targets.insert(next->address);
869 jsr_ret_targets.push_back(next->address);
872 else if(i_it->statement==
"tableswitch" ||
873 i_it->statement==
"lookupswitch")
876 for(
const auto &arg : i_it->args)
883 targets.insert(target);
884 a_entry.first->second.successors.push_back(target);
889 else if(i_it->statement==
"ret")
892 ret_instructions.push_back(i_it);
898 for(
const auto retinst : ret_instructions)
900 auto &a_entry=address_map.at(retinst->address);
901 a_entry.successors.insert(
902 a_entry.successors.end(),
903 jsr_ret_targets.begin(),
904 jsr_ret_targets.end());
907 for(
const auto &address : address_map)
909 for(
unsigned s : address.second.successors)
911 address_mapt::iterator a_it=address_map.find(s);
912 assert(a_it!=address_map.end());
914 a_it->second.predecessors.insert(address.first);
922 std::set<unsigned> working_set;
924 if(!instructions.empty())
925 working_set.insert(instructions.front().address);
927 while(!working_set.empty())
929 std::set<unsigned>::iterator cur=working_set.begin();
930 address_mapt::iterator a_it=address_map.find(*cur);
931 assert(a_it!=address_map.end());
932 unsigned cur_pc=*cur;
933 working_set.erase(cur);
935 if(a_it->second.done)
938 .insert(a_it->second.successors.begin(), a_it->second.successors.end());
940 instructionst::const_iterator i_it=a_it->second.source;
941 stack.swap(a_it->second.stack);
942 a_it->second.stack.clear();
943 codet &c=a_it->second.code;
947 a_it->second.predecessors.size()<=1 ||
949 stack.front().get_string(ID_C_base_name),
959 if(statement.
size()>=2 &&
960 statement[statement.
size()-2]==
'_' &&
961 isdigit(statement[statement.
size()-1]))
968 statement=std::string(
id2string(statement), 0, statement.size()-2);
976 if(cur_pc==it->handler_pc)
990 catch_handler_expr.
get_sub().resize(1);
991 catch_handler_expr.
get_sub()[0]=exc_var;
1000 handler_block.move_to_operands(catch_handler);
1001 handler_block.move_to_operands(label_block);
1017 if(statement==
"aconst_null")
1019 assert(results.size()==1);
1022 else if(statement==
"athrow")
1024 assert(op.size()==1 && results.size()==1);
1029 const exprt not_equal_null(
1036 block.move_to_operands(check);
1044 block.move_to_operands(c);
1047 else if(statement==
"checkcast")
1053 assert(op.size()==1 && results.size()==1);
1061 else if(statement==
"invokedynamic")
1067 pop(parameters.size());
1071 if(return_type.id()!=ID_empty)
1077 i_it->source_location,
1082 else if(statement==
"invokeinterface" ||
1083 statement==
"invokespecial" ||
1084 statement==
"invokevirtual" ||
1085 statement==
"invokestatic")
1087 const bool use_this(statement!=
"invokestatic");
1088 const bool is_virtual(
1089 statement==
"invokevirtual" || statement==
"invokeinterface");
1096 if(parameters.empty() || !parameters[0].get_this())
1102 if(statement==
"invokespecial")
1105 .find(
"<init>")!=std::string::npos)
1109 code_type.
set(ID_constructor,
true);
1112 code_type.
set(ID_java_super_method_call,
true);
1118 parameters.insert(parameters.begin(), this_p);
1133 assert(this_arg.
type().
id()==ID_pointer);
1141 for(std::size_t i=0; i<parameters.size(); i++)
1143 const typet &type=parameters[i].type();
1148 type.
id()==ID_pointer)
1152 call.
arguments()[i].make_typecast(type);
1160 if(return_type.
id()!=ID_empty)
1166 results[0]=promoted;
1169 assert(arg0.
id()==ID_virtual_function);
1182 symbol.
mode=ID_java;
1209 else if(statement==
"return")
1211 assert(op.empty() && results.empty());
1214 else if(statement==
patternt(
"?return"))
1218 assert(op.size()==1 && results.empty());
1224 else if(statement==
patternt(
"?astore"))
1226 assert(op.size()==3 && results.empty());
1228 char type_char=statement[0];
1240 plus_exprt data_plus_offset(data_ptr, op[1], data_ptr.type());
1263 else if(statement==
patternt(
"?store"))
1266 assert(op.size()==1 && results.empty());
1272 exprt toassign=op[0];
1273 if(
'a'==statement[0] && toassign.
type()!=var.type())
1285 assign.add_source_location()=i_it->source_location;
1289 else if(statement==
patternt(
"?aload"))
1291 assert(op.size()==2 && results.size()==1);
1293 char type_char=statement[0];
1305 plus_exprt data_plus_offset(data_ptr, op[1], data_ptr.type());
1313 else if(statement==
patternt(
"?load"))
1319 else if(statement==
"ldc" || statement==
"ldc_w" ||
1320 statement==
"ldc2" || statement==
"ldc2_w")
1322 assert(op.empty() && results.size()==1);
1333 if(arg0.
id()==ID_java_string_literal)
1340 else if(arg0.
id()==ID_type)
1348 results[0]=address_of_expr;
1350 else if(arg0.
id()==ID_constant)
1356 error() <<
"unexpected ldc argument" <<
eom;
1360 else if(statement==
"goto" || statement==
"goto_w")
1362 assert(op.empty() && results.empty());
1365 INVARIANT(!ret,
"goto argument should be an integer");
1369 else if(statement==
"jsr" || statement==
"jsr_w")
1372 assert(op.empty() && results.size()==1);
1375 INVARIANT(!ret,
"jsr argument should be an integer");
1380 std::next(i_it)->address,
1384 else if(statement==
"ret")
1389 assert(op.empty() && results.empty());
1392 assert(!jsr_ret_targets.empty());
1393 for(
size_t idx=0, idxlim=jsr_ret_targets.size(); idx!=idxlim; ++idx)
1395 irep_idt number=std::to_string(jsr_ret_targets[idx]);
1399 c.move_to_operands(g);
1405 jsr_ret_targets[idx],
1409 branch.cond().add_source_location()=i_it->source_location;
1411 branch.add_source_location()=i_it->source_location;
1412 c.move_to_operands(
branch);
1416 else if(statement==
"iconst_m1")
1418 assert(results.size()==1);
1421 else if(statement==
patternt(
"?const"))
1423 assert(results.size()==1);
1425 const char type_char=statement[0];
1426 const bool is_double(
'd'==type_char);
1427 const bool is_float(
'f'==type_char);
1429 if(is_double || is_float)
1436 if(arg0.
type().
id()!=ID_floatbv)
1457 else if(statement==
patternt(
"?ipush"))
1461 arg0.
id()==ID_constant,
1462 "ipush argument expected to be constant");
1467 else if(statement==
patternt(
"if_?cmp??"))
1469 assert(op.size()==2 && results.empty());
1472 INVARIANT(!ret,
"if_?cmp?? argument should be an integer");
1481 const typet &lhs_type(lhs.type());
1482 if(lhs_type!=rhs.type())
1485 code_branch.
cond()=condition;
1493 else if(statement==
patternt(
"if??"))
1496 statement==
"ifeq"?ID_equal:
1497 statement==
"ifne"?ID_notequal:
1498 statement==
"iflt"?ID_lt:
1499 statement==
"ifge"?ID_ge:
1500 statement==
"ifgt"?ID_gt:
1501 statement==
"ifle"?ID_le:
1502 (assert(
false),
"");
1504 assert(op.size()==1 && results.empty());
1507 INVARIANT(!ret,
"if?? argument should be an integer");
1522 else if(statement==
patternt(
"ifnonnull"))
1524 assert(op.size()==1 && results.empty());
1527 INVARIANT(!ret,
"ifnonnull argument should be an integer");
1538 else if(statement==
patternt(
"ifnull"))
1540 assert(op.size()==1 && results.empty());
1543 INVARIANT(!ret,
"ifnull argument should be an integer");
1554 else if(statement==
"iinc")
1570 exprt arg1_int_type=arg1;
1579 else if(statement==
patternt(
"?xor"))
1581 assert(op.size()==2 && results.size()==1);
1584 else if(statement==
patternt(
"?or"))
1586 assert(op.size()==2 && results.size()==1);
1589 else if(statement==
patternt(
"?and"))
1591 assert(op.size()==2 && results.size()==1);
1594 else if(statement==
patternt(
"?shl"))
1596 assert(op.size()==2 && results.size()==1);
1599 else if(statement==
patternt(
"?shr"))
1601 assert(op.size()==2 && results.size()==1);
1604 else if(statement==
patternt(
"?ushr"))
1606 assert(op.size()==2 && results.size()==1);
1609 const std::size_t width=type.get_size_t(ID_width);
1613 if(lhs.
type()!=target)
1616 if(rhs.
type()!=target)
1620 if(results[0].type()!=op[0].type())
1621 results[0].make_typecast(op[0].type());
1623 else if(statement==
patternt(
"?add"))
1625 assert(op.size()==2 && results.size()==1);
1628 else if(statement==
patternt(
"?sub"))
1630 assert(op.size()==2 && results.size()==1);
1633 else if(statement==
patternt(
"?div"))
1635 assert(op.size()==2 && results.size()==1);
1638 else if(statement==
patternt(
"?mul"))
1640 assert(op.size()==2 && results.size()==1);
1643 else if(statement==
patternt(
"?neg"))
1645 assert(op.size()==1 && results.size()==1);
1648 else if(statement==
patternt(
"?rem"))
1650 assert(op.size()==2 && results.size()==1);
1651 if(statement==
"frem" || statement==
"drem")
1656 else if(statement==
patternt(
"?cmp"))
1658 assert(op.size()==2 && results.size()==1);
1680 else if(statement==
patternt(
"?cmp?"))
1682 assert(op.size()==2 && results.size()==1);
1688 const int nan_value(statement[4]==
'l' ? -1 : 1);
1713 else if(statement==
patternt(
"?cmpl"))
1715 assert(op.size()==2 && results.size()==1);
1718 else if(statement==
"dup")
1720 assert(op.size()==1 && results.size()==2);
1721 results[0]=results[1]=op[0];
1723 else if(statement==
"dup_x1")
1725 assert(op.size()==2 && results.size()==3);
1730 else if(statement==
"dup_x2")
1732 assert(op.size()==3 && results.size()==4);
1740 else if(statement==
"dup2")
1742 assert(!
stack.empty() && results.empty());
1749 results.insert(results.end(), op.begin(), op.end());
1750 results.insert(results.end(), op.begin(), op.end());
1752 else if(statement==
"dup2_x1")
1754 assert(!
stack.empty() && results.empty());
1761 results.insert(results.end(), op.begin()+1, op.end());
1762 results.insert(results.end(), op.begin(), op.end());
1764 else if(statement==
"dup2_x2")
1766 assert(!
stack.empty() && results.empty());
1773 assert(!
stack.empty());
1781 results.insert(results.end(), op.begin(), op.end());
1782 results.insert(results.end(), op2.begin(), op2.end());
1783 results.insert(results.end(), op.begin(), op.end());
1785 else if(statement==
"dconst")
1787 assert(op.empty() && results.size()==1);
1789 else if(statement==
"fconst")
1791 assert(op.empty() && results.size()==1);
1793 else if(statement==
"getfield")
1795 assert(op.size()==1 && results.size()==1);
1798 else if(statement==
"getstatic")
1800 assert(op.empty() && results.size()==1);
1802 const auto &field_name=arg0.
get_string(ID_component_name);
1803 symbol_expr.set_identifier(arg0.
get_string(ID_class)+
"."+field_name);
1812 if(field_name.find(
"$assertionsDisabled")!=std::string::npos)
1815 else if(statement==
"putfield")
1817 assert(op.size()==2 && results.empty());
1824 arg0.
get(ID_component_name));
1828 else if(statement==
"putstatic")
1830 assert(op.size()==1 && results.empty());
1832 const auto &field_name=arg0.
get_string(ID_component_name);
1833 symbol_expr.set_identifier(arg0.
get_string(ID_class)+
"."+field_name);
1843 "stack_static_field",
1847 symbol_expr.get_identifier());
1851 else if(statement==
patternt(
"?2?"))
1853 assert(op.size()==1 && results.size()==1);
1856 if(results[0].type()!=type)
1857 results[0].make_typecast(type);
1859 else if(statement==
"new")
1862 assert(op.empty() && results.size()==1);
1866 if(!i_it->source_location.get_line().empty())
1867 java_new_expr.add_source_location()=i_it->source_location;
1874 else if(statement==
"newarray" ||
1875 statement==
"anewarray")
1878 assert(op.size()==1 && results.size()==1);
1882 if(statement==
"newarray")
1888 else if(
id==ID_char)
1890 else if(
id==ID_float)
1892 else if(
id==ID_double)
1894 else if(
id==ID_byte)
1896 else if(
id==ID_short)
1900 else if(
id==ID_long)
1914 if(!i_it->source_location.get_line().empty())
1939 else if(statement==
"multianewarray")
1945 INVARIANT(!ret,
"multianewarray argument should be an integer");
1949 assert(results.size()==1);
1955 java_new_array.operands()=op;
1957 if(!i_it->source_location.get_line().empty())
1958 java_new_array.add_source_location()=i_it->source_location;
1983 else if(statement==
"arraylength")
1985 assert(op.size()==1 && results.size()==1);
1991 assert(pointer.type().subtype().id()==ID_symbol);
1997 else if(statement==
"tableswitch" ||
1998 statement==
"lookupswitch")
2000 assert(op.size()==1 && results.empty());
2005 code_switch.value()=op[0];
2010 for(instructiont::argst::const_iterator
2011 a_it=i_it->args.begin();
2012 a_it!=i_it->args.end();
2013 a_it++, is_label=!is_label)
2026 if(a_it==i_it->args.begin())
2030 instructiont::argst::const_iterator prev=a_it;
2038 code_block.
add(code_case);
2042 code_switch.body()=code_block;
2045 else if(statement==
"pop" || statement==
"pop2")
2054 if(statement==
"pop2" &&
2058 else if(statement==
"instanceof")
2060 assert(op.size()==1 && results.size()==1);
2065 else if(statement==
"monitorenter")
2079 else if(statement==
"monitorexit")
2100 std::vector<irep_idt> exception_ids;
2101 std::vector<irep_idt> handler_labels;
2109 std::size_t end_pc=0;
2125 exception_ids.push_back(
2130 handler_labels.push_back(
2138 if(!exception_ids.empty())
2143 result.get_sub().resize(exception_ids.size());
2144 for(
size_t i=0; i<exception_ids.size(); ++i)
2145 result.get_sub()[i].id(exception_ids[i]);
2146 catch_push_expr.
set(ID_exception_list,
result);
2149 irept labels(ID_label);
2150 labels.
get_sub().resize(handler_labels.size());
2151 for(
size_t i=0; i<handler_labels.size(); ++i)
2152 labels.
get_sub()[i].id(handler_labels[i]);
2153 catch_push_expr.
set(ID_label, labels);
2169 exception_ids.clear();
2170 handler_labels.clear();
2177 bool first_handler=
false;
2182 if(cur_pc<exception_row.end_pc &&
2183 !working_set.empty() &&
2184 *working_set.begin()==exception_row.end_pc)
2188 if(exception_row.start_pc!=start_pc || !first_handler)
2194 start_pc=exception_row.start_pc;
2208 if(!i_it->source_location.get_line().empty())
2213 a_it->second.done=
true;
2214 for(
const unsigned address : a_it->second.successors)
2216 address_mapt::iterator a_it2=address_map.find(address);
2217 assert(a_it2!=address_map.end());
2224 if(address==exception_row.handler_pc)
2231 if(!
stack.empty() && a_it2->second.predecessors.size()>1)
2238 if(a_it2->second.stack.empty())
2240 for(stackt::iterator s_it=
stack.begin();
2253 assert(a_it2->second.stack.size()==
stack.size());
2254 stackt::const_iterator os_it=a_it2->second.stack.begin();
2255 for(
auto &expr :
stack)
2257 assert(
has_prefix(os_it->get_string(ID_C_base_name),
"$stack"));
2276 if(last_statement.get_statement()==ID_goto)
2281 last_statement.operands().begin(),
2291 a_it2->second.stack=
stack;
2301 new_symbol.
name=var.get_identifier();
2302 new_symbol.
type=var.type();
2303 new_symbol.
base_name=var.get(ID_C_base_name);
2305 new_symbol.
mode=ID_java;
2322 bool start_new_block=
true;
2323 bool has_seen_previous_address=
false;
2324 unsigned previous_address=0;
2325 for(
const auto &address_pair : address_map)
2327 const unsigned address=address_pair.first;
2328 assert(address_pair.first==address_pair.second.source->address);
2329 const codet &c=address_pair.second.code;
2332 if(!start_new_block)
2333 start_new_block=targets.find(address)!=targets.end();
2336 if(!start_new_block)
2337 start_new_block=address_pair.second.predecessors.size()>1;
2339 if(!start_new_block && has_seen_previous_address)
2342 if(exception_row.start_pc==previous_address)
2344 start_new_block=
true;
2356 "Block addresses should be unique and increasing");
2364 add_to_block.
add(c);
2366 start_new_block=address_pair.second.successors.size()>1;
2368 previous_address=address;
2369 has_seen_previous_address=
true;
2373 std::map<irep_idt, variablet> temporary_variable_live_ranges;
2374 for(
const auto &aentry : address_map)
2378 temporary_variable_live_ranges);
2380 std::vector<const variablet*> vars_to_process;
2382 for(
const auto &v : vlist)
2383 vars_to_process.push_back(&v);
2386 vars_to_process.push_back(
2387 &temporary_variable_live_ranges.at(v.get_identifier()));
2390 vars_to_process.push_back(
2391 &temporary_variable_live_ranges.at(v.get_identifier()));
2393 for(
const auto vp : vars_to_process)
2407 v.start_pc+v.length,
2408 std::numeric_limits<unsigned>::max(),
2411 for(
const auto vp : vars_to_process)
2417 if(v.symbol_expr.get_identifier().empty())
2423 v.start_pc+v.length,
2424 std::numeric_limits<unsigned>::max());
2426 block.operands().insert(block.operands().begin(), d);
2429 for(
auto &block : root_block.
operands())
2440 size_t max_array_length,
2457 const std::string &tmp_var_prefix,
2458 const typet &tmp_var_type,
2463 for(
auto &stack_entry :
stack)
2466 while(stack_entry.id()==ID_typecast)
2472 stack_entry.id()==ID_symbol)
2481 stack_entry.id()==ID_dereference)
2486 stack_entry.id()==ID_member)
2490 if(entry_id==identifier)
2498 const std::string &tmp_var_prefix,
2499 const typet &tmp_var_type,
2503 const exprt tmp_var=
2506 stack_entry=tmp_var;
const irept & get_nil_irep()
bool add_needed_class(const irep_idt &)
Notes class class_symbol_name will be instantiated, or a static field belonging to it will be accesse...
const irep_idt & get_statement() const
A side effect that pushes/pops a catch handler.
const irep_idt & get_name() const
The type of an expression.
irep_idt name
The unique identifier.
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast a generic exprt to a typecast_exprt.
const codet & then_case() const
void add_needed_method(const irep_idt &)
Notes method_symbol_name is referenced from some reachable function, and should therefore be elaborat...
void java_bytecode_convert_method_lazy(const symbolt &class_symbol, const irep_idt &method_identifier, const java_bytecode_parse_treet::methodt &m, symbol_tablet &symbol_table)
This creates a method symbol in the symtab, but doesn't actually perform method conversion just yet...
Fixed-width bit-vector with unsigned binary interpretation.
void set_function(const irep_idt &function)
symbolt & lookup(const irep_idt &identifier)
Find a symbol in the symbol table.
void pop_residue(std::size_t n)
removes minimum(n, stack.size()) elements from the stack
Linking: Zero Initialization.
JAVA Bytecode Language Conversion.
A ‘switch’ instruction.
A generic base class for relations, i.e., binary predicates.
const std::string & id2string(const irep_idt &d)
void convert(const symbolt &class_symbol, const methodt &)
pointer_typet pointer_type(const typet &subtype)
void set_label(const irep_idt &label)
Symbol table entry of function parameterThis is a symbol generated as part of type checking...
const mp_integer string2integer(const std::string &n, unsigned base)
const std::string integer2string(const mp_integer &n, unsigned base)
typet java_boolean_type()
static ieee_floatt NaN(const ieee_float_spect &_spec)
void set_property_class(const irep_idt &property_class)
const exprt variable(const exprt &arg, char type_char, size_t address, variable_cast_argumentt do_cast)
static bool operator==(const irep_idt &what, const patternt &pattern)
constant_exprt to_expr() const
Fixed-width bit-vector with IEEE floating-point interpretation.
static void gather_symbol_live_ranges(unsigned pc, const exprt &e, std::map< irep_idt, java_bytecode_convert_methodt::variablet > &result)
methodt::instructionst instructionst
irep_idt mode
Language mode.
const exprt & cond() const
source_locationt source_location
void from_expr(const constant_exprt &expr)
safe_pointer< ci_lazy_methodst > lazy_methods
code_blockt & get_or_create_block_for_pcrange(block_tree_nodet &tree, code_blockt &this_block, unsigned address_start, unsigned address_limit, unsigned next_block_start_address, const address_mapt &amap, bool allow_merge=true)
As above, but this version can additionally create a new branch in the block_tree-node and code_block...
reference_typet java_reference_type(const typet &subtype)
void set_base_name(const irep_idt &base_name)
void set_comment(const irep_idt &comment)
void set_name(const irep_idt &name)
irep_idt label(const irep_idt &address)
exception_tablet exception_table
void copy_to_operands(const exprt &expr)
const irep_idt & get_identifier() const
const member_exprt & to_member_expr(const exprt &expr)
Cast a generic exprt to a member_exprt.
void move_to_operands(exprt &expr)
struct bytecode_infot const bytecode_info[]
The null pointer constant.
std::vector< parametert > parameterst
exprt value
Initial value of symbol.
void setup_local_variables(const methodt &m, const address_mapt &amap)
See find_initialisers_for_slot above for more detail.
The trinary if-then-else operator.
character_refine_preprocesst character_preprocess
A ‘goto’ instruction.
irep_idt pretty_name
Language-specific display name.
unsignedbv_typet size_type()
bool operator==(const irep_idt &what) const
Symbol table entry.This is a symbol in the symbol table, stored in an object of type symbol_tablet...
A constant literal expression.
#define CHECK_RETURN(CONDITION)
static mstreamt & eom(mstreamt &m)
std::map< unsigned, converted_instructiont > address_mapt
reference_typet java_array_type(const char subtype)
expanding_vectort< variablest > variables
A side effect that throws an exception.
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a generic typet to a floatbv_typet.
#define INVARIANT(CONDITION, REASON)
const exprt & case_op() const
code_blockt & get_block_for_pcrange(block_tree_nodet &tree, code_blockt &this_block, unsigned address_start, unsigned address_limit, unsigned next_block_start_address)
'tree' describes a tree of code_blockt objects; this_block is the corresponding block (thus they are ...
static irep_idt strip_java_namespace_prefix(const irep_idt to_strip)
void set_base_name(const irep_idt &name)
static ieee_float_spect double_precision()
Extract member of struct or union.
void java_bytecode_convert_method(const symbolt &class_symbol, const java_bytecode_parse_treet::methodt &method, symbol_tablet &symbol_table, message_handlert &message_handler, size_t max_array_length, safe_pointer< ci_lazy_methodst > lazy_methods, const character_refine_preprocesst &character_refine)
const irep_idt & get_base_name() const
const char * as_string(coverage_criteriont c)
instructionst instructions
const irep_idt & id() const
bool is_constructor(const class_typet::methodt &method)
void add(const codet &code)
class symbol_exprt symbol_expr() const
produces a symbol_exprt for a symbol
typet java_type_from_string(const std::string &src)
class code_blockt & make_block()
exprt zero_initializer(const typet &type, const source_locationt &source_location, const namespacet &ns, message_handlert &message_handler)
const symbol_typet & to_symbol_type(const typet &type)
Cast a generic typet to a symbol_typet.
static irep_idt get_if_cmp_operator(const irep_idt &stmt)
division (integer and real)
A reference into the symbol table.
A declaration of a local variable.
Operator to dereference a pointer.
typet java_type_from_char(char t)
const code_gotot & to_code_goto(const codet &code)
API to expression classes.
const irep_idt & get(const irep_namet &name) const
Internally generated symbol table entryThis is a symbol generated as part of translation to or modifi...
codet replace_character_call(const code_function_callt &call) const
replace function calls to functions of the Character by an affectation if possible, returns the same code otherwise.
static ieee_float_spect single_precision()
A label for branch targets.
#define PRECONDITION(CONDITION)
static unsigned get_bytecode_type_width(const typet &ty)
Base class for tree-like data structures with sharing.
#define forall_operands(it, expr)
const size_t max_array_length
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
codet & find_last_statement()
Operator to return the address of an object.
The unary minus expression.
The boolean constant false.
std::list< symbol_exprt > tmp_vars
exprt::operandst pop(std::size_t n)
std::set< symbol_exprt > used_local_names
std::vector< exprt > operandst
bool has_prefix(const std::string &s, const std::string &prefix)
std::vector< block_tree_nodet > branch
void branch(symbol_tablet &symbol_table, goto_functionst &goto_functions, const irep_idt &id)
const pointer_typet & to_pointer_type(const typet &type)
Cast a generic typet to a pointer_typet.
codet convert_instructions(const methodt &, const code_typet &)
static size_t count_slots(const size_t value, const code_typet::parametert ¶m)
typet type
Type of symbol.
source_locationt location
Source code location of definition of symbol.
message_handlert & get_message_handler()
std::vector< variablet > variablest
const bytecode_infot & get_bytecode_info(const irep_idt &statement)
static size_t get_variable_slots(const code_typet::parametert ¶m)
void create_stack_tmp_var(const std::string &, const typet &, code_blockt &, exprt &)
actually create a temporary variable to hold the value of a stack entry
symbol_exprt tmp_variable(const std::string &prefix, const typet &type)
Base class for all expressions.
const parameterst & parameters() const
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast a generic exprt to a symbol_exprt.
irep_idt base_name
Base (non-scoped) name.
symbol_tablet & symbol_table
const variablet & find_variable_for_slot(size_t address, variablest &var_list)
See above.
irep_idt get_component_name() const
void save_stack_entries(const std::string &, const typet &, code_blockt &, const bytecode_write_typet, const irep_idt &)
create temporary variables if a write instruction can have undesired side- effects ...
const std::string & get_string(const irep_namet &name) const
const code_typet & to_code_type(const typet &type)
Cast a generic typet to a code_typet.
void from_integer(const mp_integer &i)
const size_t SLOTS_PER_INTEGER(1u)
void push(const exprt::operandst &o)
unsigned int get_unsigned_int(const irep_namet &name) const
source_locationt & add_source_location()
const codet & to_code(const exprt &expr)
typet java_bytecode_promotion(const typet &type)
Java does not support byte/short return types. These are always promoted.
Expression to hold a symbol (variable)
const code_blockt & to_code_block(const codet &code)
local_variable_tablet local_variable_table
A statement in a programming language.
A generic base class for expressions that are predicates, i.e., boolean-typed, and that take exactly ...
const size_t INTEGER_WIDTH(64u)
std::size_t integer2size_t(const mp_integer &n)
const constant_exprt & to_constant_expr(const exprt &expr)
Cast a generic exprt to a constant_exprt.
const code_labelt & to_code_label(const codet &code)
JAVA Bytecode Language Conversion.
const typet & subtype() const
#define DATA_INVARIANT(CONDITION, REASON)
An expression containing a side effect.
Compute dominators for CFG of goto_function.
static void replace_goto_target(codet &repl, const irep_idt &old_label, const irep_idt &new_label)
Find all goto statements in 'repl' that target 'old_label' and redirect them to 'new_label'.
void make_typecast(const typet &_type)
const irept & find(const irep_namet &name) const
static member_exprt to_member(const exprt &pointer, const exprt &fieldref)
std::vector< unsigned > branch_addresses
const typet & return_type() const
char java_char_from_type(const typet &type)
void set(const irep_namet &name, const irep_idt &value)
codet get_array_bounds_check(const exprt &arraystruct, const exprt &idx, const source_locationt &original_sloc)
static block_tree_nodet get_leaf()
IEEE-floating-point equality.