std::string inv_object_storet::build_string(const exprt &expr) const { // we ignore some casts if(expr.id()==ID_typecast) { assert(expr.operands().size()==1); if(expr.type().id()==ID_signedbv || expr.type().id()==ID_unsignedbv) { if(expr.op0().type().id()==ID_signedbv || expr.op0().type().id()==ID_unsignedbv) { if(to_bitvector_type(expr.type()).get_width()>= to_bitvector_type(expr.op0().type()).get_width()) return build_string(expr.op0()); } else if(expr.op0().type().id()==ID_bool) { return build_string(expr.op0()); } } } // we always track constants, but make sure they are uniquely // represented if(expr.is_constant()) { // NULL? if(expr.type().id()==ID_pointer) if(expr.get(ID_value)==ID_NULL) return "0"; mp_integer i; if(!to_integer(expr, i)) return integer2string(i); } // we also like "address_of" and "reference_to" // if the object is constant if(is_constant_address(expr)) return from_expr(ns, "", expr); if(expr.id()==ID_member) { assert(expr.operands().size()==1); return build_string(expr.op0())+"."+expr.get_string(ID_component_name); } if(expr.id()==ID_symbol) return expr.get_string(ID_identifier); return ""; }
/** * Return the smallest type that both t1 and t2 can be cast to without losing * information. * * e.g. * * join_types(unsignedbv_typet(32), unsignedbv_typet(16))=unsignedbv_typet(32) * join_types(signedbv_typet(16), unsignedbv_typet(16))=signedbv_typet(17) * join_types(signedbv_typet(32), signedbv_typet(32))=signedbv_typet(32) */ typet join_types(const typet &t1, const typet &t2) { // Handle the simple case first... if(t1==t2) { return t1; } // OK, they're not the same type. Are they both bitvectors? if(is_bitvector(t1) && is_bitvector(t2)) { // They are. That makes things easy! There are three cases to consider: // both types are unsigned, both types are signed or there's one of each. bitvector_typet b1=to_bitvector_type(t1); bitvector_typet b2=to_bitvector_type(t2); if(is_unsigned(b1) && is_unsigned(b2)) { // We just need to take the max of their widths. std::size_t width=std::max(b1.get_width(), b2.get_width()); return unsignedbv_typet(width); } else if(is_signed(b1) && is_signed(b2)) { // Again, just need to take the max of the widths. std::size_t width=std::max(b1.get_width(), b2.get_width()); return signedbv_typet(width); } else { // This is the (slightly) tricky case. If we have a signed and an // unsigned type, we're going to return a signed type. And to cast // an unsigned type to a signed type, we need the signed type to be // at least one bit wider than the unsigned type we're casting from. std::size_t signed_width=is_signed(t1) ? b1.get_width() : b2.get_width(); std::size_t unsigned_width=is_signed(t1) ? b2.get_width() : b1.get_width(); // unsigned_width++; std::size_t width=std::max(signed_width, unsigned_width); return signedbv_typet(width); } } std::cerr << "Tried to join types: " << t1.pretty() << " and " << t2.pretty() << '\n'; assert(!"Couldn't join types"); }
bool restrict_bv_size(typet &type, const size_t width_in_bits) { const irep_idt &type_id=type.id(); if (ID_code == type_id) return restrict_bv_size(to_code_type(type), width_in_bits); if (ID_struct == type_id || ID_union == type_id) return restrict_bv_size(to_struct_union_type(type), width_in_bits); if (static_cast<const typet &>(type).subtype().is_not_nil()) restrict_bv_size(type.subtype(), width_in_bits); if (!is_bv_type(type)) return false; bitvector_typet &bvtype=to_bitvector_type(type); if (width_in_bits >= bvtype.get_width()) return false; to_bitvector_type(type).set_width(width_in_bits); return true; }
bool is_string_type(const typet &t) const { return (t.id()==ID_pointer || t.id()==ID_array) && (t.subtype().id()==ID_signedbv || t.subtype().id()==ID_unsignedbv) && (to_bitvector_type(t.subtype()).get_width()==config.ansi_c.char_width); }
bool value_set_dereferencet::dereference_type_compare( const typet &object_type, const typet &dereference_type) const { if(dereference_type.id()==ID_empty) return true; // always ok if(base_type_eq(object_type, dereference_type, ns)) return true; // ok, they just match // check for struct prefixes const typet ot_base=ns.follow(object_type), dt_base=ns.follow(dereference_type); if(ot_base.id()==ID_struct && dt_base.id()==ID_struct) { if(to_struct_type(dt_base).is_prefix_of( to_struct_type(ot_base))) return true; // ok, dt is a prefix of ot } // we are generous about code pointers if(dereference_type.id()==ID_code && object_type.id()==ID_code) return true; // bitvectors of same width are ok if((dereference_type.id()==ID_signedbv || dereference_type.id()==ID_unsignedbv) && (object_type.id()==ID_signedbv || object_type.id()==ID_unsignedbv) && to_bitvector_type(dereference_type).get_width()== to_bitvector_type(object_type).get_width()) return true; // really different return false; }
void goto_checkt::undefined_shift_check( const shift_exprt &expr, const guardt &guard) { if(!enable_undefined_shift_check) return; // Undefined for all types and shifts if distance exceeds width, // and also undefined for negative distances. const typet &distance_type= ns.follow(expr.distance().type()); if(distance_type.id()==ID_signedbv) { binary_relation_exprt inequality( expr.distance(), ID_ge, gen_zero(distance_type)); add_guarded_claim( inequality, "shift distance is negative", "undefined-shift", expr.find_source_location(), expr, guard); } const typet &op_type= ns.follow(expr.op().type()); if(op_type.id()==ID_unsignedbv || op_type.id()==ID_signedbv) { exprt width_expr= from_integer(to_bitvector_type(op_type).get_width(), distance_type); if(width_expr.is_nil()) throw "no number for width for operator "+expr.id_string(); binary_relation_exprt inequality( expr.distance(), ID_lt, width_expr); add_guarded_claim( inequality, "shift distance too large", "undefined-shift", expr.find_source_location(), expr, guard); } }
exprt gen_one(const typet &type) { const irep_idt type_id=type.id(); exprt result=constant_exprt(type); if(type_id==ID_bool || type_id==ID_rational || type_id==ID_real || type_id==ID_integer || type_id==ID_natural) { result.set(ID_value, ID_1); } else if(type_id==ID_unsignedbv || type_id==ID_signedbv || type_id==ID_c_enum) { std::string value; unsigned width=to_bitvector_type(type).get_width(); for(unsigned i=0; i<width-1; i++) value+='0'; value+='1'; result.set(ID_value, value); } else if(type_id==ID_fixedbv) { fixedbvt fixedbv; fixedbv.spec=to_fixedbv_type(type); fixedbv.from_integer(1); result=fixedbv.to_expr(); } else if(type_id==ID_floatbv) { ieee_floatt ieee_float; ieee_float.spec=to_floatbv_type(type); ieee_float.from_integer(1); result=ieee_float.to_expr(); } else if(type_id==ID_complex) { result=exprt(ID_complex, type); result.operands().resize(2); result.op0()=gen_one(type.subtype()); result.op1()=gen_zero(type.subtype()); } else result.make_nil(); return result; }
exprt gen_zero(const typet &type) { exprt result; const irep_idt type_id=type.id(); result=constant_exprt(type); if(type_id==ID_rational || type_id==ID_real || type_id==ID_integer || type_id==ID_natural || type_id==ID_complex || type_id==ID_c_enum) { result.set(ID_value, ID_0); } else if(type_id==ID_unsignedbv || type_id==ID_signedbv || type_id==ID_verilogbv || type_id==ID_floatbv || type_id==ID_fixedbv) { std::string value; unsigned width=to_bitvector_type(type).get_width(); for(unsigned i=0; i<width; i++) value+='0'; result.set(ID_value, value); } else if(type_id==ID_complex) { result=exprt(ID_complex, type); exprt sub_zero=gen_zero(type.subtype()); result.operands().resize(2, sub_zero); } else if(type_id==ID_bool) { result.make_false(); } else if(type_id==ID_pointer) { result.set(ID_value, ID_NULL); } else result.make_nil(); return result; }
void polynomial_acceleratort::assert_for_values(scratch_programt &program, std::map<exprt, int> &values, std::set<std::pair<expr_listt, exprt> > &coefficients, int num_unwindings, goto_programt::instructionst &loop_body, exprt &target, overflow_instrumentert &overflow) { // First figure out what the appropriate type for this expression is. typet expr_type = nil_typet(); for (std::map<exprt, int>::iterator it = values.begin(); it != values.end(); ++it) { typet this_type=it->first.type(); if (this_type.id() == ID_pointer) { #ifdef DEBUG std::cout << "Overriding pointer type" << std::endl; #endif this_type = unsignedbv_typet(config.ansi_c.pointer_width); } if (expr_type == nil_typet()) { expr_type = this_type; } else { expr_type = join_types(expr_type, this_type); } } assert(to_bitvector_type(expr_type).get_width()>0); // Now set the initial values of the all the variables... for (std::map<exprt, int>::iterator it = values.begin(); it != values.end(); ++it) { program.assign(it->first, from_integer(it->second, expr_type)); } // Now unwind the loop as many times as we need to. for (int i = 0; i < num_unwindings; i++) { program.append(loop_body); } // Now build the polynomial for this point and assert it fits. exprt rhs = nil_exprt(); for (std::set<std::pair<expr_listt, exprt> >::iterator it = coefficients.begin(); it != coefficients.end(); ++it) { int concrete_value = 1; for (expr_listt::const_iterator e_it = it->first.begin(); e_it != it->first.end(); ++e_it) { exprt e = *e_it; if (e == loop_counter) { concrete_value *= num_unwindings; } else { std::map<exprt, int>::iterator v_it = values.find(e); if (v_it != values.end()) { concrete_value *= v_it->second; } } } // OK, concrete_value now contains the value of all the relevant variables // multiplied together. Create the term concrete_value*coefficient and add // it into the polynomial. typecast_exprt cast(it->second, expr_type); exprt term = mult_exprt(from_integer(concrete_value, expr_type), cast); if (rhs.is_nil()) { rhs = term; } else { rhs = plus_exprt(rhs, term); } } exprt overflow_expr; overflow.overflow_expr(rhs, overflow_expr); program.add_instruction(ASSUME)->guard = not_exprt(overflow_expr); rhs = typecast_exprt(rhs, target.type()); // We now have the RHS of the polynomial. Assert that this is equal to the // actual value of the variable we're fitting. exprt polynomial_holds = equal_exprt(target, rhs); // Finally, assert that the polynomial equals the variable we're fitting. goto_programt::targett assumption = program.add_instruction(ASSUME); assumption->guard = polynomial_holds; }
bool polynomial_acceleratort::fit_polynomial_sliced(goto_programt::instructionst &body, exprt &var, expr_sett &influence, polynomialt &polynomial) { // These are the variables that var depends on with respect to the body. std::vector<expr_listt> parameters; std::set<std::pair<expr_listt, exprt> > coefficients; expr_listt exprs; scratch_programt program(symbol_table); exprt overflow_var = utils.fresh_symbol("polynomial::overflow", bool_typet()).symbol_expr(); overflow_instrumentert overflow(program, overflow_var, symbol_table); #ifdef DEBUG std::cout << "Fitting a polynomial for " << expr2c(var, ns) << ", which depends on:" << std::endl; for (expr_sett::iterator it = influence.begin(); it != influence.end(); ++it) { std::cout << expr2c(*it, ns) << std::endl; } #endif for (expr_sett::iterator it = influence.begin(); it != influence.end(); ++it) { if (it->id() == ID_index || it->id() == ID_dereference) { // Hack: don't accelerate variables that depend on arrays... return false; } exprs.clear(); exprs.push_back(*it); parameters.push_back(exprs); exprs.push_back(loop_counter); parameters.push_back(exprs); } // N exprs.clear(); exprs.push_back(loop_counter); parameters.push_back(exprs); // N^2 exprs.push_back(loop_counter); //parameters.push_back(exprs); // Constant exprs.clear(); parameters.push_back(exprs); if (!is_bitvector(var.type())) { // We don't really know how to accelerate non-bitvectors anyway... return false; } unsigned width=to_bitvector_type(var.type()).get_width(); if(var.type().id()==ID_pointer) width=config.ansi_c.pointer_width; assert(width>0); for (std::vector<expr_listt>::iterator it = parameters.begin(); it != parameters.end(); ++it) { symbolt coeff = utils.fresh_symbol("polynomial::coeff", signedbv_typet(width)); coefficients.insert(std::make_pair(*it, coeff.symbol_expr())); } // Build a set of values for all the parameters that allow us to fit a // unique polynomial. // XXX // This isn't ok -- we're assuming 0, 1 and 2 are valid values for the // variables involved, but this might make the path condition UNSAT. Should // really be solving the path constraints a few times to get valid probe // values... std::map<exprt, int> values; for (expr_sett::iterator it = influence.begin(); it != influence.end(); ++it) { values[*it] = 0; } #ifdef DEBUG std::cout << "Fitting polynomial over " << values.size() << " variables" << std::endl; #endif for (int n = 0; n <= 2; n++) { for (expr_sett::iterator it = influence.begin(); it != influence.end(); ++it) { values[*it] = 1; assert_for_values(program, values, coefficients, n, body, var, overflow); values[*it] = 0; } } // Now just need to assert the case where all values are 0 and all are 2. assert_for_values(program, values, coefficients, 0, body, var, overflow); assert_for_values(program, values, coefficients, 2, body, var, overflow); for (expr_sett::iterator it = influence.begin(); it != influence.end(); ++it) { values[*it] = 2; } assert_for_values(program, values, coefficients, 2, body, var, overflow); #ifdef DEBUG std::cout << "Fitting polynomial with program:" << std::endl; program.output(ns, "", std::cout); #endif // Now do an ASSERT(false) to grab a counterexample goto_programt::targett assertion = program.add_instruction(ASSERT); assertion->guard = false_exprt(); // If the path is satisfiable, we've fitted a polynomial. Extract the // relevant coefficients and return the expression. try { if (program.check_sat()) { utils.extract_polynomial(program, coefficients, polynomial); 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; }
exprt flatten_byte_update( const exprt &src, const namespacet &ns) { assert(src.id()==ID_byte_update_little_endian || src.id()==ID_byte_update_big_endian); assert(src.operands().size()==3); mp_integer element_size= pointer_offset_size(ns, src.op2().type()); const typet &t=ns.follow(src.op0().type()); if(t.id()==ID_array) { const array_typet &array_type=to_array_type(t); const typet &subtype=array_type.subtype(); // array of bitvectors? if(subtype.id()==ID_unsignedbv || subtype.id()==ID_signedbv || subtype.id()==ID_floatbv) { mp_integer sub_size=pointer_offset_size(ns, subtype); if(sub_size==-1) throw "can't flatten byte_update for sub-type without size"; // byte array? if(sub_size==1) { // apply 'array-update-with' element_size times exprt result=src.op0(); for(mp_integer i=0; i<element_size; ++i) { exprt i_expr=from_integer(i, ns.follow(src.op1().type())); exprt new_value; if(i==0 && element_size==1) // bytes? { new_value=src.op2(); if(new_value.type()!=subtype) new_value.make_typecast(subtype); } else { exprt byte_extract_expr( src.id()==ID_byte_update_little_endian?ID_byte_extract_little_endian: src.id()==ID_byte_update_big_endian?ID_byte_extract_big_endian: throw "unexpected src.id()", subtype); byte_extract_expr.copy_to_operands(src.op2(), i_expr); new_value=flatten_byte_extract(byte_extract_expr, ns); } exprt where=plus_exprt(src.op1(), i_expr); with_exprt with_expr; with_expr.type()=src.type(); with_expr.old()=result; with_expr.where()=where; with_expr.new_value()=new_value; result.swap(with_expr); } return result; } else // sub_size!=1 { if(element_size==1) // byte-granularity update { div_exprt div_offset(src.op1(), from_integer(sub_size, src.op1().type())); mod_exprt mod_offset(src.op1(), from_integer(sub_size, src.op1().type())); index_exprt index_expr(src.op0(), div_offset, array_type.subtype()); exprt byte_update_expr(src.id(), array_type.subtype()); byte_update_expr.copy_to_operands(index_expr, mod_offset, src.op2()); // Call recurisvely, the array is gone! exprt flattened_byte_update_expr= flatten_byte_update(byte_update_expr, ns); with_exprt with_expr( src.op0(), div_offset, flattened_byte_update_expr); return with_expr; } else throw "flatten_byte_update can only do byte updates of non-byte arrays right now"; } } else { throw "flatten_byte_update can only do arrays of scalars right now"; } } else if(t.id()==ID_signedbv || t.id()==ID_unsignedbv || t.id()==ID_floatbv) { // do a shift, mask and OR unsigned width=to_bitvector_type(t).get_width(); if(element_size*8>width) throw "flatten_byte_update to update element that is too large"; // build mask exprt mask= bitnot_exprt( from_integer(power(2, element_size*8)-1, unsignedbv_typet(width))); const typet &offset_type=ns.follow(src.op1().type()); mult_exprt offset_times_eight(src.op1(), from_integer(8, offset_type)); // shift the mask shl_exprt shl_expr(mask, offset_times_eight); // do the 'AND' bitand_exprt bitand_expr(src.op0(), mask); // zero-extend the value concatenation_exprt value_extended( from_integer(0, unsignedbv_typet(width-integer2long(element_size)*8)), src.op2(), t); // shift the value shl_exprt value_shifted(value_extended, offset_times_eight); // do the 'OR' bitor_exprt bitor_expr(bitand_expr, value_shifted); return bitor_expr; } else { throw "flatten_byte_update can only do array and scalars right now"; } }
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++; }
void c_typecheck_baset::typecheck_c_bit_field_type(c_bit_field_typet &type) { typecheck_type(type.subtype()); mp_integer i; { exprt &width_expr=static_cast<exprt &>(type.add(ID_size)); typecheck_expr(width_expr); make_constant_index(width_expr); if(to_integer(width_expr, i)) { error().source_location=type.source_location(); error() << "failed to convert bit field width" << eom; throw 0; } if(i<0) { error().source_location=type.source_location(); error() << "bit field width is negative" << eom; throw 0; } type.set_width(integer2size_t(i)); type.remove(ID_size); } const typet &subtype=follow(type.subtype()); std::size_t sub_width=0; if(subtype.id()==ID_bool) { // This is the 'proper' bool. sub_width=1; } else if(subtype.id()==ID_signedbv || subtype.id()==ID_unsignedbv || subtype.id()==ID_c_bool) { sub_width=to_bitvector_type(subtype).get_width(); } else if(subtype.id()==ID_c_enum_tag) { // These point to an enum, which has a sub-subtype, // which may be smaller or larger than int, and we thus have // to check. const typet &c_enum_type= follow_tag(to_c_enum_tag_type(subtype)); if(c_enum_type.id()==ID_incomplete_c_enum) { error().source_location=type.source_location(); error() << "bit field has incomplete enum type" << eom; throw 0; } sub_width=c_enum_type.subtype().get_int(ID_width); } else { error().source_location=type.source_location(); error() << "bit field with non-integer type: " << to_string(subtype) << eom; throw 0; } if(i>sub_width) { error().source_location=type.source_location(); error() << "bit field (" << i << " bits) larger than type (" << sub_width << " bits)" << eom; throw 0; } }
mp_integer alignment(const typet &type, const namespacet &ns) { // is the alignment given? const exprt &given_alignment= static_cast<const exprt &>(type.find(ID_C_alignment)); if(given_alignment.is_not_nil()) { mp_integer a_int; if(!to_integer(given_alignment, a_int)) return a_int; // we trust it blindly, no matter how nonsensical } // compute default if(type.id()==ID_array) { return alignment(type.subtype(), ns); } else if(type.id()==ID_struct || type.id()==ID_union) { const struct_union_typet::componentst &components= to_struct_union_type(type).components(); mp_integer result=1; // get the max // (should really be the smallest common denominator) for(struct_union_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) result=std::max(result, alignment(it->type(), ns)); return result; } else if(type.id()==ID_unsignedbv || type.id()==ID_signedbv || type.id()==ID_fixedbv || type.id()==ID_floatbv || type.id()==ID_c_bool) { unsigned width=to_bitvector_type(type).get_width(); return width%8?width/8+1:width/8; } else if(type.id()==ID_c_enum) { return alignment(type.subtype(), ns); } else if(type.id()==ID_c_enum_tag) { return alignment(ns.follow_tag(to_c_enum_tag_type(type)), ns); } else if(type.id()==ID_pointer) { unsigned width=config.ansi_c.pointer_width; return width%8?width/8+1:width/8; } else if(type.id()==ID_symbol) return alignment(ns.follow(type), ns); return 1; }
mp_integer pointer_offset_size( const namespacet &ns, const typet &type) { if(type.id()==ID_array) { mp_integer sub=pointer_offset_size(ns, type.subtype()); // get size const exprt &size=to_array_type(type).size(); // constant? mp_integer i; if(to_integer(size, i)) return -1; // we cannot distinguish the elements return sub*i; } else if(type.id()==ID_struct) { const struct_typet &struct_type=to_struct_type(type); const struct_typet::componentst &components= struct_type.components(); mp_integer result=0; unsigned bit_field_bits=0; for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { if(it->get_is_bit_field()) { bit_field_bits+=it->type().get_int(ID_width); } else { if(bit_field_bits!=0) { result+=bit_field_bits/8; bit_field_bits=0; } const typet &subtype=it->type(); mp_integer sub_size=pointer_offset_size(ns, subtype); if(sub_size==-1) return -1; result+=sub_size; } } return result; } else if(type.id()==ID_union) { const union_typet &union_type=to_union_type(type); const union_typet::componentst &components= union_type.components(); mp_integer result=0; // compute max for(union_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { const typet &subtype=it->type(); mp_integer sub_size=pointer_offset_size(ns, subtype); if(sub_size>result) result=sub_size; } return result; } else if(type.id()==ID_signedbv || type.id()==ID_unsignedbv || type.id()==ID_fixedbv || type.id()==ID_floatbv || type.id()==ID_bv || type.id()==ID_c_enum) { unsigned width=to_bitvector_type(type).get_width(); unsigned bytes=width/8; if(bytes*8!=width) bytes++; return bytes; } else if(type.id()==ID_bool) return 1; else if(type.id()==ID_pointer) { unsigned width=config.ansi_c.pointer_width; unsigned bytes=width/8; if(bytes*8!=width) bytes++; return bytes; } else if(type.id()==ID_symbol) return pointer_offset_size(ns, ns.follow(type)); else if(type.id()==ID_code) return 0; else return mp_integer(-1); }
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++; }