Ejemplo n.º 1
0
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();
  }
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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);
}