expr2tc from_integer(const mp_integer &int_value, const type2tc &type) { switch(type->type_id) { case type2t::bool_id: return !int_value.is_zero() ? gen_true_expr() : gen_false_expr(); case type2t::unsignedbv_id: case type2t::signedbv_id: return constant_int2tc(type, int_value); case type2t::fixedbv_id: { constant_fixedbv2tc f(fixedbvt(fixedbv_spect( to_fixedbv_type(type).width, to_fixedbv_type(type).integer_bits))); f->value.from_integer(int_value); return f; } case type2t::floatbv_id: { constant_floatbv2tc f(ieee_floatt(ieee_float_spect( to_floatbv_type(type).fraction, to_floatbv_type(type).exponent))); f->value.from_integer(int_value); return f; } default: abort(); } }
void goto_symext::track_new_pointer( const expr2tc &ptr_obj, const type2tc &new_type, const expr2tc &size) { // Also update all the accounting data. // Mark that object as being dynamic, in the __ESBMC_is_dynamic array type2tc sym_type = type2tc(new array_type2t(get_bool_type(), expr2tc(), true)); symbol2tc sym(sym_type, dyn_info_arr_name); index2tc idx(get_bool_type(), sym, ptr_obj); expr2tc truth = gen_true_expr(); symex_assign(code_assign2tc(idx, truth), true); symbol2tc valid_sym(sym_type, valid_ptr_arr_name); index2tc valid_index_expr(get_bool_type(), valid_sym, ptr_obj); truth = gen_true_expr(); symex_assign(code_assign2tc(valid_index_expr, truth), true); symbol2tc dealloc_sym(sym_type, deallocd_arr_name); index2tc dealloc_index_expr(get_bool_type(), dealloc_sym, ptr_obj); expr2tc falseity = gen_false_expr(); symex_assign(code_assign2tc(dealloc_index_expr, falseity), true); type2tc sz_sym_type = type2tc(new array_type2t(pointer_type2(), expr2tc(), true)); symbol2tc sz_sym(sz_sym_type, alloc_size_arr_name); index2tc sz_index_expr(get_bool_type(), sz_sym, ptr_obj); expr2tc object_size_exp; if(is_nil_expr(size)) { try { mp_integer object_size = type_byte_size(new_type); object_size_exp = constant_int2tc(pointer_type2(), object_size.to_ulong()); } catch(array_type2t::dyn_sized_array_excp *e) { object_size_exp = typecast2tc(pointer_type2(), e->size); } } else { object_size_exp = size; } symex_assign(code_assign2tc(sz_index_expr, object_size_exp), true); }
smt_astt array_sym_smt_ast::update( smt_convt *ctx, smt_astt value, unsigned int idx, expr2tc idx_expr) const { const array_type2t array_type = to_array_type(sort->get_tuple_type()); const struct_union_data &data = ctx->get_type_def(array_type.subtype); expr2tc index; if(is_nil_expr(idx_expr)) { index = constant_int2tc(ctx->make_array_domain_type(array_type), BigInt(idx)); } else { index = idx_expr; } std::string name = ctx->mk_fresh_name("tuple_array_update::") + "."; tuple_sym_smt_astt result = new array_sym_smt_ast(ctx, sort, name); // Iterate over all members. They are _all_ indexed and updated. unsigned int i = 0; for(auto const &it : data.members) { type2tc arrtype( new array_type2t(it, array_type.array_size, array_type.size_is_infinite)); // Project and update a field in 'this' smt_astt field = project(ctx, i); smt_astt resval = value->project(ctx, i); smt_astt updated = field->update(ctx, resval, 0, index); // Now equality it into the result object smt_astt res_field = result->project(ctx, i); updated->assign(ctx, res_field); i++; } return result; }
smt_astt smt_convt::convert_byte_update(const expr2tc &expr) { const byte_update2t &data = to_byte_update2t(expr); assert(is_scalar_type(data.source_value) && "Byte update only works on " "scalar variables now"); if (!is_constant_int2t(data.source_offset)) { expr2tc source = data.source_value; unsigned int src_width = source->type->get_width(); if (!is_bv_type(source)) source = typecast2tc(get_uint_type(src_width), source); expr2tc offs = data.source_offset; // Endian-ness: if we're in non-"native" endian-ness mode, then flip the // offset distance. The rest of these calculations will still apply. if (data.big_endian) { auto data_size = type_byte_size(*source->type); constant_int2tc data_size_expr(source->type, data_size - 1); sub2tc sub(source->type, data_size_expr, offs); offs = sub; } if (offs->type->get_width() != src_width) offs = typecast2tc(get_uint_type(src_width), offs); expr2tc update = data.update_value; if (update->type->get_width() != src_width) update = typecast2tc(get_uint_type(src_width), update); // The approach: mask, shift and or. XXX, byte order? // Massively inefficient. expr2tc eight = constant_int2tc(get_uint_type(src_width), BigInt(8)); expr2tc effs = constant_int2tc(eight->type, BigInt(255)); offs = mul2tc(eight->type, offs, eight); expr2tc shl = shl2tc(offs->type, effs, offs); expr2tc noteffs = bitnot2tc(effs->type, shl); source = bitand2tc(source->type, source, noteffs); expr2tc shl2 = shl2tc(offs->type, update, offs); return convert_ast(bitor2tc(offs->type, shl2, source)); } // We are merging two values: an 8 bit update value, and a larger source // value that we will have to merge it into. Start off by collecting // information about the source values and their widths. assert(is_number_type(data.source_value->type) && "Byte update of unsupported data type"); smt_astt value, src_value; unsigned int width_op0, width_op2, src_offset; value = convert_ast(data.update_value); src_value = convert_ast(data.source_value); width_op2 = data.update_value->type->get_width(); width_op0 = data.source_value->type->get_width(); src_offset = to_constant_int2t(data.source_offset).constant_value.to_ulong(); // Flip location if we're in big-endian mode if (data.big_endian) { unsigned int data_size = type_byte_size(*data.source_value->type).to_ulong() - 1; src_offset = data_size - src_offset; } if (int_encoding) { std::cerr << "Can't byte update in integer mode; rerun in bitvector mode" << std::endl; abort(); } // Assertion some of our assumptions, which broadly mean that we'll only work // on bytes that are going into non-byte words assert(width_op2 == 8 && "Can't byte update non-byte operations"); assert(width_op2 != width_op0 && "Can't byte update bytes, sorry"); smt_astt top, middle, bottom; // Build in three parts: the most significant bits, any in the middle, and // the bottom, of the reconstructed / merged output. There might not be a // middle if the update byte is at the top or the bottom. unsigned int top_of_update = (8 * src_offset) + 8; unsigned int bottom_of_update = (8 * src_offset); if (top_of_update == width_op0) { top = value; } else { smt_sortt s = mk_sort(SMT_SORT_BV, width_op0 - top_of_update, false); top = mk_extract(src_value, width_op0 - 1, top_of_update, s); } if (top == value) { middle = NULL; } else { middle = value; } if (src_offset == 0) { middle = NULL; bottom = value; } else { smt_sortt s = mk_sort(SMT_SORT_BV, bottom_of_update, false); bottom = mk_extract(src_value, bottom_of_update - 1, 0, s); } // Concatenate the top and bottom, and possible middle, together. smt_astt concat; if (middle != NULL) { smt_sortt s = mk_sort(SMT_SORT_BV, width_op0 - bottom_of_update, false); concat = mk_func_app(s, SMT_FUNC_CONCAT, top, middle); } else { concat = top; } return mk_func_app(src_value->sort, SMT_FUNC_CONCAT, concat, bottom); }