void equality_domaint::project_on_vars( valuet &value, const var_sett &vars, exprt &result) { #if 0 if(templ.size()==0) return domaint::project_on_vars(value, vars, result); #endif equ_valuet &v=static_cast<equ_valuet &>(value); exprt::operandst c; for(unsigned index=0; index<templ.size(); index++) { const var_pairt &vv=templ[index].var_pair; #if 0 std::cout << vv.second << std::endl; #endif if(vars.find(vv.first)==vars.end() || (vars.find(vv.second)==vars.end() && !(vv.second.id()==ID_constant && to_constant_expr(vv.second).get_value()=="NULL"))) continue; if(v.equs.same_set(vv.first, vv.second)) { if(templ[index].kind==LOOP) c.push_back( implies_exprt( templ[index].pre_guard, equal_exprt(vv.first, vv.second))); else c.push_back(equal_exprt(vv.first, vv.second)); } } for(index_sett::const_iterator it=v.disequs.begin(); it!=v.disequs.end(); it++) { const var_pairt &vv=templ[*it].var_pair; if(vars.find(vv.first)==vars.end() || (vars.find(vv.second)==vars.end() && !(vv.second.id()==ID_constant && to_constant_expr(vv.second).get_value()=="NULL"))) continue; if(templ[*it].kind==LOOP) c.push_back( implies_exprt( templ[*it].pre_guard, notequal_exprt(vv.first, vv.second))); else c.push_back(notequal_exprt(vv.first, vv.second)); } result=conjunction(c); }
bool simplify_exprt::simplify_ieee_float_relation(exprt &expr) { assert(expr.id()==ID_ieee_float_equal || expr.id()==ID_ieee_float_notequal); exprt::operandst &operands=expr.operands(); if(expr.type().id()!=ID_bool) return true; if(operands.size()!=2) return true; // types must match if(expr.op0().type()!=expr.op1().type()) return true; if(expr.op0().type().id()!=ID_floatbv) return true; // first see if we compare to a constant if(expr.op0().is_constant() && expr.op1().is_constant()) { ieee_floatt f0(to_constant_expr(expr.op0())); ieee_floatt f1(to_constant_expr(expr.op1())); if(expr.id()==ID_ieee_float_notequal) expr.make_bool(f0.ieee_not_equal(f1)); else if(expr.id()==ID_ieee_float_equal) expr.make_bool(f0.ieee_equal(f1)); else assert(false); return false; } if(expr.op0()==expr.op1()) { // x!=x is the same as saying isnan(op) exprt isnan(ID_isnan, bool_typet()); isnan.copy_to_operands(expr.op0()); if(expr.id()==ID_ieee_float_notequal) { } else if(expr.id()==ID_ieee_float_equal) isnan.make_not(); else assert(false); expr.swap(isnan); return false; } return true; }
std::string expr2javat::convert( const exprt &src, unsigned &precedence) { if(src.id()=="java-this") return convert_java_this(src, precedence=15); if(src.id()=="java_instanceof") return convert_java_instanceof(src, precedence=15); else if(src.id()==ID_side_effect && (src.get(ID_statement)==ID_java_new || src.get(ID_statement)==ID_java_new_array)) return convert_java_new(src, precedence=15); else if(src.id()==ID_side_effect && src.get(ID_statement)==ID_throw) return convert_function(src, "throw", precedence=16); else if(src.is_constant() && to_constant_expr(src).get_value()==ID_nullptr) return "nullptr"; else if(src.id()==ID_unassigned) return "?"; else if(src.id()=="pod_constructor") return "pod_constructor"; else if(src.id()==ID_virtual_function) return convert_function(src, "VIRTUAL_FUNCTION", precedence=16); else if(src.id()==ID_java_string_literal) return '"'+id2string(src.get(ID_value))+'"'; // Todo: add escaping as needed else return expr2ct::convert(src, precedence); }
bool simplify_exprt::simplify_sign(exprt &expr) { if(expr.operands().size()!=1) return true; if(expr.op0().is_constant()) { const typet &type=ns.follow(expr.op0().type()); if(type.id()==ID_floatbv) { ieee_floatt value(to_constant_expr(expr.op0())); expr.make_bool(value.get_sign()); return false; } else if(type.id()==ID_signedbv || type.id()==ID_unsignedbv) { mp_integer value; if(!to_integer(expr.op0(), value)) { expr.make_bool(value>=0); return false; } } } return true; }
static bool is_dereference_integer_object( const exprt &expr, mp_integer &address) { if(expr.id()==ID_dereference && expr.operands().size()==1) { if(expr.op0().id()==ID_typecast && expr.op0().operands().size()==1 && expr.op0().op0().is_constant() && !to_integer(expr.op0().op0(), address)) return true; if(expr.op0().is_constant()) { if(to_constant_expr(expr.op0()).get_value()==ID_NULL && config.ansi_c.NULL_is_zero) // NULL { address=0; return true; } else if(!to_integer(expr.op0(), address)) return true; } } return false; }
bool remove_const_function_pointerst::try_resolve_index_value( const exprt &expr, mp_integer &out_array_index) { expressionst index_value_expressions; bool is_const=false; bool resolved=try_resolve_expression(expr, index_value_expressions, is_const); if(resolved) { if(index_value_expressions.size()==1 && index_value_expressions.front().id()==ID_constant) { const constant_exprt &constant_expr= to_constant_expr(index_value_expressions.front()); mp_integer array_index; bool errors=to_integer(constant_expr, array_index); if(!errors) { out_array_index=array_index; } return !errors; } else { return false; } } else { return false; } }
exprt dereferencet::dereference_rec( const exprt &address, const exprt &offset, const typet &type) { if(address.id()==ID_address_of) { const address_of_exprt &address_of_expr=to_address_of_expr(address); const exprt &object=address_of_expr.object(); return read_object(object, offset, type); } else if(address.id()==ID_typecast) { const typecast_exprt &typecast_expr=to_typecast_expr(address); return dereference_typecast(typecast_expr, offset, type); } else if(address.id()==ID_plus) { // pointer arithmetic if(address.operands().size()<2) throw "plus with less than two operands"; return dereference_plus(address, offset, type); } else if(address.id()==ID_if) { const if_exprt &if_expr=to_if_expr(address); return dereference_if(if_expr, offset, type); } else if(address.id()==ID_constant) { const typet result_type=ns.follow(address.type()).subtype(); // pointer-typed constant if(to_constant_expr(address).get_value()==ID_NULL) // NULL { // we turn this into (type *)0 exprt zero=gen_zero(index_type()); return dereference_rec( typecast_exprt(zero, address.type()), offset, type); } else throw "dereferencet: unexpected pointer constant "+address.pretty(); } else { throw "failed to dereference `"+address.id_string()+"'"; } }
static void build_ssa_identifier_rec( const exprt &expr, const irep_idt &l0, const irep_idt &l1, const irep_idt &l2, std::ostream &os, std::ostream &l1_object_os) { if(expr.id()==ID_member) { const member_exprt &member=to_member_expr(expr); build_ssa_identifier_rec(member.struct_op(), l0, l1, l2, os, l1_object_os); os << '.' << member.get_component_name(); } else if(expr.id()==ID_index) { const index_exprt &index=to_index_expr(expr); build_ssa_identifier_rec(index.array(), l0, l1, l2, os, l1_object_os); mp_integer idx; if(to_integer(to_constant_expr(index.index()), idx)) assert(false); os << '[' << idx << ']'; } else if(expr.id()==ID_symbol) { auto symid=to_symbol_expr(expr).get_identifier(); os << symid; l1_object_os << symid; if(!l0.empty()) { os << '!' << l0; l1_object_os << '!' << l0; } if(!l1.empty()) { os << '@' << l1; l1_object_os << '@' << l1; } if(!l2.empty()) os << '#' << l2; } else assert(false); }
bool simplify_exprt::simplify_isnormal(exprt &expr) { if(expr.operands().size()!=1) return true; if(expr.op0().is_constant()) { ieee_floatt value(to_constant_expr(expr.op0())); expr.make_bool(value.is_normal()); return false; } return true; }
bool simplify_exprt::simplify_isinf(exprt &expr) { if(expr.operands().size()!=1) return true; if(ns.follow(expr.op0().type()).id()!=ID_floatbv) return true; if(expr.op0().is_constant()) { ieee_floatt value(to_constant_expr(expr.op0())); expr.make_bool(value.is_infinity()); return false; } return true; }
bool simplify_exprt::simplify_abs(exprt &expr) { if(expr.operands().size()!=1) return true; if(expr.op0().is_constant()) { const typet &type=ns.follow(expr.op0().type()); if(type.id()==ID_floatbv) { ieee_floatt value(to_constant_expr(expr.op0())); value.set_sign(false); expr=value.to_expr(); return false; } else if(type.id()==ID_signedbv || type.id()==ID_unsignedbv) { mp_integer value; if(!to_integer(expr.op0(), value)) { if(value>=0) { expr=expr.op0(); return false; } else { value.negate(); expr=from_integer(value, type); return false; } } } } return true; }
std::string expr2javat::convert( const exprt &src, unsigned &precedence) { if(src.id()=="java-this") return convert_java_this(src, precedence=15); else if(src.id()==ID_side_effect && (src.get(ID_statement)==ID_java_new || src.get(ID_statement)==ID_java_new_array)) return convert_java_new(src, precedence=15); else if(src.id()==ID_side_effect && src.get(ID_statement)==ID_throw) return convert_function(src, "throw", precedence=16); else if(src.is_constant() && to_constant_expr(src).get_value()==ID_nullptr) return "nullptr"; else if(src.id()==ID_unassigned) return "?"; else if(src.id()=="pod_constructor") return "pod_constructor"; else return expr2ct::convert(src, precedence); }
static unsigned from_ns( const namespacet &ns, const std::string &what) { const irep_idt id=CPROVER_PREFIX "architecture_"+what; const symbolt *symbol; if(ns.lookup(id, symbol)) throw "failed to find "+id2string(id); exprt tmp=symbol->value; simplify(tmp, ns); if(tmp.id()!=ID_constant) throw "symbol table configuration entry `"+id2string(id)+"' is not a constant"; mp_integer int_value; if(to_integer(to_constant_expr(tmp), int_value)) throw "failed to convert symbol table configuration entry `"+id2string(id)+"'"; return integer2unsigned(int_value); }
bool polynomial_acceleratort::fit_const(goto_programt::instructionst &body, exprt &target, polynomialt &poly) { return false; scratch_programt program(symbol_table); program.append(body); program.add_instruction(ASSERT)->guard = equal_exprt(target, not_exprt(target)); try { if (program.check_sat(false)) { #ifdef DEBUG std::cout << "Fitting constant, eval'd to: " << expr2c(program.eval(target), ns) << std::endl; #endif constant_exprt val = to_constant_expr(program.eval(target)); mp_integer mp = binary2integer(val.get_value().c_str(), true); monomialt mon; monomialt::termt term; term.var = from_integer(1, target.type()); term.exp = 1; mon.terms.push_back(term); mon.coeff = mp.to_long(); poly.monomials.push_back(mon); return true; } } catch (std::string s) { std::cout << "Error in fitting polynomial SAT check: " << s << std::endl; } catch (const char *s) { std::cout << "Error in fitting polynomial SAT check: " << s << std::endl; } return false; }
bool simplify_exprt::simplify_floatbv_op(exprt &expr) { const typet &type=ns.follow(expr.type()); if(type.id()!=ID_floatbv) return true; assert(expr.operands().size()==3); exprt op0=expr.op0(); exprt op1=expr.op1(); exprt op2=expr.op2(); // rounding mode assert(ns.follow(op0.type())==type); assert(ns.follow(op1.type())==type); // Remember that floating-point addition is _NOT_ associative. // Thus, we don't re-sort the operands. // We only merge constants! if(op0.is_constant() && op1.is_constant() && op2.is_constant()) { ieee_floatt v0(to_constant_expr(op0)); ieee_floatt v1(to_constant_expr(op1)); mp_integer rounding_mode; if(!to_integer(op2, rounding_mode)) { v0.rounding_mode=(ieee_floatt::rounding_modet)integer2size_t(rounding_mode); v1.rounding_mode=v0.rounding_mode; ieee_floatt result=v0; if(expr.id()==ID_floatbv_plus) result+=v1; else if(expr.id()==ID_floatbv_minus) result-=v1; else if(expr.id()==ID_floatbv_mult) result*=v1; else if(expr.id()==ID_floatbv_div) result/=v1; else assert(false); expr=result.to_expr(); return false; } } // division by one? Exact for all rounding modes. if (expr.id()==ID_floatbv_div && op1.is_constant() && op1.is_one()) { exprt tmp; tmp.swap(op0); expr.swap(tmp); return false; } return true; }
bool simplify_exprt::simplify_floatbv_typecast(exprt &expr) { // These casts usually reduce precision, and thus, usually round. assert(expr.operands().size()==2); const typet &dest_type=ns.follow(expr.type()); const typet &src_type=ns.follow(expr.op0().type()); // eliminate redundant casts if(dest_type==src_type) { expr=expr.op0(); return false; } exprt op0=expr.op0(); exprt op1=expr.op1(); // rounding mode // We can soundly re-write (float)((double)x op (double)y) // to x op y. True for any rounding mode! #if 0 if(op0.id()==ID_floatbv_div || op0.id()==ID_floatbv_mult || op0.id()==ID_floatbv_plus || op0.id()==ID_floatbv_minus) { if(op0.operands().size()==3 && op0.op0().id()==ID_typecast && op0.op1().id()==ID_typecast && op0.op0().operands().size()==1 && op0.op1().operands().size()==1 && ns.follow(op0.op0().type())==dest_type && ns.follow(op0.op1().type())==dest_type) { exprt result(op0.id(), expr.type()); result.operands().resize(3); result.op0()=op0.op0().op0(); result.op1()=op0.op1().op0(); result.op2()=op1; simplify_node(result); expr.swap(result); return false; } } #endif // constant folding if(op0.is_constant() && op1.is_constant()) { mp_integer rounding_mode; if(!to_integer(op1, rounding_mode)) { if(src_type.id()==ID_floatbv) { if(dest_type.id()==ID_floatbv) // float to float { ieee_floatt result(to_constant_expr(op0)); result.rounding_mode=(ieee_floatt::rounding_modet)integer2size_t(rounding_mode); result.change_spec(to_floatbv_type(dest_type)); expr=result.to_expr(); return false; } else if(dest_type.id()==ID_signedbv || dest_type.id()==ID_unsignedbv) { if(rounding_mode==ieee_floatt::ROUND_TO_ZERO) { ieee_floatt result(to_constant_expr(op0)); result.rounding_mode=(ieee_floatt::rounding_modet)integer2size_t(rounding_mode); mp_integer value=result.to_integer(); expr=from_integer(value, dest_type); return false; } } } else if(src_type.id()==ID_signedbv || src_type.id()==ID_unsignedbv) { mp_integer value; if(!to_integer(op0, value)) { if(dest_type.id()==ID_floatbv) // int to float { ieee_floatt result; result.rounding_mode=(ieee_floatt::rounding_modet)integer2size_t(rounding_mode); result.spec=to_floatbv_type(dest_type); result.from_integer(value); expr=result.to_expr(); return false; } } } } } #if 0 // (T)(a?b:c) --> a?(T)b:(T)c if(expr.op0().id()==ID_if && expr.op0().operands().size()==3) { exprt tmp_op1=binary_exprt(expr.op0().op1(), ID_floatbv_typecast, expr.op1(), dest_type); exprt tmp_op2=binary_exprt(expr.op0().op2(), ID_floatbv_typecast, expr.op1(), dest_type); simplify_floatbv_typecast(tmp_op1); simplify_floatbv_typecast(tmp_op2); expr=if_exprt(expr.op0().op0(), tmp_op1, tmp_op2, dest_type); simplify_if(expr); return false; } #endif return true; }
void interpretert::evaluate( const exprt &expr, std::vector<mp_integer> &dest) const { if(expr.id()==ID_constant) { if(expr.type().id()==ID_struct) { } else if(expr.type().id()==ID_floatbv) { ieee_floatt f; f.from_expr(to_constant_expr(expr)); dest.push_back(f.pack()); return; } else if(expr.type().id()==ID_fixedbv) { fixedbvt f; f.from_expr(to_constant_expr(expr)); dest.push_back(f.get_value()); return; } else if(expr.type().id()==ID_bool) { dest.push_back(expr.is_true()); return; } else { mp_integer i; if(!to_integer(expr, i)) { dest.push_back(i); return; } } } else if(expr.id()==ID_struct) { dest.reserve(get_size(expr.type())); bool error=false; forall_operands(it, expr) { if(it->type().id()==ID_code) continue; unsigned sub_size=get_size(it->type()); if(sub_size==0) continue; std::vector<mp_integer> tmp; evaluate(*it, tmp); if(tmp.size()==sub_size) { for(unsigned i=0; i<sub_size; i++) dest.push_back(tmp[i]); } else error=true; } if(!error) return; dest.clear(); }
unsigned int dynamic_object_exprt::get_instance() const { return std::stoul(id2string(to_constant_expr(op0()).get_value())); }
void interval_domaint::assume_rec( const exprt &lhs, irep_idt id, const exprt &rhs) { if(lhs.id()==ID_typecast) return assume_rec(to_typecast_expr(lhs).op(), id, rhs); if(rhs.id()==ID_typecast) return assume_rec(lhs, id, to_typecast_expr(rhs).op()); if(id==ID_equal) { assume_rec(lhs, ID_ge, rhs); assume_rec(lhs, ID_le, rhs); return; } if(id==ID_ge) return assume_rec(rhs, ID_le, lhs); if(id==ID_gt) return assume_rec(rhs, ID_lt, lhs); // we now have lhs < rhs or // lhs <= rhs assert(id==ID_lt || id==ID_le); #ifdef DEBUG std::cout << "assume_rec: " << from_expr(lhs) << " " << id << " " << from_expr(rhs) << "\n"; #endif if(lhs.id()==ID_symbol && rhs.id()==ID_constant) { irep_idt lhs_identifier=to_symbol_expr(lhs).get_identifier(); if(is_int(lhs.type()) && is_int(rhs.type())) { mp_integer tmp; to_integer(rhs, tmp); if(id==ID_lt) --tmp; int_map[lhs_identifier].make_le_than(tmp); } else if(is_float(lhs.type()) && is_float(rhs.type())) { ieee_floatt tmp(to_constant_expr(rhs)); if(id==ID_lt) tmp.decrement(); float_map[lhs_identifier].make_le_than(tmp); } } else if(lhs.id()==ID_constant && rhs.id()==ID_symbol) { irep_idt rhs_identifier=to_symbol_expr(rhs).get_identifier(); if(is_int(lhs.type()) && is_int(rhs.type())) { mp_integer tmp; to_integer(lhs, tmp); if(id==ID_lt) ++tmp; int_map[rhs_identifier].make_ge_than(tmp); } else if(is_float(lhs.type()) && is_float(rhs.type())) { ieee_floatt tmp(to_constant_expr(lhs)); if(id==ID_lt) tmp.increment(); float_map[rhs_identifier].make_ge_than(tmp); } } else if(lhs.id()==ID_symbol && rhs.id()==ID_symbol) { irep_idt lhs_identifier=to_symbol_expr(lhs).get_identifier(); irep_idt rhs_identifier=to_symbol_expr(rhs).get_identifier(); if(is_int(lhs.type()) && is_int(rhs.type())) { integer_intervalt &lhs_i=int_map[lhs_identifier]; integer_intervalt &rhs_i=int_map[rhs_identifier]; lhs_i.meet(rhs_i); rhs_i=lhs_i; } else if(is_float(lhs.type()) && is_float(rhs.type())) { ieee_float_intervalt &lhs_i=float_map[lhs_identifier]; ieee_float_intervalt &rhs_i=float_map[rhs_identifier]; lhs_i.meet(rhs_i); rhs_i=lhs_i; } } }
codet java_bytecode_convertt::convert_instructions( const instructionst &instructions, const code_typet &method_type) { // Run a worklist algorithm, assuming that the bytecode has not // been tampered with. See "Leroy, X. (2003). Java bytecode // verification: algorithms and formalizations. Journal of Automated // Reasoning, 30(3-4), 235-269." for a more complete treatment. // first pass: get targets and map addresses to instructions struct converted_instructiont { converted_instructiont( const instructionst::const_iterator &it, const codet &_code):source(it), code(_code), done(false) { } instructionst::const_iterator source; std::list<unsigned> successors; std::set<unsigned> predecessors; codet code; stackt stack; bool done; }; typedef std::map<unsigned, converted_instructiont> address_mapt; address_mapt address_map; std::set<unsigned> targets; for(instructionst::const_iterator i_it=instructions.begin(); i_it!=instructions.end(); i_it++) { std::pair<address_mapt::iterator, bool> a_entry= address_map.insert(std::make_pair( i_it->address, converted_instructiont(i_it, code_skipt()))); assert(a_entry.second); // addresses are strictly increasing, hence we must have inserted // a new maximal key assert(a_entry.first==--address_map.end()); if(i_it->statement!="goto" && i_it->statement!="return" && !(i_it->statement==patternt("?return")) && i_it->statement!="athrow") { instructionst::const_iterator next=i_it; if(++next!=instructions.end()) a_entry.first->second.successors.push_back(next->address); } if(i_it->statement=="goto" || i_it->statement==patternt("if_?cmp??") || i_it->statement==patternt("if??") || i_it->statement=="ifnonnull" || i_it->statement=="ifnull") { assert(!i_it->args.empty()); const unsigned target=safe_string2unsigned( id2string(to_constant_expr(i_it->args[0]).get_value())); targets.insert(target); a_entry.first->second.successors.push_back(target); } else if(i_it->statement=="tableswitch" || i_it->statement=="lookupswitch") { bool is_label=true; for(instructiont::argst::const_iterator a_it=i_it->args.begin(); a_it!=i_it->args.end(); a_it++, is_label=!is_label) { if(is_label) { const unsigned target=safe_string2unsigned( id2string(to_constant_expr(*a_it).get_value())); targets.insert(target); a_entry.first->second.successors.push_back(target); } } } } for(address_mapt::iterator it=address_map.begin(); it!=address_map.end(); ++it) { for(unsigned s : it->second.successors) { address_mapt::iterator a_it=address_map.find(s); assert(a_it!=address_map.end()); a_it->second.predecessors.insert(it->first); } } std::set<unsigned> working_set; if(!instructions.empty()) working_set.insert(instructions.front().address); while(!working_set.empty()) { std::set<unsigned>::iterator cur=working_set.begin(); address_mapt::iterator a_it=address_map.find(*cur); assert(a_it!=address_map.end()); working_set.erase(cur); if(a_it->second.done) continue; working_set.insert(a_it->second.successors.begin(), a_it->second.successors.end()); instructionst::const_iterator i_it=a_it->second.source; stack.swap(a_it->second.stack); a_it->second.stack.clear(); codet &c=a_it->second.code; assert(stack.empty() || a_it->second.predecessors.size()<=1 || has_prefix(stack.front().get_string(ID_C_base_name), "$stack")); irep_idt statement=i_it->statement; exprt arg0=i_it->args.size()>=1?i_it->args[0]:nil_exprt(); exprt arg1=i_it->args.size()>=2?i_it->args[1]:nil_exprt(); const bytecode_infot &bytecode_info=get_bytecode_info(statement); // deal with _idx suffixes if(statement.size()>=2 && statement[statement.size()-2]=='_' && isdigit(statement[statement.size()-1])) { arg0=constant_exprt( std::string(id2string(statement), statement.size()-1, 1), integer_typet()); statement=std::string(id2string(statement), 0, statement.size()-2); } exprt::operandst op=pop(bytecode_info.pop); exprt::operandst results; results.resize(bytecode_info.push, nil_exprt()); if(statement=="aconst_null") { assert(results.size()==1); results[0]=gen_zero(java_reference_type(void_typet())); } else if(statement=="athrow") { assert(op.size()==1 && results.size()==1); side_effect_expr_throwt throw_expr; throw_expr.add_source_location()=i_it->source_location; throw_expr.copy_to_operands(op[0]); c=code_expressiont(throw_expr); results[0]=op[0]; } else if(statement=="checkcast") { // checkcast throws an exception in case a cast of object // on stack to given type fails. // The stack isn't modified. assert(op.size()==1 && results.size()==1); results[0]=op[0]; } else if(statement=="invokedynamic") { // not used in Java code_typet &code_type=to_code_type(arg0.type()); const code_typet::parameterst ¶meters(code_type.parameters()); pop(parameters.size()); const typet &return_type=code_type.return_type(); if(return_type.id()!=ID_empty) { results.resize(1); results[0]=nil_exprt(); } } else if(statement=="invokeinterface" || statement=="invokespecial" || statement=="invokevirtual" || statement=="invokestatic") { const bool use_this(statement != "invokestatic"); const bool is_virtual( statement == "invokevirtual" || statement == "invokeinterface"); code_typet &code_type=to_code_type(arg0.type()); code_typet::parameterst ¶meters(code_type.parameters()); if(use_this) { if(parameters.empty() || !parameters[0].get_this()) { const empty_typet empty; pointer_typet object_ref_type(empty); code_typet::parametert this_p(object_ref_type); this_p.set_this(); this_p.set_base_name("this"); parameters.insert(parameters.begin(), this_p); } } code_function_callt call; call.add_source_location()=i_it->source_location; call.arguments() = pop(parameters.size()); // double-check a bit if(use_this) { const exprt &this_arg=call.arguments().front(); assert(this_arg.type().id()==ID_pointer); } // do some type adjustment for the arguments, // as Java promotes arguments for(unsigned i=0; i<parameters.size(); i++) { const typet &type=parameters[i].type(); if(type==java_boolean_type() || type==java_char_type() || type==java_byte_type() || type==java_short_type()) { assert(i<call.arguments().size()); call.arguments()[i].make_typecast(type); } } // do some type adjustment for return values const typet &return_type=code_type.return_type(); if(return_type.id()!=ID_empty) { // return types are promoted in Java call.lhs()=tmp_variable("return", return_type); exprt promoted=java_bytecode_promotion(call.lhs()); results.resize(1); results[0]=promoted; } assert(arg0.id()==ID_virtual_function); // does the function symbol exist? irep_idt id=arg0.get(ID_identifier); if(symbol_table.symbols.find(id)==symbol_table.symbols.end()) { // no, create stub symbolt symbol; symbol.name=id; symbol.base_name=arg0.get(ID_C_base_name); symbol.type=arg0.type(); symbol.value.make_nil(); symbol.mode=ID_java; symbol_table.add(symbol); } if(is_virtual) { // dynamic binding assert(use_this); assert(!call.arguments().empty()); call.function()=arg0; } else { // static binding /*if(id == "java::java.lang.String.charAt:(I)C") call.function()=symbol_exprt("java::__CPROVER_uninterpreted_char_at", arg0.type()); else*/ call.function()=symbol_exprt(arg0.get(ID_identifier), arg0.type()); } call.function().add_source_location()=i_it->source_location; c = call; } else if(statement=="return") { assert(op.empty() && results.empty()); c=code_returnt(); } else if(statement==patternt("?return")) { // Return types are promoted in java, so this might need // conversion. assert(op.size()==1 && results.empty()); exprt r=op[0]; if(r.type()!=method_return_type) r=typecast_exprt(r, method_return_type); c=code_returnt(r); } else if(statement==patternt("?astore")) { assert(op.size()==3 && results.empty()); char type_char=statement[0]; exprt pointer= typecast_exprt(op[0], java_array_type(type_char)); const dereference_exprt deref(pointer, pointer.type().subtype()); const member_exprt data_ptr( deref, "data", pointer_typet(java_type_from_char(type_char))); plus_exprt data_plus_offset(data_ptr, op[1], data_ptr.type()); typet element_type=data_ptr.type().subtype(); const dereference_exprt element(data_plus_offset, element_type); c=code_assignt(element, op[2]); } else if(statement==patternt("?store")) { // store value into some local variable assert(op.size()==1 && results.empty()); exprt var=variable(arg0, statement[0]); const bool is_array('a' == statement[0]); if(is_array) var.type()=op[0].type(); c=code_assignt(var, op[0]); } else if(statement==patternt("?aload")) { assert(op.size() == 2 && results.size() == 1); char type_char=statement[0]; exprt pointer= typecast_exprt(op[0], java_array_type(type_char)); const dereference_exprt deref(pointer, pointer.type().subtype()); const member_exprt data_ptr( deref, "data", pointer_typet(java_type_from_char(type_char))); plus_exprt data_plus_offset(data_ptr, op[1], data_ptr.type()); typet element_type=data_ptr.type().subtype(); dereference_exprt element(data_plus_offset, element_type); results[0]=java_bytecode_promotion(element); } else if(statement==patternt("?load")) { // load a value from a local variable results[0]=variable(arg0, statement[0]); } else if(statement=="ldc" || statement=="ldc_w" || statement=="ldc2" || statement=="ldc2_w") { assert(op.empty() && results.size()==1); // 1) Pushing a String causes a reference to a java.lang.String object // to be constructed and pushed onto the operand stack. // 2) Pushing an int or a float causes a primitive value to be pushed // onto the stack. // 3) Pushing a Class constant causes a reference to a java.lang.Class // to be pushed onto the operand stack if(arg0.id()==ID_java_string_literal) { // these need to be references to java.lang.String results[0]=arg0; symbol_typet string_type("java::java.lang.String"); results[0].type()=pointer_typet(string_type); } else if(arg0.id()==ID_type) { irep_idt class_id=arg0.type().get(ID_identifier); symbol_typet java_lang_Class("java::java.lang.Class"); symbol_exprt symbol_expr(id2string(class_id)+"@class_model", java_lang_Class); address_of_exprt address_of_expr(symbol_expr); results[0]=address_of_expr; } else if(arg0.id()==ID_constant) { results[0]=arg0; } else { error() << "unexpected ldc argument" << eom; throw 0; } } else if(statement=="goto" || statement=="goto_w") { assert(op.empty() && results.empty()); irep_idt number=to_constant_expr(arg0).get_value(); code_gotot code_goto(label(number)); c=code_goto; } else if(statement=="iconst_m1") { assert(results.size()==1); results[0]=from_integer(-1, java_int_type()); } else if(statement==patternt("?const")) { assert(results.size() == 1); const char type_char=statement[0]; const bool is_double('d' == type_char); const bool is_float('f' == type_char); if(is_double || is_float) { const ieee_float_spect spec( is_float ? ieee_float_spect::single_precision() : ieee_float_spect::double_precision()); ieee_floatt value(spec); const typet &arg_type(arg0.type()); if(ID_integer == arg_type.id()) value.from_integer(arg0.get_int(ID_value)); else value.from_expr(to_constant_expr(arg0)); results[0] = value.to_expr(); } else { const unsigned int value(arg0.get_unsigned_int(ID_value)); const typet type=java_type_from_char(statement[0]); results[0] = as_number(value, type); } } else if(statement==patternt("?ipush")) { assert(results.size()==1); results[0]=typecast_exprt(arg0, java_int_type()); } else if(statement==patternt("if_?cmp??")) { irep_idt number=to_constant_expr(arg0).get_value(); assert(op.size()==2 && results.empty()); code_ifthenelset code_branch; const irep_idt cmp_op=get_if_cmp_operator(statement); binary_relation_exprt condition(op[0], cmp_op, op[1]); cast_if_necessary(condition); code_branch.cond()=condition; code_branch.then_case()=code_gotot(label(number)); code_branch.then_case().add_source_location()=i_it->source_location; code_branch.add_source_location()=i_it->source_location; c=code_branch; } else if(statement==patternt("if??")) { const irep_idt id= statement=="ifeq"?ID_equal: statement=="ifne"?ID_notequal: statement=="iflt"?ID_lt: statement=="ifge"?ID_ge: statement=="ifgt"?ID_gt: statement=="ifle"?ID_le: (assert(false), ""); irep_idt number=to_constant_expr(arg0).get_value(); assert(op.size()==1 && results.empty()); code_ifthenelset code_branch; code_branch.cond()=binary_relation_exprt(op[0], id, gen_zero(op[0].type())); code_branch.cond().add_source_location()=i_it->source_location; code_branch.then_case()=code_gotot(label(number)); code_branch.then_case().add_source_location()=i_it->source_location; code_branch.add_source_location()=i_it->source_location; c=code_branch; } else if(statement==patternt("ifnonnull")) { irep_idt number=to_constant_expr(arg0).get_value(); assert(op.size()==1 && results.empty()); code_ifthenelset code_branch; const typecast_exprt lhs(op[0], pointer_typet()); const exprt rhs(gen_zero(lhs.type())); code_branch.cond()=binary_relation_exprt(lhs, ID_notequal, rhs); code_branch.then_case()=code_gotot(label(number)); code_branch.then_case().add_source_location()=i_it->source_location; code_branch.add_source_location()=i_it->source_location; c=code_branch; } else if(statement==patternt("ifnull")) { assert(op.size()==1 && results.empty()); irep_idt number=to_constant_expr(arg0).get_value(); code_ifthenelset code_branch; const typecast_exprt lhs(op[0], pointer_typet(empty_typet())); const exprt rhs(gen_zero(lhs.type())); code_branch.cond()=binary_relation_exprt(lhs, ID_equal, rhs); code_branch.then_case()=code_gotot(label(number)); code_branch.then_case().add_source_location()=i_it->source_location; code_branch.add_source_location()=i_it->source_location; c=code_branch; } else if(statement=="iinc") { code_assignt code_assign; code_assign.lhs()=variable(arg0, 'i'); code_assign.rhs()=plus_exprt( variable(arg0, 'i'), typecast_exprt(arg1, java_int_type())); c=code_assign; } else if(statement==patternt("?xor")) { assert(op.size()==2 && results.size()==1); results[0]=bitxor_exprt(op[0], op[1]); } else if(statement==patternt("?or")) { assert(op.size()==2 && results.size()==1); results[0]=bitor_exprt(op[0], op[1]); } else if(statement==patternt("?and")) { assert(op.size()==2 && results.size()==1); results[0]=bitand_exprt(op[0], op[1]); } else if(statement==patternt("?shl")) { assert(op.size()==2 && results.size()==1); results[0]=shl_exprt(op[0], op[1]); } else if(statement==patternt("?shr")) { assert(op.size()==2 && results.size()==1); results[0]=ashr_exprt(op[0], op[1]); } else if(statement==patternt("?ushr")) { assert(op.size()==2 && results.size()==1); const typet type(java_type_from_char(statement[0])); const unsigned int width(type.get_unsigned_int(ID_width)); typet target=unsigned_long_int_type(); target.set(ID_width, width); const typecast_exprt lhs(op[0], target); const typecast_exprt rhs(op[1], target); results[0]=lshr_exprt(lhs, rhs); } else if(statement==patternt("?add")) { assert(op.size()==2 && results.size()==1); results[0]=plus_exprt(op[0], op[1]); } else if(statement==patternt("?sub")) { assert(op.size()==2 && results.size()==1); results[0]=minus_exprt(op[0], op[1]); } else if(statement==patternt("?div")) { assert(op.size()==2 && results.size()==1); results[0]=div_exprt(op[0], op[1]); } else if(statement==patternt("?mul")) { assert(op.size()==2 && results.size()==1); results[0]=mult_exprt(op[0], op[1]); } else if(statement==patternt("?neg")) { assert(op.size()==1 && results.size()==1); results[0]=unary_minus_exprt(op[0], op[0].type()); } else if(statement==patternt("?rem")) { assert(op.size()==2 && results.size()==1); if(statement=="frem" || statement=="drem") results[0]=rem_exprt(op[0], op[1]); else results[0]=mod_exprt(op[0], op[1]); } else if(statement==patternt("?cmp")) { assert(op.size() == 2 && results.size() == 1); // The integer result on the stack is: // 0 if op[0] equals op[1] // -1 if op[0] is less than op[1] // 1 if op[0] is greater than op[1] const typet t=java_int_type(); results[0]= if_exprt(binary_relation_exprt(op[0], ID_equal, op[1]), gen_zero(t), if_exprt(binary_relation_exprt(op[0], ID_gt, op[1]), from_integer(1, t), from_integer(-1, t))); } else if(statement==patternt("?cmp?")) { assert(op.size()==2 && results.size()==1); const floatbv_typet type(to_floatbv_type(java_type_from_char(statement[0]))); const ieee_float_spect spec(type); const ieee_floatt nan(ieee_floatt::NaN(spec)); const constant_exprt nan_expr(nan.to_expr()); const int nan_value(statement[4] == 'l' ? -1 : 1); const typet result_type(java_int_type()); const exprt nan_result(from_integer(nan_value, result_type)); // (value1 == NaN || value2 == NaN) ? nan_value : value1 < value2 ? -1 : value2 < value1 1 ? 1 : 0; // (value1 == NaN || value2 == NaN) ? nan_value : value1 == value2 ? 0 : value1 < value2 -1 ? 1 : 0; results[0]= if_exprt(or_exprt(ieee_float_equal_exprt(nan_expr, op[0]), ieee_float_equal_exprt(nan_expr, op[1])), nan_result, if_exprt(ieee_float_equal_exprt(op[0], op[1]), gen_zero(result_type), if_exprt(binary_relation_exprt(op[0], ID_lt, op[1]), from_integer(-1, result_type), from_integer(1, result_type)))); } else if(statement==patternt("?cmpl")) { assert(op.size()==2 && results.size()==1); results[0]=binary_relation_exprt(op[0], ID_lt, op[1]); } else if(statement=="dup") { assert(op.size()==1 && results.size()==2); results[0]=results[1]=op[0]; } else if(statement=="dup_x1") { assert(op.size()==2 && results.size()==3); results[0]=op[1]; results[1]=op[0]; results[2]=op[1]; } else if(statement=="dup_x2") { assert(op.size()==3 && results.size()==4); results[0]=op[2]; results[1]=op[0]; results[2]=op[1]; results[3]=op[2]; } // dup2* behaviour depends on the size of the operands on the // stack else if(statement=="dup2") { assert(!stack.empty() && results.empty()); if(stack.back().type().get_unsigned_int(ID_width)==32) op=pop(2); else op=pop(1); results.insert(results.end(), op.begin(), op.end()); results.insert(results.end(), op.begin(), op.end()); } else if(statement=="dup2_x1") { assert(!stack.empty() && results.empty()); if(stack.back().type().get_unsigned_int(ID_width)==32) op=pop(3); else op=pop(2); results.insert(results.end(), op.begin()+1, op.end()); results.insert(results.end(), op.begin(), op.end()); } else if(statement=="dup2_x2") { assert(!stack.empty() && results.empty()); if(stack.back().type().get_unsigned_int(ID_width)==32) op=pop(2); else op=pop(1); assert(!stack.empty()); exprt::operandst op2; if(stack.back().type().get_unsigned_int(ID_width)==32) op2=pop(2); else op2=pop(1); results.insert(results.end(), op.begin(), op.end()); results.insert(results.end(), op2.begin(), op2.end()); results.insert(results.end(), op.begin(), op.end()); } else if(statement=="dconst") { assert(op.empty() && results.size()==1); } else if(statement=="fconst") { assert(op.empty() && results.size()==1); } else if(statement=="getfield") { assert(op.size()==1 && results.size()==1); results[0]=to_member(op[0], arg0); } else if(statement=="getstatic") { assert(op.empty() && results.size()==1); symbol_exprt symbol_expr(arg0.type()); symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+arg0.get_string(ID_component_name)); results[0]=symbol_expr; } else if(statement=="putfield") { assert(op.size()==2 && results.size()==0); c = code_assignt(to_member(op[0], arg0), op[1]); } else if(statement=="putstatic") { assert(op.size()==1 && results.empty()); symbol_exprt symbol_expr(arg0.type()); symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+arg0.get_string(ID_component_name)); c=code_assignt(symbol_expr, op[0]); } else if(statement==patternt("?2?")) // i2c etc. { assert(op.size()==1 && results.size()==1); results[0]=typecast_exprt(op[0], java_type_from_char(statement[2])); } else if(statement=="new") { // use temporary since the stack symbol might get duplicated assert(op.empty() && results.size()==1); const pointer_typet ref_type(arg0.type()); exprt java_new_expr=side_effect_exprt(ID_java_new, ref_type); if(!i_it->source_location.get_line().empty()) java_new_expr.add_source_location()=i_it->source_location; const exprt tmp=tmp_variable("new", ref_type); c=code_assignt(tmp, java_new_expr); results[0]=tmp; } else if(statement=="newarray" || statement=="anewarray") { // the op is the array size assert(op.size()==1 && results.size()==1); char element_type; if(statement=="newarray") { irep_idt id=arg0.type().id(); if(id==ID_bool) element_type='z'; else if(id==ID_char) element_type='c'; else if(id==ID_float) element_type='f'; else if(id==ID_double) element_type='d'; else if(id==ID_byte) element_type='b'; else if(id==ID_short) element_type='s'; else if(id==ID_int) element_type='i'; else if(id==ID_long) element_type='j'; else element_type='?'; } else element_type='a'; const pointer_typet ref_type=java_array_type(element_type); side_effect_exprt java_new_array(ID_java_new_array, ref_type); java_new_array.copy_to_operands(op[0]); if(!i_it->source_location.get_line().empty()) java_new_array.add_source_location()=i_it->source_location; const exprt tmp=tmp_variable("newarray", ref_type); c=code_assignt(tmp, java_new_array); results[0]=tmp; } else if(statement=="multianewarray") { // The first argument is the type, the second argument is the dimension. // The size of each dimension is on the stack. irep_idt number=to_constant_expr(arg1).get_value(); unsigned dimension=safe_c_str2unsigned(number.c_str()); op=pop(dimension); assert(results.size()==1); // arg0.type() const pointer_typet ref_type=java_array_type('a'); side_effect_exprt java_new_array(ID_java_new_array, ref_type); java_new_array.operands()=op; if(!i_it->source_location.get_line().empty()) java_new_array.add_source_location()=i_it->source_location; const exprt tmp=tmp_variable("newarray", ref_type); c=code_assignt(tmp, java_new_array); results[0]=tmp; } else if(statement=="arraylength") { assert(op.size()==1 && results.size()==1); exprt pointer= typecast_exprt(op[0], java_array_type(statement[0])); const dereference_exprt array(pointer, pointer.type().subtype()); assert(pointer.type().subtype().id()==ID_symbol); const member_exprt length(array, "length", java_int_type()); results[0]=length; } else if(statement=="tableswitch" || statement=="lookupswitch") { assert(op.size()==1 && results.size()==0); // we turn into switch-case code_switcht code_switch; code_switch.add_source_location()=i_it->source_location; code_switch.value()=op[0]; code_blockt code_block; code_block.add_source_location()=i_it->source_location; bool is_label=true; for(instructiont::argst::const_iterator a_it=i_it->args.begin(); a_it!=i_it->args.end(); a_it++, is_label=!is_label) { if(is_label) { code_switch_caset code_case; code_case.add_source_location()=i_it->source_location; irep_idt number=to_constant_expr(*a_it).get_value(); code_case.code()=code_gotot(label(number)); code_case.code().add_source_location()=i_it->source_location; if(a_it==i_it->args.begin()) code_case.set_default(); else { instructiont::argst::const_iterator prev=a_it; prev--; code_case.case_op()=typecast_exprt(*prev, op[0].type()); code_case.case_op().add_source_location()=i_it->source_location; } code_block.add(code_case); } } code_switch.body()=code_block; c=code_switch; } else if(statement=="pop" || statement=="pop2") { // these are skips c=code_skipt(); // pop2 removes two single-word items from the stack (e.g. two // integers, or an integer and an object reference) or one // two-word item (i.e. a double or a long). // http://cs.au.dk/~mis/dOvs/jvmspec/ref-pop2.html if(statement=="pop2" && op[0].type().get_unsigned_int(ID_width)==32) pop(1); } else if(statement=="instanceof") { assert(op.size()==1 && results.size()==1); results[0]= binary_predicate_exprt(op[0], "java_instanceof", arg0); } else { c=codet(statement); c.operands()=op; } if(!i_it->source_location.get_line().empty()) c.add_source_location()=i_it->source_location; push(results); a_it->second.done=true; for(std::list<unsigned>::iterator it=a_it->second.successors.begin(); it!=a_it->second.successors.end(); ++it) { address_mapt::iterator a_it2=address_map.find(*it); assert(a_it2!=address_map.end()); if(!stack.empty() && a_it2->second.predecessors.size()>1) { // copy into temporaries code_blockt more_code; // introduce temporaries when successor is seen for the first // time if(a_it2->second.stack.empty()) { for(stackt::iterator s_it=stack.begin(); s_it!=stack.end(); ++s_it) { symbol_exprt lhs=tmp_variable("$stack", s_it->type()); code_assignt a(lhs, *s_it); more_code.copy_to_operands(a); s_it->swap(lhs); } } else { assert(a_it2->second.stack.size()==stack.size()); stackt::const_iterator os_it=a_it2->second.stack.begin(); for(stackt::iterator s_it=stack.begin(); s_it!=stack.end(); ++s_it) { assert(has_prefix(os_it->get_string(ID_C_base_name), "$stack")); symbol_exprt lhs=to_symbol_expr(*os_it); code_assignt a(lhs, *s_it); more_code.copy_to_operands(a); s_it->swap(lhs); ++os_it; } } if(results.empty()) { more_code.copy_to_operands(c); c.swap(more_code); } else { c.make_block(); forall_operands(o_it, more_code) c.copy_to_operands(*o_it); } } a_it2->second.stack=stack; } } // TODO: add exception handlers from exception table // review successor computation of athrow! code_blockt code; // temporaries for(const auto & var : tmp_vars) { code.add(code_declt(var)); } for(const auto & it : address_map) { const unsigned address=it.first; assert(it.first==it.second.source->address); const codet &c=it.second.code; if(targets.find(address)!=targets.end()) code.add(code_labelt(label(i2string(address)), c)); else if(c.get_statement()!=ID_skip) code.add(c); } return code; }
constant_exprt unsignedbv_typet::largest_expr() const { return to_constant_expr(from_integer(largest(), *this)); }
constant_exprt unsignedbv_typet::zero_expr() const { return to_constant_expr(from_integer(0, *this)); }
constant_exprt signedbv_typet::smallest_expr() const { return to_constant_expr(from_integer(smallest(), *this)); }
xmlt xml( const exprt &expr, const namespacet &ns) { xmlt result; const typet &type=ns.follow(expr.type()); if(expr.id()==ID_constant) { if(type.id()==ID_unsignedbv || type.id()==ID_signedbv || type.id()==ID_c_bit_field) { std::size_t width=to_bitvector_type(type).get_width(); result.name="integer"; result.set_attribute("binary", expr.get_string(ID_value)); result.set_attribute("width", width); const typet &underlying_type= type.id()==ID_c_bit_field?type.subtype(): type; bool is_signed=underlying_type.id()==ID_signedbv; std::string sig=is_signed?"":"unsigned "; if(width==config.ansi_c.char_width) result.set_attribute("c_type", sig+"char"); else if(width==config.ansi_c.int_width) result.set_attribute("c_type", sig+"int"); else if(width==config.ansi_c.short_int_width) result.set_attribute("c_type", sig+"short int"); else if(width==config.ansi_c.long_int_width) result.set_attribute("c_type", sig+"long int"); else if(width==config.ansi_c.long_long_int_width) result.set_attribute("c_type", sig+"long long int"); mp_integer i; if(!to_integer(expr, i)) result.data=integer2string(i); } else if(type.id()==ID_c_enum) { result.name="integer"; result.set_attribute("binary", expr.get_string(ID_value)); result.set_attribute("width", type.subtype().get_string(ID_width)); result.set_attribute("c_type", "enum"); mp_integer i; if(!to_integer(expr, i)) result.data=integer2string(i); } else if(type.id()==ID_c_enum_tag) { constant_exprt tmp; tmp.type()=ns.follow_tag(to_c_enum_tag_type(type)); tmp.set_value(to_constant_expr(expr).get_value()); return xml(tmp, ns); } else if(type.id()==ID_bv) { result.name="bitvector"; result.set_attribute("binary", expr.get_string(ID_value)); } else if(type.id()==ID_fixedbv) { result.name="fixed"; result.set_attribute("width", type.get_string(ID_width)); result.set_attribute("binary", expr.get_string(ID_value)); result.data=fixedbvt(to_constant_expr(expr)).to_ansi_c_string(); } else if(type.id()==ID_floatbv) { result.name="float"; result.set_attribute("width", type.get_string(ID_width)); result.set_attribute("binary", expr.get_string(ID_value)); result.data=ieee_floatt(to_constant_expr(expr)).to_ansi_c_string(); } else if(type.id()==ID_pointer) { result.name="pointer"; result.set_attribute("binary", expr.get_string(ID_value)); if(expr.get(ID_value)==ID_NULL) result.data="NULL"; } else if(type.id()==ID_bool) { result.name="boolean"; result.set_attribute("binary", expr.is_true()?"1":"0"); result.data=expr.is_true()?"TRUE":"FALSE"; } else { result.name="unknown"; } } else if(expr.id()==ID_array) { result.name="array"; unsigned index=0; forall_operands(it, expr) { xmlt &e=result.new_element("element"); e.set_attribute("index", index); e.new_element(xml(*it, ns)); index++; }
xmlt xml( const exprt &expr, const namespacet &ns) { const typet &type=ns.follow(expr.type()); xmlt result; if(expr.id()==ID_constant) { if(type.id()==ID_unsignedbv || type.id()==ID_signedbv) { result.name="integer"; result.set_attribute("binary", expr.get_string(ID_value)); mp_integer i; if(!to_integer(expr, i)) result.data=integer2string(i); } else if(type.id()==ID_bv) { result.name="bitvector"; result.set_attribute("binary", expr.get_string(ID_value)); result.data=expr.get_string(ID_value); } else if(type.id()==ID_fixedbv) { result.name="fixed"; result.set_attribute("binary", expr.get_string(ID_value)); result.data=fixedbvt(to_constant_expr(expr)).to_ansi_c_string(); } else if(type.id()==ID_floatbv) { result.name="float"; result.set_attribute("binary", expr.get_string(ID_value)); result.data=ieee_floatt(to_constant_expr(expr)).to_ansi_c_string(); } else if(type.id()==ID_pointer) { result.name="pointer"; result.set_attribute("binary", expr.get_string(ID_value)); if(expr.get(ID_value)==ID_NULL) result.data="NULL"; } else if(type.id()==ID_bool) { result.name="boolean"; result.set_attribute("binary", expr.is_true()?"1":"0"); result.data=expr.is_true()?"TRUE":"FALSE"; } else { result.name="unknown"; } } else if(expr.id()==ID_array) { result.name="array"; unsigned index=0; forall_operands(it, expr) { xmlt &e=result.new_element("element"); e.set_attribute("index", index); e.new_element(xml(*it, ns)); index++; }
json_objectt json( const exprt &expr, const namespacet &ns) { json_objectt result; const typet &type=ns.follow(expr.type()); if(expr.id()==ID_constant) { if(type.id()==ID_unsignedbv || type.id()==ID_signedbv || type.id()==ID_c_bit_field) { std::size_t width=to_bitvector_type(type).get_width(); result["name"]=json_stringt("integer"); result["binary"]=json_stringt(expr.get_string(ID_value)); result["width"]=json_numbert(i2string(width)); const typet &underlying_type= type.id()==ID_c_bit_field?type.subtype(): type; bool is_signed=underlying_type.id()==ID_signedbv; std::string sig=is_signed?"":"unsigned "; if(width==config.ansi_c.char_width) result["c_type"]=json_stringt(sig+"char"); else if(width==config.ansi_c.int_width) result["c_type"]=json_stringt(sig+"int"); else if(width==config.ansi_c.short_int_width) result["c_type"]=json_stringt(sig+"short int"); else if(width==config.ansi_c.long_int_width) result["c_type"]=json_stringt(sig+"long int"); else if(width==config.ansi_c.long_long_int_width) result["c_type"]=json_stringt(sig+"long long int"); mp_integer i; if(!to_integer(expr, i)) result["data"]=json_stringt(integer2string(i)); } else if(type.id()==ID_c_enum) { result["name"]=json_stringt("integer"); result["binary"]=json_stringt(expr.get_string(ID_value)); result["width"]=json_numbert(type.subtype().get_string(ID_width)); result["c_type"]=json_stringt("enum"); mp_integer i; if(!to_integer(expr, i)) result["data"]=json_stringt(integer2string(i)); } else if(type.id()==ID_c_enum_tag) { constant_exprt tmp; tmp.type()=ns.follow_tag(to_c_enum_tag_type(type)); tmp.set_value(to_constant_expr(expr).get_value()); return json(tmp, ns); } else if(type.id()==ID_bv) { result["name"]=json_stringt("bitvector"); result["binary"]=json_stringt(expr.get_string(ID_value)); } else if(type.id()==ID_fixedbv) { result["name"]=json_stringt("fixed"); result["width"]=json_numbert(type.get_string(ID_width)); result["binary"]=json_stringt(expr.get_string(ID_value)); result["data"]= json_stringt(fixedbvt(to_constant_expr(expr)).to_ansi_c_string()); } else if(type.id()==ID_floatbv) { result["name"]=json_stringt("float"); result["width"]=json_numbert(type.get_string(ID_width)); result["binary"]=json_stringt(expr.get_string(ID_value)); result["data"]= json_stringt(ieee_floatt(to_constant_expr(expr)).to_ansi_c_string()); } else if(type.id()==ID_pointer) { result["name"]=json_stringt("pointer"); result["binary"]=json_stringt(expr.get_string(ID_value)); if(expr.get(ID_value)==ID_NULL) result["data"]=json_stringt("NULL"); } else if(type.id()==ID_bool) { result["name"]=json_stringt("boolean"); result["binary"]=json_stringt(expr.is_true()?"1":"0"); result["data"]=jsont::json_boolean(expr.is_true()); } else { result["name"]=json_stringt("unknown"); } } else if(expr.id()==ID_array) { result["name"]=json_stringt("array"); json_arrayt &elements=result["elements"].make_array(); unsigned index=0; forall_operands(it, expr) { json_objectt &e=elements.push_back().make_object(); e["index"]=json_numbert(i2string(index)); e["value"]=json(*it, ns); index++; }