void component_exprt::gen_loc_var( exprt &loc_var, const exprt &expr, std::string suffix) { std::string base; if (expr.id()==ID_symbol) base="."+id2string(to_symbol_expr(expr).get_identifier()); else if (expr.id()==ID_constant) base=".const"; else if (expr.id()==ID_typecast) { base=".typecast__"+id2string(expr.type().id()); if (expr.type().id()==ID_signedbv) { base=base+i2string(to_signedbv_type(expr.type()).get_width()); } else if (expr.type().id()==ID_unsignedbv) { base=base+i2string(to_unsignedbv_type(expr.type()).get_width()); } } else if(id_maps.find(expr.id())!=id_maps.end()) base=".OPERATOR."+id_maps[expr.id()]; else base=".OPERATOR."+id2string(expr.id()); std::string final_name="L."+id2string(source_location.get_line())+"."+i2string(instruction_number)+"_"+i2string(component_cnt)+"_"+i2string(unique_identifier)+base+suffix; //typet type(ID_integer); //exprt loc_var(ID_symbol, type); to_symbol_expr(loc_var).set_identifier(final_name); }
void boolbvt::convert_floatbv_typecast( const floatbv_typecast_exprt &expr, bvt &bv) { const exprt &op0=expr.op(); // number to convert const exprt &op1=expr.rounding_mode(); // rounding mode bvt bv0=convert_bv(op0); bvt bv1=convert_bv(op1); const typet &src_type=ns.follow(expr.op0().type()); const typet &dest_type=ns.follow(expr.type()); if(src_type==dest_type) // redundant type cast? { bv=bv0; return; } float_utilst float_utils(prop); float_utils.set_rounding_mode(convert_bv(op1)); if(src_type.id()==ID_floatbv && dest_type.id()==ID_floatbv) { float_utils.spec=to_floatbv_type(src_type); bv=float_utils.conversion(bv0, to_floatbv_type(dest_type)); } else if(src_type.id()==ID_signedbv && dest_type.id()==ID_floatbv) { float_utils.spec=to_floatbv_type(dest_type); bv=float_utils.from_signed_integer(bv0); } else if(src_type.id()==ID_unsignedbv && dest_type.id()==ID_floatbv) { float_utils.spec=to_floatbv_type(dest_type); bv=float_utils.from_unsigned_integer(bv0); } else if(src_type.id()==ID_floatbv && dest_type.id()==ID_signedbv) { std::size_t dest_width=to_signedbv_type(dest_type).get_width(); float_utils.spec=to_floatbv_type(src_type); bv=float_utils.to_signed_integer(bv0, dest_width); } else if(src_type.id()==ID_floatbv && dest_type.id()==ID_unsignedbv) { std::size_t dest_width=to_unsignedbv_type(dest_type).get_width(); float_utils.spec=to_floatbv_type(src_type); bv=float_utils.to_unsigned_integer(bv0, dest_width); } else return conversion_failed(expr, bv); }
static std::string type_max(const typet &src) { if(src.id()==ID_signedbv) return integer2string( power(2, to_signedbv_type(src).get_width()-1)-1); else if(src.id()==ID_unsignedbv) return integer2string( power(2, to_unsignedbv_type(src).get_width()-1)-1); else assert(false); }
xmlt xml( const typet &type, const namespacet &ns) { if(type.id()==ID_symbol) return xml(ns.follow(type), ns); xmlt result; if(type.id()==ID_unsignedbv) { result.name="integer"; result.set_attribute("width", to_unsignedbv_type(type).get_width()); } else if(type.id()==ID_signedbv) { result.name="integer"; result.set_attribute("width", to_signedbv_type(type).get_width()); } else if(type.id()==ID_floatbv) { result.name="float"; result.set_attribute("width", to_floatbv_type(type).get_width()); } else if(type.id()==ID_bv) { result.name="integer"; result.set_attribute("width", to_bv_type(type).get_width()); } else if(type.id()==ID_c_bit_field) { result.name="integer"; result.set_attribute("width", to_c_bit_field_type(type).get_width()); } else if(type.id()==ID_c_enum_tag) { // we return the base type return xml(ns.follow_tag(to_c_enum_tag_type(type)).subtype(), ns); } else if(type.id()==ID_fixedbv) { result.name="fixed"; result.set_attribute("width", to_fixedbv_type(type).get_width()); } else if(type.id()==ID_pointer) { result.name="pointer"; result.new_element("subtype").new_element()=xml(type.subtype(), ns); } else if(type.id()==ID_bool) { result.name="boolean"; } else if(type.id()==ID_array) { result.name="array"; result.new_element("subtype").new_element()=xml(type.subtype(), ns); } else if(type.id()==ID_vector) { result.name="vector"; result.new_element("subtype").new_element()=xml(type.subtype(), ns); result.new_element("size").new_element()=xml(to_vector_type(type).size(), ns); } else if(type.id()==ID_struct) { result.name="struct"; const struct_typet::componentst &components= to_struct_type(type).components(); for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { xmlt &e=result.new_element("member"); e.set_attribute("name", id2string(it->get_name())); e.new_element("type").new_element()=xml(it->type(), ns); } } else if(type.id()==ID_union) { result.name="union"; const union_typet::componentst &components= to_union_type(type).components(); for(union_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { xmlt &e=result.new_element("member"); e.set_attribute("name", id2string(it->get_name())); e.new_element("type").new_element()=xml(it->type(), ns); } } else result.name="unknown"; return result; }
void goto_checkt::integer_overflow_check( const exprt &expr, const guardt &guard) { if(!enable_signed_overflow_check && !enable_unsigned_overflow_check) return; // First, check type. const typet &type=ns.follow(expr.type()); if(type.id()==ID_signedbv && !enable_signed_overflow_check) return; if(type.id()==ID_unsignedbv && !enable_unsigned_overflow_check) return; // add overflow subgoal if(expr.id()==ID_div) { assert(expr.operands().size()==2); // undefined for signed division INT_MIN/-1 if(type.id()==ID_signedbv) { equal_exprt int_min_eq( expr.op0(), to_signedbv_type(type).smallest_expr()); equal_exprt minus_one_eq( expr.op1(), from_integer(-1, type)); add_guarded_claim( not_exprt(and_exprt(int_min_eq, minus_one_eq)), "arithmetic overflow on signed division", "overflow", expr.find_source_location(), expr, guard); } return; } else if(expr.id()==ID_mod) { // these can't overflow return; } else if(expr.id()==ID_unary_minus) { if(type.id()==ID_signedbv) { // overflow on unary- can only happen with the smallest // representable number 100....0 equal_exprt int_min_eq( expr.op0(), to_signedbv_type(type).smallest_expr()); add_guarded_claim( not_exprt(int_min_eq), "arithmetic overflow on signed unary minus", "overflow", expr.find_source_location(), expr, guard); } return; } exprt overflow("overflow-"+expr.id_string(), bool_typet()); overflow.operands()=expr.operands(); if(expr.operands().size()>=3) { // The overflow checks are binary! // We break these up. for(unsigned i=1; i<expr.operands().size(); i++) { exprt tmp; if(i==1) tmp=expr.op0(); else { tmp=expr; tmp.operands().resize(i); } overflow.operands().resize(2); overflow.op0()=tmp; overflow.op1()=expr.operands()[i]; std::string kind= type.id()==ID_unsignedbv?"unsigned":"signed"; add_guarded_claim( not_exprt(overflow), "arithmetic overflow on "+kind+" "+expr.id_string(), "overflow", expr.find_source_location(), expr, guard); } } else { std::string kind= type.id()==ID_unsignedbv?"unsigned":"signed"; add_guarded_claim( not_exprt(overflow), "arithmetic overflow on "+kind+" "+expr.id_string(), "overflow", expr.find_source_location(), expr, guard); } }
void goto_checkt::conversion_check( const exprt &expr, const guardt &guard) { if(!enable_conversion_check) return; // First, check type. const typet &type=ns.follow(expr.type()); if(type.id()!=ID_signedbv && type.id()!=ID_unsignedbv) return; if(expr.id()==ID_typecast) { // conversion to signed int may overflow if(expr.operands().size()!=1) throw "typecast takes one operand"; const typet &old_type=ns.follow(expr.op0().type()); if(type.id()==ID_signedbv) { std::size_t new_width=to_signedbv_type(type).get_width(); if(old_type.id()==ID_signedbv) // signed -> signed { std::size_t old_width=to_signedbv_type(old_type).get_width(); if(new_width>=old_width) return; // always ok binary_relation_exprt no_overflow_upper(ID_le); no_overflow_upper.lhs()=expr.op0(); no_overflow_upper.rhs()=from_integer(power(2, new_width-1)-1, old_type); binary_relation_exprt no_overflow_lower(ID_ge); no_overflow_lower.lhs()=expr.op0(); no_overflow_lower.rhs()=from_integer(-power(2, new_width-1), old_type); add_guarded_claim( and_exprt(no_overflow_lower, no_overflow_upper), "arithmetic overflow on signed type conversion", "overflow", expr.find_source_location(), expr, guard); } else if(old_type.id()==ID_unsignedbv) // unsigned -> signed { std::size_t old_width=to_unsignedbv_type(old_type).get_width(); if(new_width>=old_width+1) return; // always ok binary_relation_exprt no_overflow_upper(ID_le); no_overflow_upper.lhs()=expr.op0(); no_overflow_upper.rhs()=from_integer(power(2, new_width-1)-1, old_type); add_guarded_claim( no_overflow_upper, "arithmetic overflow on unsigned to signed type conversion", "overflow", expr.find_source_location(), expr, guard); } else if(old_type.id()==ID_floatbv) // float -> signed { // Note that the fractional part is truncated! ieee_floatt upper(to_floatbv_type(old_type)); upper.from_integer(power(2, new_width-1)); binary_relation_exprt no_overflow_upper(ID_lt); no_overflow_upper.lhs()=expr.op0(); no_overflow_upper.rhs()=upper.to_expr(); ieee_floatt lower(to_floatbv_type(old_type)); lower.from_integer(-power(2, new_width-1)-1); binary_relation_exprt no_overflow_lower(ID_gt); no_overflow_lower.lhs()=expr.op0(); no_overflow_lower.rhs()=lower.to_expr(); add_guarded_claim( and_exprt(no_overflow_lower, no_overflow_upper), "arithmetic overflow on float to signed integer type conversion", "overflow", expr.find_source_location(), expr, guard); } } else if(type.id()==ID_unsignedbv) { std::size_t new_width=to_unsignedbv_type(type).get_width(); if(old_type.id()==ID_signedbv) // signed -> unsigned { std::size_t old_width=to_signedbv_type(old_type).get_width(); if(new_width>=old_width-1) { // only need lower bound check binary_relation_exprt no_overflow_lower(ID_ge); no_overflow_lower.lhs()=expr.op0(); no_overflow_lower.rhs()=from_integer(0, old_type); add_guarded_claim( no_overflow_lower, "arithmetic overflow on signed to unsigned type conversion", "overflow", expr.find_source_location(), expr, guard); } else { // need both binary_relation_exprt no_overflow_upper(ID_le); no_overflow_upper.lhs()=expr.op0(); no_overflow_upper.rhs()=from_integer(power(2, new_width)-1, old_type); binary_relation_exprt no_overflow_lower(ID_ge); no_overflow_lower.lhs()=expr.op0(); no_overflow_lower.rhs()=from_integer(0, old_type); add_guarded_claim( and_exprt(no_overflow_lower, no_overflow_upper), "arithmetic overflow on signed to unsigned type conversion", "overflow", expr.find_source_location(), expr, guard); } } else if(old_type.id()==ID_unsignedbv) // unsigned -> unsigned { std::size_t old_width=to_unsignedbv_type(old_type).get_width(); if(new_width>=old_width) return; // always ok binary_relation_exprt no_overflow_upper(ID_le); no_overflow_upper.lhs()=expr.op0(); no_overflow_upper.rhs()=from_integer(power(2, new_width)-1, old_type); add_guarded_claim( no_overflow_upper, "arithmetic overflow on unsigned to unsigned type conversion", "overflow", expr.find_source_location(), expr, guard); } else if(old_type.id()==ID_floatbv) // float -> unsigned { // Note that the fractional part is truncated! ieee_floatt upper(to_floatbv_type(old_type)); upper.from_integer(power(2, new_width)-1); binary_relation_exprt no_overflow_upper(ID_lt); no_overflow_upper.lhs()=expr.op0(); no_overflow_upper.rhs()=upper.to_expr(); ieee_floatt lower(to_floatbv_type(old_type)); lower.from_integer(-1); binary_relation_exprt no_overflow_lower(ID_gt); no_overflow_lower.lhs()=expr.op0(); no_overflow_lower.rhs()=lower.to_expr(); add_guarded_claim( and_exprt(no_overflow_lower, no_overflow_upper), "arithmetic overflow on float to unsigned integer type conversion", "overflow", expr.find_source_location(), expr, guard); } } } }
bool equality_domaint::adapt_types(exprt &v1, exprt &v2) { // signed, unsigned integers if((v1.type().id()==ID_signedbv || v1.type().id()==ID_unsignedbv) && (v2.type().id()==ID_signedbv || v2.type().id()==ID_unsignedbv)) { unsigned size1=0, size2=0; if(v1.type().id()==ID_signedbv) size1=to_signedbv_type(v1.type()).get_width(); if(v1.type().id()==ID_unsignedbv) size1=to_unsignedbv_type(v1.type()).get_width(); if(v2.type().id()==ID_signedbv) size2=to_signedbv_type(v2.type()).get_width(); if(v2.type().id()==ID_unsignedbv) size2=to_unsignedbv_type(v2.type()).get_width(); if(v1.type().id()==v2.type().id()) { if(size1==size2) return true; typet new_type=v1.type(); if(new_type.id()==ID_signedbv) to_signedbv_type(new_type).set_width(std::max(size1, size2)); else // if(new_type.id()==ID_unsignedbv) to_unsignedbv_type(new_type).set_width(std::max(size1, size2)); if(size1>size2) v2=typecast_exprt(v2, new_type); else v1=typecast_exprt(v1, new_type); return true; } // types are different typet new_type=signedbv_typet(std::max(size1, size2)+1); v1=typecast_exprt(v1, new_type); v2=typecast_exprt(v2, new_type); return true; } // pointer equality if(v1.type().id()==ID_pointer && v2.type().id()==ID_pointer) { if(to_pointer_type(v1.type()).subtype()== to_pointer_type(v2.type()).subtype()) return true; return false; } if(v1.id()==ID_index || v2.id()==ID_index) { #if 0 std::cout << "v1: " << v1 << std::endl; std::cout << "v2: " << v2 << std::endl; #endif // TODO: implement return false; } return false; // types incompatible }
const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const { // check cache first std::pair<cachet::iterator, bool> cache_result= cache.insert(std::pair<typet, entryt>(type, entryt())); entryt &entry=cache_result.first->second; if(!cache_result.second) // found! return entry; entry.total_width=0; const irep_idt type_id=type.id(); if(type_id==ID_struct) { const struct_typet::componentst &components= to_struct_type(type).components(); std::size_t offset=0; entry.members.resize(components.size()); for(std::size_t i=0; i<entry.members.size(); i++) { std::size_t sub_width=operator()(components[i].type()); entry.members[i].offset=offset; entry.members[i].width=sub_width; offset+=sub_width; } entry.total_width=offset; } else if(type_id==ID_union) { const union_typet::componentst &components= to_union_type(type).components(); entry.members.resize(components.size()); std::size_t max_width=0; for(std::size_t i=0; i<entry.members.size(); i++) { std::size_t sub_width=operator()(components[i].type()); entry.members[i].width=sub_width; max_width=std::max(max_width, sub_width); } entry.total_width=max_width; } else if(type_id==ID_bool) entry.total_width=1; else if(type_id==ID_c_bool) { entry.total_width=to_c_bool_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_signedbv) { entry.total_width=to_signedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_unsignedbv) { entry.total_width=to_unsignedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_floatbv) { entry.total_width=to_floatbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_fixedbv) { entry.total_width=to_fixedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_bv) { entry.total_width=to_bv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_verilogbv) { // we encode with two bits entry.total_width=type.get_unsigned_int(ID_width)*2; assert(entry.total_width!=0); } else if(type_id==ID_range) { mp_integer from=string2integer(type.get_string(ID_from)), to=string2integer(type.get_string(ID_to)); mp_integer size=to-from+1; if(size>=1) { entry.total_width=integer2unsigned(address_bits(size)); assert(entry.total_width!=0); } } else if(type_id==ID_array) { const array_typet &array_type=to_array_type(type); std::size_t sub_width=operator()(array_type.subtype()); mp_integer array_size; if(to_integer(array_type.size(), array_size)) { // we can still use the theory of arrays for this entry.total_width=0; } else { mp_integer total=array_size*sub_width; if(total>(1<<30)) // realistic limit throw "array too large for flattening"; entry.total_width=integer2unsigned(total); } } else if(type_id==ID_vector) { const vector_typet &vector_type=to_vector_type(type); std::size_t sub_width=operator()(vector_type.subtype()); mp_integer vector_size; if(to_integer(vector_type.size(), vector_size)) { // we can still use the theory of arrays for this entry.total_width=0; } else { mp_integer total=vector_size*sub_width; if(total>(1<<30)) // realistic limit throw "vector too large for flattening"; entry.total_width=integer2unsigned(vector_size*sub_width); } } else if(type_id==ID_complex) { std::size_t sub_width=operator()(type.subtype()); entry.total_width=integer2unsigned(2*sub_width); } else if(type_id==ID_code) { } else if(type_id==ID_enum) { // get number of necessary bits std::size_t size=type.find(ID_elements).get_sub().size(); entry.total_width=integer2unsigned(address_bits(size)); assert(entry.total_width!=0); } else if(type_id==ID_c_enum) { // these have a subtype entry.total_width=type.subtype().get_unsigned_int(ID_width); assert(entry.total_width!=0); } else if(type_id==ID_incomplete_c_enum) { // no width } else if(type_id==ID_pointer || type_id==ID_reference) { entry.total_width=config.ansi_c.pointer_width; } else if(type_id==ID_symbol) entry=get_entry(ns.follow(type)); else if(type_id==ID_struct_tag) entry=get_entry(ns.follow_tag(to_struct_tag_type(type))); else if(type_id==ID_union_tag) entry=get_entry(ns.follow_tag(to_union_tag_type(type))); else if(type_id==ID_c_enum_tag) entry=get_entry(ns.follow_tag(to_c_enum_tag_type(type))); else if(type_id==ID_c_bit_field) { entry.total_width=to_c_bit_field_type(type).get_width(); } return entry; }
json_objectt json( const typet &type, const namespacet &ns) { if(type.id()==ID_symbol) return json(ns.follow(type), ns); json_objectt result; if(type.id()==ID_unsignedbv) { result["name"]=json_stringt("integer"); result["width"]= json_numbert(i2string(to_unsignedbv_type(type).get_width())); } else if(type.id()==ID_signedbv) { result["name"]=json_stringt("integer"); result["width"]=json_numbert(i2string(to_signedbv_type(type).get_width())); } else if(type.id()==ID_floatbv) { result["name"]=json_stringt("float"); result["width"]=json_numbert(i2string(to_floatbv_type(type).get_width())); } else if(type.id()==ID_bv) { result["name"]=json_stringt("integer"); result["width"]=json_numbert(i2string(to_bv_type(type).get_width())); } else if(type.id()==ID_c_bit_field) { result["name"]=json_stringt("integer"); result["width"]= json_numbert(i2string(to_c_bit_field_type(type).get_width())); } else if(type.id()==ID_c_enum_tag) { // we return the base type return json(ns.follow_tag(to_c_enum_tag_type(type)).subtype(), ns); } else if(type.id()==ID_fixedbv) { result["name"]=json_stringt("fixed"); result["width"]=json_numbert(i2string(to_fixedbv_type(type).get_width())); } else if(type.id()==ID_pointer) { result["name"]=json_stringt("pointer"); result["subtype"]=json(type.subtype(), ns); } else if(type.id()==ID_bool) { result["name"]=json_stringt("boolean"); } else if(type.id()==ID_array) { result["name"]=json_stringt("array"); result["subtype"]=json(type.subtype(), ns); } else if(type.id()==ID_vector) { result["name"]=json_stringt("vector"); result["subtype"]=json(type.subtype(), ns); result["size"]=json(to_vector_type(type).size(), ns); } else if(type.id()==ID_struct) { result["name"]=json_stringt("struct"); json_arrayt &members=result["members"].make_array(); const struct_typet::componentst &components= to_struct_type(type).components(); for(const auto & it : components) { json_objectt &e=members.push_back().make_object(); e["name"]=json_stringt(id2string(it.get_name())); e["type"]=json(it.type(), ns); } } else if(type.id()==ID_union) { result["name"]=json_stringt("union"); json_arrayt &members=result["members"].make_array(); const union_typet::componentst &components= to_union_type(type).components(); for(const auto & it : components) { json_objectt &e=members.push_back().make_object(); e["name"]=json_stringt(id2string(it.get_name())); e["type"]=json(it.type(), ns); } } else result["name"]=json_stringt("unknown"); return result; }