void boolbvt::convert_index( const exprt &array, const mp_integer &index, bvt &bv) { const array_typet &array_type= to_array_type(ns.follow(array.type())); unsigned width=boolbv_width(array_type.subtype()); if(width==0) return conversion_failed(array, bv); bv.resize(width); const bvt &tmp=convert_bv(array); // recursive call mp_integer offset=index*width; if(offset>=0 && offset+width<=mp_integer(tmp.size())) { // in bounds for(unsigned i=0; i<width; i++) bv[i]=tmp[integer2long(offset+i)]; } else { // out of bounds for(unsigned i=0; i<width; i++) bv[i]=prop.new_variable(); } }
typet c_typecheck_baset::enum_constant_type( const mp_integer &min_value, const mp_integer &max_value) const { if(config.ansi_c.mode==configt::ansi_ct::flavourt::VISUAL_STUDIO) { return signed_int_type(); } else { // enum constants are at least 'int', but may be made larger. // 'Packing' has no influence. if(max_value<(mp_integer(1)<<(config.ansi_c.int_width-1)) && min_value>=-(mp_integer(1)<<(config.ansi_c.int_width-1))) return signed_int_type(); else if(max_value<(mp_integer(1)<<config.ansi_c.int_width) && min_value>=0) return unsigned_int_type(); else if(max_value<(mp_integer(1)<<config.ansi_c.long_int_width) && min_value>=0) return unsigned_long_int_type(); else if(max_value<(mp_integer(1)<<config.ansi_c.long_long_int_width) && min_value>=0) return unsigned_long_long_int_type(); else if(max_value<(mp_integer(1)<<(config.ansi_c.long_int_width-1)) && min_value>=-(mp_integer(1)<<(config.ansi_c.long_int_width-1))) return signed_long_int_type(); else return signed_long_long_int_type(); } }
exprt c_typecheck_baset::do_initializer_rec( const exprt &value, const typet &type, bool force_constant) { const typet &full_type=follow(type); if(full_type.id()==ID_incomplete_struct) { err_location(value); error() << "type `" << to_string(full_type) << "' is still incomplete -- cannot initialize" << eom; throw 0; } if(value.id()==ID_initializer_list) return do_initializer_list(value, type, force_constant); if(value.id()==ID_array && value.get_bool(ID_C_string_constant) && full_type.id()==ID_array && (full_type.subtype().id()==ID_signedbv || full_type.subtype().id()==ID_unsignedbv) && full_type.subtype().get(ID_width)==value.type().subtype().get(ID_width)) { exprt tmp=value; // adjust char type tmp.type().subtype()=full_type.subtype(); Forall_operands(it, tmp) it->type()=full_type.subtype(); if(full_type.id()==ID_array && to_array_type(full_type).is_complete()) { // check size mp_integer array_size; if(to_integer(to_array_type(full_type).size(), array_size)) { err_location(value); error() << "array size needs to be constant, got " << to_string(to_array_type(full_type).size()) << eom; throw 0; } if(array_size<0) { err_location(value); error() << "array size must not be negative" << eom; throw 0; } if(mp_integer(tmp.operands().size())>array_size) { // cut off long strings. gcc does a warning for this tmp.operands().resize(integer2size_t(array_size)); tmp.type()=type; } else if(mp_integer(tmp.operands().size())<array_size) { // fill up tmp.type()=type; exprt zero= zero_initializer( full_type.subtype(), value.source_location(), *this, get_message_handler()); tmp.operands().resize(integer2size_t(array_size), zero); } } return tmp; } if(value.id()==ID_string_constant && full_type.id()==ID_array && (full_type.subtype().id()==ID_signedbv || full_type.subtype().id()==ID_unsignedbv) && full_type.subtype().get(ID_width)==char_type().get(ID_width)) { // will go away, to be replaced by the above block string_constantt tmp1=to_string_constant(value); // adjust char type tmp1.type().subtype()=full_type.subtype(); exprt tmp2=tmp1.to_array_expr(); if(full_type.id()==ID_array && to_array_type(full_type).is_complete()) { // check size mp_integer array_size; if(to_integer(to_array_type(full_type).size(), array_size)) { err_location(value); error() << "array size needs to be constant, got " << to_string(to_array_type(full_type).size()) << eom; throw 0; } if(array_size<0) { err_location(value); error() << "array size must not be negative" << eom; throw 0; } if(mp_integer(tmp2.operands().size())>array_size) { // cut off long strings. gcc does a warning for this tmp2.operands().resize(integer2size_t(array_size)); tmp2.type()=type; } else if(mp_integer(tmp2.operands().size())<array_size) { // fill up tmp2.type()=type; exprt zero= zero_initializer( full_type.subtype(), value.source_location(), *this, get_message_handler()); tmp2.operands().resize(integer2size_t(array_size), zero); } } return tmp2; } if(full_type.id()==ID_array && to_array_type(full_type).size().is_nil()) { err_location(value); error() << "type `" << to_string(full_type) << "' cannot be initialized with `" << to_string(value) << "'" << eom; throw 0; } if(value.id()==ID_designated_initializer) { err_location(value); error() << "type `" << to_string(full_type) << "' cannot be initialized with designated initializer" << eom; throw 0; } exprt result=value; implicit_typecast(result, type); return result; }
exprt convert_float_literal(const std::string &src) { mp_integer significand; mp_integer exponent; bool is_float, is_long, is_imaginary; bool is_decimal, is_float80, is_float128; // GCC extensions unsigned base; parse_float(src, significand, exponent, base, is_float, is_long, is_imaginary, is_decimal, is_float80, is_float128); exprt result=exprt(ID_constant); result.set(ID_C_cformat, src); // In ANSI-C, float literals are double by default, // unless marked with 'f'. // All of these can be complex as well. // This can be overriden with // config.ansi_c.single_precision_constant. if(is_float) result.type()=float_type(); else if(is_long) result.type()=long_double_type(); else if(is_float80) { result.type()=ieee_float_spect(64, 15).to_type(); result.type().set(ID_C_c_type, ID_long_double); } else if(is_float128) { result.type()=ieee_float_spect::quadruple_precision().to_type(); result.type().set(ID_C_c_type, ID_gcc_float128); } else { // default if(config.ansi_c.single_precision_constant) result.type()=float_type(); // default else result.type()=double_type(); // default } if(is_decimal) { // TODO - should set ID_gcc_decimal32/ID_gcc_decimal64/ID_gcc_decimal128, // but these aren't handled anywhere } if(config.ansi_c.use_fixed_for_float) { unsigned width=result.type().get_int(ID_width); unsigned fraction_bits; const irep_idt integer_bits=result.type().get(ID_integer_bits); assert(width!=0); if(integer_bits==irep_idt()) fraction_bits=width/2; // default else fraction_bits=width-safe_string2int(id2string(integer_bits)); mp_integer factor=mp_integer(1)<<fraction_bits; mp_integer value=significand*factor; if(value!=0) { if(exponent<0) value/=power(base, -exponent); else { value*=power(base, exponent); if(value>=power(2, width-1)) { // saturate: use "biggest value" value=power(2, width-1)-1; } else if(value<=-power(2, width-1)-1) { // saturate: use "smallest value" value=-power(2, width-1); } } } result.set(ID_value, integer2binary(value, width)); } else { ieee_floatt a; a.spec=to_floatbv_type(result.type()); if(base==10) a.from_base10(significand, exponent); else if(base==2) // hex a.build(significand, exponent); else assert(false); result.set(ID_value, integer2binary(a.pack(), a.spec.width())); } if(is_imaginary) { complex_typet complex_type; complex_type.subtype()=result.type(); exprt complex_expr(ID_complex, complex_type); complex_expr.operands().resize(2); complex_expr.op0()=gen_zero(result.type()); complex_expr.op1()=result; return complex_expr; } return result; }
bvt boolbvt::convert_byte_update(const byte_update_exprt &expr) { if(expr.operands().size()!=3) throw "byte_update takes three operands"; const exprt &op=expr.op0(); const exprt &offset_expr=expr.offset(); const exprt &value=expr.value(); bool little_endian; if(expr.id()==ID_byte_update_little_endian) little_endian=true; else if(expr.id()==ID_byte_update_big_endian) little_endian=false; else assert(false); bvt bv=convert_bv(op); const bvt &value_bv=convert_bv(value); std::size_t update_width=value_bv.size(); std::size_t byte_width=8; if(update_width>bv.size()) update_width=bv.size(); // see if the byte number is constant mp_integer index; if(!to_integer(offset_expr, index)) { // yes! mp_integer offset=index*8; if(offset+update_width>mp_integer(bv.size()) || offset<0) { // out of bounds } else { if(little_endian) { for(std::size_t i=0; i<update_width; i++) bv[integer2size_t(offset+i)]=value_bv[i]; } else { endianness_mapt map_op(op.type(), false, ns); endianness_mapt map_value(value.type(), false, ns); std::size_t offset_i=integer2unsigned(offset); for(std::size_t i=0; i<update_width; i++) { size_t index_op=map_op.map_bit(offset_i+i); size_t index_value=map_value.map_bit(i); assert(index_op<bv.size()); assert(index_value<value_bv.size()); bv[index_op]=value_bv[index_value]; } } } return bv; } // byte_update with variable index for(std::size_t offset=0; offset<bv.size(); offset+=byte_width) { // index condition equal_exprt equality; equality.lhs()=offset_expr; equality.rhs()=from_integer(offset/byte_width, offset_expr.type()); literalt equal=convert(equality); endianness_mapt map_op(op.type(), little_endian, ns); endianness_mapt map_value(value.type(), little_endian, ns); for(std::size_t bit=0; bit<update_width; bit++) if(offset+bit<bv.size()) { std::size_t bv_o=map_op.map_bit(offset+bit); std::size_t value_bv_o=map_value.map_bit(bit); bv[bv_o]=prop.lselect(equal, value_bv[value_bv_o], bv[bv_o]); } } return bv; }
void goto_convertt::do_prob_coin( const exprt &lhs, const exprt &function, const exprt::operandst &arguments, goto_programt &dest) { const irep_idt &identifier=function.get(ID_identifier); // make it a side effect if there is an LHS if(arguments.size()!=2) { err_location(function); throw "`"+id2string(identifier)+"' expected to have two arguments"; } if(lhs.is_nil()) { err_location(function); throw "`"+id2string(identifier)+"' expected to have LHS"; } exprt rhs=side_effect_exprt("prob_coin", lhs.type()); rhs.add_source_location()=function.source_location(); if(lhs.type()!=bool_typet()) { err_location(function); throw "`"+id2string(identifier)+"' expected bool"; } if(arguments[0].type().id()!=ID_unsignedbv || arguments[0].id()!=ID_constant) { err_location(function); throw "`"+id2string(identifier)+"' expected first " "operand to be a constant literal of type unsigned long"; } mp_integer num, den; if(to_integer(arguments[0], num) || to_integer(arguments[1], den)) { err_location(function); throw "error converting operands"; } if(num-den > mp_integer(0)) { err_location(function); throw "probability has to be smaller than 1"; } if(den == mp_integer(0)) { err_location(function); throw "denominator may not be zero"; } rationalt numerator(num), denominator(den); rationalt prob = numerator / denominator; rhs.copy_to_operands(from_rational(prob)); code_assignt assignment(lhs, rhs); assignment.add_source_location()=function.source_location(); copy(assignment, ASSIGN, dest); }
typet c_typecheck_baset::enum_underlying_type( const mp_integer &min_value, const mp_integer &max_value, bool is_packed) const { if(config.ansi_c.mode==configt::ansi_ct::flavourt::VISUAL_STUDIO) { return signed_int_type(); } else { if(min_value<0) { // We'll want a signed type. if(is_packed) { // If packed, there are smaller options. if(max_value<(mp_integer(1)<<(config.ansi_c.char_width-1)) && min_value>=-(mp_integer(1)<<(config.ansi_c.char_width-1))) return signed_char_type(); else if(max_value<(mp_integer(1)<<(config.ansi_c.short_int_width-1)) && min_value>=-(mp_integer(1)<<(config.ansi_c.short_int_width-1))) return signed_short_int_type(); } if(max_value<(mp_integer(1)<<(config.ansi_c.int_width-1)) && min_value>=-(mp_integer(1)<<(config.ansi_c.int_width-1))) return signed_int_type(); else if(max_value<(mp_integer(1)<<(config.ansi_c.long_int_width-1)) && min_value>=-(mp_integer(1)<<(config.ansi_c.long_int_width-1))) return signed_long_int_type(); else return signed_long_long_int_type(); } else { // We'll want an unsigned type. if(is_packed) { // If packed, there are smaller options. if(max_value<(mp_integer(1)<<config.ansi_c.char_width)) return unsigned_char_type(); else if(max_value<(mp_integer(1)<<config.ansi_c.short_int_width)) return unsigned_short_int_type(); } if(max_value<(mp_integer(1)<<config.ansi_c.int_width)) return unsigned_int_type(); else if(max_value<(mp_integer(1)<<config.ansi_c.long_int_width)) return unsigned_long_int_type(); else return unsigned_long_long_int_type(); } } }
exprt convert_float_literal(const std::string &src) { mp_integer significand; mp_integer exponent; bool is_float, is_long, is_fixed, is_accum; unsigned base; parse_float(src, significand, exponent, base, is_float, is_long, is_fixed, is_accum); exprt result=exprt(ID_constant); result.set(ID_C_cformat, src); // In ANSI-C, float literals are double by default // unless marked with 'f'. if(is_float) { result.type()=float_type(); result.type().set(ID_C_cpp_type, ID_float); } else if(is_long) { result.type()=long_double_type(); result.type().set(ID_C_cpp_type, ID_long_double); } else if(is_fixed) { result.type()=fixed_type(); result.type().set(ID_C_cpp_type, ID_fixed); } else if(is_accum) { result.type()=accum_type(); result.type().set(ID_C_cpp_type, ID_accum); } else { result.type()=double_type(); // default result.type().set(ID_C_cpp_type, ID_double); } if(config.ansi_c.use_fixed_for_float || is_fixed || is_accum) { unsigned width=result.type().get_int(ID_width); unsigned fraction_bits; const irep_idt integer_bits=result.type().get(ID_integer_bits); assert(width!=0); if(is_fixed) { fraction_bits = width - 1; } else if(is_accum) { fraction_bits = width - 9; } else if(integer_bits==irep_idt()) fraction_bits=width/2; // default else fraction_bits=width-safe_string2int(id2string(integer_bits)); mp_integer factor=mp_integer(1)<<fraction_bits; mp_integer value=significand*factor; if(value!=0) { if(exponent<0) value/=power(base, -exponent); else { value*=power(base, exponent); if(value>=power(2, width-1)) { // saturate: use "biggest value" value=power(2, width-1)-1; } else if(value<=-power(2, width-1)-1) { // saturate: use "smallest value" value=-power(2, width-1); } } } result.set(ID_value, integer2binary(value, width)); } else { ieee_floatt a; a.spec=to_floatbv_type(result.type()); if(base==10) a.from_base10(significand, exponent); else if(base==2) // hex a.build(significand, exponent); else assert(false); result.set(ID_value, integer2binary(a.pack(), a.spec.width())); } return result; }
void ieee_floatt::align() { // NaN? if(NaN_flag) { fraction=0; exponent=0; sign_flag=false; return; } // do sign if(fraction<0) { sign_flag=!sign_flag; fraction=-fraction; } // zero? if(fraction==0) { exponent=0; return; } // 'usual case' mp_integer f_power=power(2, spec.f); mp_integer f_power_next=power(2, spec.f+1); std::size_t lowPower2=fraction.floorPow2(); mp_integer exponent_offset=0; if(lowPower2<spec.f) // too small { exponent_offset-=(spec.f-lowPower2); assert(fraction*power(2, (spec.f-lowPower2))>=f_power); assert(fraction*power(2, (spec.f-lowPower2))<f_power_next); } else if(lowPower2>spec.f) // too large { exponent_offset+=(lowPower2-spec.f); assert(fraction/power(2, (lowPower2-spec.f))>=f_power); assert(fraction/power(2, (lowPower2-spec.f))<f_power_next); } mp_integer biased_exponent=exponent+exponent_offset+spec.bias(); // exponent too large (infinity)? if(biased_exponent>=spec.max_exponent()) { // we need to consider the rounding mode here switch(rounding_mode) { case UNKNOWN: case NONDETERMINISTIC: case ROUND_TO_EVEN: infinity_flag=true; break; case ROUND_TO_MINUS_INF: // the result of the rounding is never larger than the argument if(sign_flag) infinity_flag=true; else make_fltmax(); break; case ROUND_TO_PLUS_INF: // the result of the rounding is never smaller than the argument if(sign_flag) { make_fltmax(); sign_flag=true; // restore sign } else infinity_flag=true; break; case ROUND_TO_ZERO: if(sign_flag) { make_fltmax(); sign_flag=true; // restore sign } else make_fltmax(); // positive break; } return; // done } else if(biased_exponent<=0) // exponent too small? { // produce a denormal (or zero) mp_integer new_exponent=mp_integer(1)-spec.bias(); exponent_offset=new_exponent-exponent; } exponent+=exponent_offset; if(exponent_offset>0) { divide_and_round(fraction, power(2, exponent_offset)); // rounding might make the fraction too big! if(fraction==f_power_next) { fraction=f_power; ++exponent; } } else if(exponent_offset<0) fraction*=power(2, -exponent_offset); if(fraction==0) exponent=0; }
std::string ieee_floatt::to_string_decimal(std::size_t precision) const { std::string result; if(sign_flag) result+='-'; if((NaN_flag || infinity_flag) && !sign_flag) result+='+'; // special cases if(NaN_flag) result+="NaN"; else if(infinity_flag) result+="inf"; else if(is_zero()) { result+='0'; // add zeros, if needed if(precision>0) { result+='.'; for(std::size_t i=0; i<precision; i++) result+='0'; } } else { mp_integer _exponent, _fraction; extract_base2(_fraction, _exponent); // convert to base 10 if(_exponent>=0) { result+=integer2string(_fraction*power(2, _exponent)); // add dot and zeros, if needed if(precision>0) { result+='.'; for(std::size_t i=0; i<precision; i++) result+='0'; } } else { #if 1 mp_integer position=-_exponent; // 10/2=5 -- this makes it base 10 _fraction*=power(5, position); // apply rounding if(position>precision) { mp_integer r=power(10, position-precision); mp_integer remainder=_fraction%r; _fraction/=r; // not sure if this is the right kind of rounding here if(remainder>=r/2) ++_fraction; position=precision; } std::string tmp=integer2string(_fraction); // pad with zeros from the front, if needed while(mp_integer(tmp.size())<=position) tmp="0"+tmp; std::size_t dot=tmp.size()-integer2size_t(position); result+=std::string(tmp, 0, dot)+'.'; result+=std::string(tmp, dot, std::string::npos); // append zeros if needed for(mp_integer i=position; i<precision; ++i) result+='0'; #else result+=integer2string(_fraction); if(_exponent!=0) result+="*2^"+integer2string(_exponent); #endif } } return result; }
void ieee_floatt::align() { // NaN? if(NaN) { fraction=0; exponent=0; sign=false; return; } // do sign if(fraction<0) { sign=!sign; fraction=-fraction; } // zero? if(fraction==0) { exponent=0; return; } // 'usual case' mp_integer f_power=power(2, spec.f); mp_integer f_power_next=power(2, spec.f+1); mp_integer exponent_offset=0; if(fraction<f_power) // too small? { mp_integer tmp_fraction=fraction; while(tmp_fraction<f_power) { tmp_fraction*=2; --exponent_offset; } } else if(fraction>=f_power_next) // too big? { mp_integer tmp_fraction=fraction; while(tmp_fraction>=f_power_next) { tmp_fraction/=2; ++exponent_offset; } } mp_integer biased_exponent=exponent+exponent_offset+spec.bias(); // exponent too large (infinity)? if(biased_exponent>=spec.max_exponent()) infinity=true; else if(biased_exponent<=0) // exponent too small? { // produce a denormal (or zero) mp_integer new_exponent=mp_integer(1)-spec.bias(); exponent_offset=new_exponent-exponent; } exponent+=exponent_offset; if(exponent_offset>0) { divide_and_round(fraction, power(2, exponent_offset)); // rounding might make the fraction too big! if(fraction==f_power_next) { fraction=f_power; ++exponent; } } else if(exponent_offset<0) fraction*=power(2, -exponent_offset); if(fraction==0) exponent=0; }
std::string ieee_floatt::format(const format_spect &format_spec) const { std::string result; if(sign) result+="-"; if((NaN || infinity) && !sign) result+="+"; // special cases if(NaN) result+="NaN"; else if(infinity) result+="inf"; else if(is_zero()) { result+="0"; // add zeros, if needed if(format_spec.precision>0) { result+='.'; for(unsigned i=0; i<format_spec.precision; i++) result+='0'; } } else { mp_integer _exponent, _fraction; extract(_fraction, _exponent); // convert to base 10 if(_exponent>=0) { result+=integer2string(_fraction*power(2, _exponent)); // add zeros, if needed if(format_spec.precision>0) { result+='.'; for(unsigned i=0; i<format_spec.precision; i++) result+='0'; } } else { #if 1 mp_integer position=-_exponent; // 10/2=5 -- this makes it base 10 _fraction*=power(5, position); // apply rounding if(position>format_spec.precision) { mp_integer r=power(10, position-format_spec.precision); mp_integer remainder=_fraction%r; _fraction/=r; // not sure if this is the right kind of rounding here if(remainder>=r/2) ++_fraction; position=format_spec.precision; } std::string tmp=integer2string(_fraction); // pad with zeros from the front, if needed while(mp_integer(tmp.size())<=position) tmp="0"+tmp; unsigned dot=tmp.size()-integer2long(position); result+=std::string(tmp, 0, dot)+'.'; result+=std::string(tmp, dot, std::string::npos); // append zeros if needed for(mp_integer i=position; i<format_spec.precision; ++i) result+='0'; #else result+=integer2string(_fraction); if(_exponent!=0) result+="*2^"+integer2string(_exponent); #endif } } while(result.size()<format_spec.min_width) result=" "+result; return result; }
bool clang_c_convertert::convert_float_literal( const clang::FloatingLiteral &floating_literal, exprt &dest) { if(!config.ansi_c.use_fixed_for_float) { std::cerr << "floatbv unsupported, sorry" << std::endl; return false; } typet type; if(get_type(floating_literal.getType(), type)) return true; llvm::APFloat val = floating_literal.getValue(); llvm::SmallVector<char, 32> string; val.toString(string, 32, 0); unsigned width = bv_width(type); mp_integer value; std::string float_string; if(!val.isInfinity()) { mp_integer significand; mp_integer exponent; float_string = parse_float(string, significand, exponent); unsigned fraction_bits; const std::string &integer_bits = type.integer_bits().as_string(); if (integer_bits == "") fraction_bits = width / 2; else fraction_bits = width - atoi(integer_bits.c_str()); mp_integer factor = mp_integer(1) << fraction_bits; value = significand * factor; if(exponent < 0) value /= power(10, -exponent); else { value *= power(10, exponent); if(value <= -power(2, width - 1) - 1) { // saturate: use "smallest value" value = -power(2, width - 1); } } } else { // saturate: use "biggest value" value = power(2, width - 1) - 1; float_string = "2147483647.99999999976716935634613037109375"; } dest = constant_exprt( integer2binary(value, bv_width(type)), float_string, type); return false; }
void convert_float_literal(const std::string &src, exprt &dest) { mp_integer significand; mp_integer exponent; bool is_float, is_long; unsigned base; parse_float(src, significand, exponent, base, is_float, is_long); dest = exprt("constant"); dest.cformat(src); if(is_float) { dest.type() = float_type(); dest.type().set("#cpp_type", "float"); } else if(is_long) { dest.type() = long_double_type(); dest.type().set("#cpp_type", "long_double"); } else { dest.type() = double_type(); dest.type().set("#cpp_type", "double"); } if(config.ansi_c.use_fixed_for_float) { unsigned width = atoi(dest.type().width().c_str()); unsigned fraction_bits; const std::string &integer_bits = dest.type().integer_bits().as_string(); if(integer_bits == "") fraction_bits = width / 2; else fraction_bits = width - atoi(integer_bits.c_str()); mp_integer factor = mp_integer(1) << fraction_bits; mp_integer value = significand * factor; if(value != 0) { if(exponent < 0) value /= power(base, -exponent); else { value *= power(base, exponent); if(value >= power(2, width - 1)) { // saturate: use "biggest value" value = power(2, width - 1) - 1; } else if(value <= -power(2, width - 1) - 1) { // saturate: use "smallest value" value = -power(2, width - 1); } } } dest.value(integer2binary(value, width)); } else { ieee_floatt a; a.spec = to_floatbv_type(dest.type()); if(base == 10) a.from_base10(significand, exponent); else if(base == 2) // hex a.build(significand, exponent); else assert(false); dest.value(integer2binary(a.pack(), a.spec.width())); } }
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); }