Beispiel #1
0
static void build_object_descriptor_rec(
  const namespacet &ns,
  const exprt &expr,
  object_descriptor_exprt &dest)
{
  const signedbv_typet index_type(config.ansi_c.pointer_width);

  if(expr.id()==ID_index)
  {
    const index_exprt &index=to_index_expr(expr);

    build_object_descriptor_rec(ns, index.array(), dest);

    exprt sub_size=size_of_expr(expr.type(), ns);
    assert(sub_size.is_not_nil());

    dest.offset()=
      plus_exprt(dest.offset(),
                 mult_exprt(typecast_exprt(index.index(), index_type),
                            typecast_exprt(sub_size, index_type)));
  }
  else if(expr.id()==ID_member)
  {
    const member_exprt &member=to_member_expr(expr);
    const exprt &struct_op=member.struct_op();

    build_object_descriptor_rec(ns, struct_op, dest);

    exprt offset=member_offset_expr(member, ns);
    assert(offset.is_not_nil());

    dest.offset()=
      plus_exprt(dest.offset(),
                 typecast_exprt(offset, index_type));
  }
  else if(expr.id()==ID_byte_extract_little_endian ||
          expr.id()==ID_byte_extract_big_endian)
  {
    const byte_extract_exprt &be=to_byte_extract_expr(expr);

    dest.object()=be.op();

    build_object_descriptor_rec(ns, be.op(), dest);

    dest.offset()=
      plus_exprt(dest.offset(),
                 typecast_exprt(to_byte_extract_expr(expr).offset(),
                                index_type));
  }
  else if(expr.id()==ID_typecast)
  {
    const typecast_exprt &tc=to_typecast_expr(expr);

    dest.object()=tc.op();

    build_object_descriptor_rec(ns, tc.op(), dest);
  }
}
Beispiel #2
0
exprt address_canonizer(
  const exprt &address,
  const namespacet &ns)
{
  assert(ns.follow(address.type()).id()==ID_pointer);

  if(address.id()==ID_address_of)
  {
    const address_of_exprt &address_of_expr=
      to_address_of_expr(address);
    const exprt &object=address_of_expr.object();

    if(object.id()==ID_dereference)
    {
      // &*x ---> x
      return to_dereference_expr(object).pointer();
    }
    else if(object.id()==ID_member)
    {
      // get offset
      exprt offset=member_offset_expr(to_member_expr(object), ns);

      // &x.m  ---> (&x)+offset

      address_of_exprt address_of_expr(to_member_expr(object).struct_op());
      exprt rec_result=address_canonizer(address_of_expr, ns); // rec. call

      pointer_typet byte_pointer(unsigned_char_type());
      typecast_exprt typecast_expr(rec_result, byte_pointer);
      plus_exprt sum(typecast_expr, offset);
      if(sum.type()!=address.type())
        sum.make_typecast(address.type());

      return sum;
    }
    else if(object.id()==ID_index)
    {
      // &(x[i]) ---> (&x)+i
      address_of_exprt address_of_expr(to_index_expr(object).array());
      exprt rec_result=address_canonizer(address_of_expr, ns); // rec. call

      pointer_typet pointer_type;
      pointer_type.subtype()=object.type();
      typecast_exprt typecast_expr(rec_result, pointer_type);
      plus_exprt sum(typecast_expr, to_index_expr(object).index());
      if(sum.type()!=address.type())
        sum.make_typecast(address.type());

      return sum;
    }
    else if(object.id()==ID_symbol && is_iterator(object))
    {
      // address of iterator is dereferenced to a corresponding symbol -
      // will be bound to real address during analysis
      symbol_exprt iterator_addr(
        id2string(to_symbol_expr(object).get_identifier())+"'addr",
        address.type());
      return iterator_addr;
    }
    else
      return address;
  }
  else if(address.id()==ID_plus ||
          address.id()==ID_minus)
  {
    // one of the operands needs to be a pointer
    assert(address.operands().size()==2);
    exprt tmp=address;
    if(ns.follow(tmp.op0().type()).id()==ID_pointer)
    {
      tmp.op0()=address_canonizer(tmp.op0(), ns);
      return tmp;
    }
    else if(ns.follow(tmp.op1().type()).id()==ID_pointer)
    {
      tmp.op1()=address_canonizer(tmp.op1(), ns);
      return tmp;
    }
    else
      return tmp;
  }
  else if(address.id()==ID_if)
  {
    if_exprt tmp=to_if_expr(address);
    tmp.true_case()=address_canonizer(tmp.true_case(), ns);
    tmp.false_case()=address_canonizer(tmp.false_case(), ns);
    return tmp;
  }
  else if(address.id()==ID_typecast)
  {
    typecast_exprt tmp=to_typecast_expr(address);

    // cast from another pointer?
    if(tmp.op().type().id()==ID_pointer)
    {
      tmp.op()=address_canonizer(tmp.op(), ns);
      return tmp;
    }

    return address;
  }
  else
    return address;
}
Beispiel #3
0
exprt dereferencet::read_object(
  const exprt &object,
  const exprt &offset,
  const typet &type)
{
  const typet &object_type=ns.follow(object.type());
  const typet &dest_type=ns.follow(type);

  // is the object an array with matching subtype?

  exprt simplified_offset=simplify_expr(offset, ns);

  // check if offset is zero
  if(simplified_offset.is_zero())
  {
    // check type
    if(base_type_eq(object_type, dest_type, ns))
    {
      return object; // trivial case
    }
    else if(type_compatible(object_type, dest_type))
    {
      // the type differs, but we can do this with a typecast
      return typecast_exprt(object, dest_type);
    }
  }

  if(object.id()==ID_index)
  {
    const index_exprt &index_expr=to_index_expr(object);

    exprt index=index_expr.index();

    // multiply index by object size
    exprt size=size_of_expr(object_type, ns);

    if(size.is_nil())
      throw "dereference failed to get object size for index";

    index.make_typecast(simplified_offset.type());
    size.make_typecast(index.type());

    exprt new_offset=plus_exprt(simplified_offset, mult_exprt(index, size));

    return read_object(index_expr.array(), new_offset, type);
  }
  else if(object.id()==ID_member)
  {
    const member_exprt &member_expr=to_member_expr(object);

    const typet &compound_type=
      ns.follow(member_expr.struct_op().type());

    if(compound_type.id()==ID_struct)
    {
      const struct_typet &struct_type=
        to_struct_type(compound_type);

      exprt member_offset=member_offset_expr(
        struct_type, member_expr.get_component_name(), ns);

      if(member_offset.is_nil())
        throw "dereference failed to get member offset";

      member_offset.make_typecast(simplified_offset.type());

      exprt new_offset=plus_exprt(simplified_offset, member_offset);

      return read_object(member_expr.struct_op(), new_offset, type);
    }
    else if(compound_type.id()==ID_union)
    {
      // Unions are easy: the offset is always zero,
      // so simply pass down.
      return read_object(member_expr.struct_op(), offset, type);
    }
  }

  // check if we have an array with the right subtype
  if(object_type.id()==ID_array &&
     base_type_eq(object_type.subtype(), dest_type, ns))
  {
    // check proper alignment
    exprt size=size_of_expr(dest_type, ns);

    if(size.is_not_nil())
    {
      mp_integer size_constant, offset_constant;
      if(!to_integer(simplify_expr(size, ns), size_constant) &&
         !to_integer(simplified_offset, offset_constant) &&
         (offset_constant%size_constant)==0)
      {
        // Yes! Can use index expression!
        mp_integer index_constant=offset_constant/size_constant;
        exprt index_expr=from_integer(index_constant, size.type());
        return index_exprt(object, index_expr, dest_type);
      }
    }
  }

  // give up and use byte_extract
  return binary_exprt(object, byte_extract_id(), simplified_offset, dest_type);
}