示例#1
0
exprt ssa_alias_guard(
  const exprt &e1,
  const exprt &e2,
  const namespacet &ns)
{
  exprt a1=address_canonizer(address_of_exprt(e1), ns);
  exprt a2=address_canonizer(address_of_exprt(e2), ns);
  
  // in some cases, we can use plain address equality,
  // as we assume well-aligned-ness
  mp_integer size1=pointer_offset_size(e1.type(), ns);
  mp_integer size2=pointer_offset_size(e2.type(), ns);
  
  if(size1>=size2)
  {
    exprt lhs=a1;
    exprt rhs=a2;
    if(ns.follow(rhs.type())!=ns.follow(lhs.type()))
      rhs=typecast_exprt(rhs, lhs.type());
  
    return equal_exprt(lhs, rhs);
  }
  
  return same_object(a1, a2);
}
示例#2
0
exprt ssa_alias_guard(
  const exprt &e1,
  const exprt &e2,
  const namespacet &ns)
{
  exprt a1=address_canonizer(address_of_exprt(e1), ns);
  // TODO: We should compare 'base' pointers here because
  // we have a higher chance that there was no pointer arithmetic
  // on the base pointer than that the result of the pointer
  // arithmetic points to a base pointer.
  // The following hack does that:
  if(a1.id()==ID_plus)
    a1=a1.op0();

  exprt a2=address_canonizer(address_of_exprt(e2), ns);

  // in some cases, we can use plain address equality,
  // as we assume well-aligned-ness
  mp_integer size1=pointer_offset_size(e1.type(), ns);
  mp_integer size2=pointer_offset_size(e2.type(), ns);

  if(size1>=size2)
  {
    exprt lhs=a1;
    exprt rhs=a2;
    if(ns.follow(rhs.type())!=ns.follow(lhs.type()))
      rhs=typecast_exprt(rhs, lhs.type());

    return equal_exprt(lhs, rhs);
  }

  return same_object(a1, a2);
}
示例#3
0
void rd_range_domaint::assign(
  const namespacet &ns,
  locationt from,
  const exprt &lhs,
  const mp_integer &range_start,
  const mp_integer &size)
{
  if(lhs.id()==ID_member)
    assign(ns, from, to_member_expr(lhs).struct_op(), range_start, size);
  else if(lhs.id()==ID_index)
    assign(ns, from, to_index_expr(lhs).array(), range_start, size);
  else
  {
    const symbol_exprt &symbol=to_symbol_expr(lhs);
    const irep_idt identifier=symbol.get_identifier();

    if(range_start>=0)
    {
      kill(from, identifier, range_start, size);
      gen(from, identifier, range_start, size);
    }
    else
    {
      mp_integer full_size=pointer_offset_size(ns, symbol.type());
      gen(from, identifier, 0, full_size);
    }
  }
}
mp_integer compute_pointer_offset(
  const namespacet &ns,
  const exprt &expr)
{
  if(expr.id()==ID_symbol)
    return 0;
  else if(expr.id()==ID_index)
  {
    assert(expr.operands().size()==2);
    
    const typet &array_type=ns.follow(expr.op0().type());
    assert(array_type.id()==ID_array);

    mp_integer o=compute_pointer_offset(ns, expr.op0());
    
    if(o!=-1)
    {
      mp_integer sub_size=
        pointer_offset_size(ns, array_type.subtype());

      mp_integer i;

      if(sub_size!=0 && !to_integer(expr.op1(), i))
        return o+i*sub_size;
    }
      
    // don't know
  }
  else if(expr.id()==ID_member)
  {
    assert(expr.operands().size()==1);
    const typet &type=ns.follow(expr.op0().type());
    
    assert(type.id()==ID_struct ||
           type.id()==ID_union);

    mp_integer o=compute_pointer_offset(ns, expr.op0());

    if(o!=-1)
    {    
      if(type.id()==ID_union)
        return o;
    
      return o+member_offset(
        ns, to_struct_type(type), expr.get(ID_component_name));
    }
  }
  else if(expr.id()==ID_string_constant)
    return 0;

  return -1; // don't know
}
示例#5
0
void rd_range_domaint::transform(
  const namespacet &ns,
  locationt from,
  locationt to)
{
  if(from->is_dead())
  {
    const symbol_exprt &symbol=
      to_symbol_expr(to_code_dead(from->code).symbol());
    values.erase(symbol.get_identifier());
    return;
  }
  else if(!from->is_assign())
    return;

  const exprt &lhs=to_code_assign(from->code).lhs();

  if(lhs.id()==ID_complex_real ||
          lhs.id()==ID_complex_imag)
  {
    assert(lhs.type().id()==ID_complex);
    mp_integer offset=compute_pointer_offset(ns, lhs.op0());
    mp_integer sub_size=pointer_offset_size(ns, lhs.type().subtype());

    assign(
      ns,
      from,
      lhs.op0(),
      offset+((offset==-1 || lhs.id()==ID_complex_real) ? 0 : sub_size),
      sub_size);
  }
  else
  {
    mp_integer size=pointer_offset_size(ns, lhs.type());

    assign(ns, from, lhs, size);
  }
}
示例#6
0
exprt ssa_alias_value(
  const exprt &e1,
  const exprt &e2,
  const namespacet &ns)
{
  const typet &e1_type=ns.follow(e1.type());
  const typet &e2_type=ns.follow(e2.type());

  // type matches?
  if(e1_type==e2_type)
    return e2;

  exprt a1=address_canonizer(address_of_exprt(e1), ns);
  exprt a2=address_canonizer(address_of_exprt(e2), ns);

  exprt offset1=pointer_offset(a1);

  // array index possible?
  if(e2_type.id()==ID_array &&
     e1_type==ns.follow(e2_type.subtype()))
  {
    // this assumes well-alignedness

    mp_integer element_size=pointer_offset_size(e2_type.subtype(), ns);

    if(element_size==1)
      return index_exprt(e2, offset1, e1.type());
    else if(element_size>1)
    {
      exprt index=
        div_exprt(offset1, from_integer(element_size, offset1.type()));
      return index_exprt(e2, index, e1.type());
    }
  }

  byte_extract_exprt byte_extract(byte_extract_id(), e1.type());
  byte_extract.op()=e2;
  byte_extract.offset()=offset1;

  return byte_extract;
}
mp_integer member_offset(
  const namespacet &ns,
  const struct_typet &type,
  const irep_idt &member)
{
  const struct_typet::componentst &components=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_name()==member) break;
    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; // give up
      result+=sub_size;
    }
  }
  
  return result;
}
示例#8
0
value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
  const exprt &what,
  const modet mode,
  const exprt &pointer_expr,
  const guardt &guard)
{
  const typet &dereference_type=
    ns.follow(pointer_expr.type()).subtype();

  if(what.id()==ID_unknown ||
     what.id()==ID_invalid)
  {
    invalid_pointer(pointer_expr, guard);
    return valuet();
  }

  if(what.id()!=ID_object_descriptor)
    throw "unknown points-to: "+what.id_string();

  const object_descriptor_exprt &o=to_object_descriptor_expr(what);

  const exprt &root_object=o.root_object();
  const exprt &object=o.object();

  #if 0
  std::cout << "O: " << from_expr(ns, "", root_object) << '\n';
  #endif

  valuet result;

  if(root_object.id()=="NULL-object")
  {
    if(options.get_bool_option("pointer-check"))
    {
      guardt tmp_guard(guard);

      if(o.offset().is_zero())
      {
        tmp_guard.add(null_pointer(pointer_expr));

        dereference_callback.dereference_failure(
          "pointer dereference",
          "NULL pointer", tmp_guard);
      }
      else
      {
        tmp_guard.add(null_object(pointer_expr));

        dereference_callback.dereference_failure(
          "pointer dereference",
          "NULL plus offset pointer", tmp_guard);
      }
    }
  }
  else if(root_object.id()==ID_dynamic_object)
  {
    // const dynamic_object_exprt &dynamic_object=
    //  to_dynamic_object_expr(root_object);

    // the object produced by malloc
    exprt malloc_object=
      ns.lookup(CPROVER_PREFIX "malloc_object").symbol_expr();

    exprt is_malloc_object=same_object(pointer_expr, malloc_object);

    // constraint that it actually is a dynamic object
    exprt dynamic_object_expr(ID_dynamic_object, bool_typet());
    dynamic_object_expr.copy_to_operands(pointer_expr);

    // this is also our guard
    result.pointer_guard=dynamic_object_expr;

    // can't remove here, turn into *p
    result.value=dereference_exprt(pointer_expr, dereference_type);

    if(options.get_bool_option("pointer-check"))
    {
      // if(!dynamic_object.valid().is_true())
      {
        // check if it is still alive
        guardt tmp_guard(guard);
        tmp_guard.add(deallocated(pointer_expr, ns));
        dereference_callback.dereference_failure(
          "pointer dereference",
          "dynamic object deallocated",
          tmp_guard);
      }

      if(options.get_bool_option("bounds-check"))
      {
        if(!o.offset().is_zero())
        {
          // check lower bound
          guardt tmp_guard(guard);
          tmp_guard.add(is_malloc_object);
          tmp_guard.add(
            dynamic_object_lower_bound(
              pointer_expr,
              ns,
              nil_exprt()));
          dereference_callback.dereference_failure(
            "pointer dereference",
            "dynamic object lower bound", tmp_guard);
        }

        {
          // check upper bound

          // we check SAME_OBJECT(__CPROVER_malloc_object, p) &&
          //          POINTER_OFFSET(p)+size>__CPROVER_malloc_size

          guardt tmp_guard(guard);
          tmp_guard.add(is_malloc_object);
          tmp_guard.add(
            dynamic_object_upper_bound(
              pointer_expr,
              dereference_type,
              ns,
              size_of_expr(dereference_type, ns)));
          dereference_callback.dereference_failure(
            "pointer dereference",
            "dynamic object upper bound", tmp_guard);
        }
      }
    }
  }
  else if(root_object.id()==ID_integer_address)
  {
    // This is stuff like *((char *)5).
    // This is turned into an access to __CPROVER_memory[...].

    if(language_mode==ID_java)
    {
      result.value=nil_exprt();
      return result;
    }

    const symbolt &memory_symbol=ns.lookup(CPROVER_PREFIX "memory");
    exprt symbol_expr=symbol_exprt(memory_symbol.name, memory_symbol.type);

    if(base_type_eq(
         ns.follow(memory_symbol.type).subtype(),
         dereference_type, ns))
    {
      // Types match already, what a coincidence!
      // We can use an index expression.

      exprt index_expr=index_exprt(symbol_expr, pointer_offset(pointer_expr));
      index_expr.type()=ns.follow(memory_symbol.type).subtype();
      result.value=index_expr;
    }
    else if(dereference_type_compare(
              ns.follow(memory_symbol.type).subtype(),
              dereference_type))
    {
      exprt index_expr=index_exprt(symbol_expr, pointer_offset(pointer_expr));
      index_expr.type()=ns.follow(memory_symbol.type).subtype();
      result.value=typecast_exprt(index_expr, dereference_type);
    }
    else
    {
      // We need to use byte_extract.
      // Won't do this without a commitment to an endianness.

      if(config.ansi_c.endianness==configt::ansi_ct::endiannesst::NO_ENDIANNESS)
      {
      }
      else
      {
        exprt byte_extract(byte_extract_id(), dereference_type);
        byte_extract.copy_to_operands(
          symbol_expr, pointer_offset(pointer_expr));
        result.value=byte_extract;
      }
    }
  }
  else
  {
    // something generic -- really has to be a symbol
    address_of_exprt object_pointer(object);

    if(o.offset().is_zero())
    {
      equal_exprt equality(pointer_expr, object_pointer);

      if(ns.follow(equality.lhs().type())!=ns.follow(equality.rhs().type()))
        equality.lhs().make_typecast(equality.rhs().type());

      result.pointer_guard=equality;
    }
    else
    {
      result.pointer_guard=same_object(pointer_expr, object_pointer);
    }

    guardt tmp_guard(guard);
    tmp_guard.add(result.pointer_guard);

    valid_check(object, tmp_guard, mode);

    const typet &object_type=ns.follow(object.type());
    const exprt &root_object=o.root_object();
    const typet &root_object_type=ns.follow(root_object.type());

    exprt root_object_subexpression=root_object;

    if(dereference_type_compare(object_type, dereference_type) &&
       o.offset().is_zero())
    {
      // The simplest case: types match, and offset is zero!
      // This is great, we are almost done.

      result.value=object;

      if(object_type!=ns.follow(dereference_type))
        result.value.make_typecast(dereference_type);
    }
    else if(root_object_type.id()==ID_array &&
            dereference_type_compare(
              root_object_type.subtype(),
              dereference_type))
    {
      // We have an array with a subtype that matches
      // the dereferencing type.
      // We will require well-alignedness!

      exprt offset;

      // this should work as the object is essentially the root object
      if(o.offset().is_constant())
        offset=o.offset();
      else
        offset=pointer_offset(pointer_expr);

      exprt adjusted_offset;

      // are we doing a byte?
      mp_integer element_size=
        dereference_type.id()==ID_empty?
        pointer_offset_size(char_type(), ns):
        pointer_offset_size(dereference_type, ns);

      if(element_size==1)
      {
        // no need to adjust offset
        adjusted_offset=offset;
      }
      else if(element_size<=0)
      {
        throw "unknown or invalid type size of:\n"+dereference_type.pretty();
      }
      else
      {
        exprt element_size_expr=
          from_integer(element_size, offset.type());

        adjusted_offset=binary_exprt(
          offset, ID_div, element_size_expr, offset.type());

        // TODO: need to assert well-alignedness
      }

      index_exprt index_expr=
        index_exprt(root_object, adjusted_offset, root_object_type.subtype());

      bounds_check(index_expr, tmp_guard);

      result.value=index_expr;

      if(ns.follow(result.value.type())!=ns.follow(dereference_type))
        result.value.make_typecast(dereference_type);
    }
    else if(get_subexpression_at_offset(
        root_object_subexpression,
        o.offset(),
        dereference_type,
        ns))
    {
      // Successfully found a member, array index, or combination thereof
      // that matches the desired type and offset:
      result.value=root_object_subexpression;
    }
    else
    {
      // we extract something from the root object
      result.value=o.root_object();

      // this is relative to the root object
      const exprt offset=pointer_offset(pointer_expr);

      if(memory_model(result.value, dereference_type, tmp_guard, offset))
      {
        // ok, done
      }
      else
      {
        if(options.get_bool_option("pointer-check"))
        {
          std::string msg="memory model not applicable (got `";
          msg+=from_type(ns, "", result.value.type());
          msg+="', expected `";
          msg+=from_type(ns, "", dereference_type);
          msg+="')";

          dereference_callback.dereference_failure(
            "pointer dereference",
            msg, tmp_guard);
        }

        return valuet(); // give up, no way that this is ok
      }
    }
  }

  return result;
}
exprt flatten_byte_extract(
  const exprt &src,
  const namespacet &ns)
{
  assert(src.id()==ID_byte_extract_little_endian ||
         src.id()==ID_byte_extract_big_endian);
  assert(src.operands().size()==2);

  bool little_endian;
  
  if(src.id()==ID_byte_extract_little_endian)
    little_endian=true;
  else if(src.id()==ID_byte_extract_big_endian)
    little_endian=false;
  else
    assert(false);
  
  if(src.id()==ID_byte_extract_big_endian) 
    throw "byte_extract flattening of big endian not done yet";

  unsigned width=
    integer2long(pointer_offset_size(ns, src.type()));
  
  const typet &t=src.op0().type();
  
  if(t.id()==ID_array)
  {
    const array_typet &array_type=to_array_type(t);
    const typet &subtype=array_type.subtype();
    
    // byte-array?
    if((subtype.id()==ID_unsignedbv ||
        subtype.id()==ID_signedbv) &&
       subtype.get_int(ID_width)==8)
    {
      // get 'width'-many bytes, and concatenate
      exprt::operandst op;
      op.resize(width);
      
      for(unsigned i=0; i<width; i++)
      {
        // the most significant byte comes first in the concatenation!
        unsigned offset_i=
          little_endian?(width-i-1):i;
        
        plus_exprt offset(from_integer(offset_i, src.op1().type()), src.op1());
        index_exprt index_expr(subtype);
        index_expr.array()=src.op0();
        index_expr.index()=offset;
        op[i]=index_expr;
      }
      
      if(width==1)
        return op[0];
      else // width>=2
      {
        concatenation_exprt concatenation(src.type());
        concatenation.operands().swap(op);
        return concatenation;
      }
    }
    else // non-byte array
    {
      const exprt &root=src.op0();
      const exprt &offset=src.op1();
      const typet &array_type=ns.follow(root.type());
      const typet &offset_type=ns.follow(offset.type());
      const typet &element_type=ns.follow(array_type.subtype());
      mp_integer element_width=pointer_offset_size(ns, element_type);
      
      if(element_width==-1) // failed
        throw "failed to flatten non-byte array with unknown element width";

      mp_integer result_width=pointer_offset_size(ns, src.type());
      mp_integer num_elements=(element_width+result_width-2)/element_width+1;

      // compute new root and offset
      concatenation_exprt concat(
        unsignedbv_typet(integer2long(element_width*8*num_elements)));

      exprt first_index=
        (element_width==1)?offset 
        : div_exprt(offset, from_integer(element_width, offset_type)); // 8*offset/el_w

      for(mp_integer i=num_elements; i>0; --i)
      {
        plus_exprt index(first_index, from_integer(i-1, offset_type));
        concat.copy_to_operands(index_exprt(root, index));
      }

      // the new offset is width%offset
      exprt new_offset=
        (element_width==1)?from_integer(0, offset_type):
        mod_exprt(offset, from_integer(element_width, offset_type));

      // build new byte-extract expression
      exprt tmp(src.id(), src.type());
      tmp.copy_to_operands(concat, new_offset);

      return tmp;
    }
  }
  else // non-array
  {
    // We turn that into logical right shift and extractbits
    
    const exprt &offset=src.op1();
    const typet &offset_type=ns.follow(offset.type());

    mult_exprt times_eight(offset, from_integer(8, offset_type));
        
    lshr_exprt left_shift(src.op0(), times_eight);

    extractbits_exprt extractbits;
    
    extractbits.src()=left_shift;
    extractbits.type()=src.type();
    extractbits.upper()=from_integer(width*8-1, offset_type);
    extractbits.lower()=from_integer(0, offset_type);
      
    return extractbits;
  }
}
exprt flatten_byte_update(
  const exprt &src,
  const namespacet &ns)
{
  assert(src.id()==ID_byte_update_little_endian ||
         src.id()==ID_byte_update_big_endian);
  assert(src.operands().size()==3);

  mp_integer element_size=
    pointer_offset_size(ns, src.op2().type());
  
  const typet &t=ns.follow(src.op0().type());
  
  if(t.id()==ID_array)
  {
    const array_typet &array_type=to_array_type(t);
    const typet &subtype=array_type.subtype();
    
    // array of bitvectors?
    if(subtype.id()==ID_unsignedbv ||
       subtype.id()==ID_signedbv ||
       subtype.id()==ID_floatbv)
    {
      mp_integer sub_size=pointer_offset_size(ns, subtype);
      
      if(sub_size==-1)
        throw "can't flatten byte_update for sub-type without size";

      // byte array?
      if(sub_size==1)
      {
        // apply 'array-update-with' element_size times
        exprt result=src.op0();
        
        for(mp_integer i=0; i<element_size; ++i)
        {
          exprt i_expr=from_integer(i, ns.follow(src.op1().type()));

          exprt new_value;
          
          if(i==0 && element_size==1) // bytes?
          {
            new_value=src.op2();
            if(new_value.type()!=subtype)
              new_value.make_typecast(subtype);
          }
          else
          {
            exprt byte_extract_expr(
              src.id()==ID_byte_update_little_endian?ID_byte_extract_little_endian:
              src.id()==ID_byte_update_big_endian?ID_byte_extract_big_endian:
              throw "unexpected src.id()",
              subtype);
            
            byte_extract_expr.copy_to_operands(src.op2(), i_expr);
            new_value=flatten_byte_extract(byte_extract_expr, ns);
          }

          exprt where=plus_exprt(src.op1(), i_expr);
            
          with_exprt with_expr;
          with_expr.type()=src.type();
          with_expr.old()=result;
          with_expr.where()=where;
          with_expr.new_value()=new_value;
          
          result.swap(with_expr);
        }
        
        return result;
      }
      else // sub_size!=1
      {
        if(element_size==1) // byte-granularity update
        {
          div_exprt div_offset(src.op1(), from_integer(sub_size, src.op1().type()));
          mod_exprt mod_offset(src.op1(), from_integer(sub_size, src.op1().type()));
        
          index_exprt index_expr(src.op0(), div_offset, array_type.subtype());
          
          exprt byte_update_expr(src.id(), array_type.subtype());
          byte_update_expr.copy_to_operands(index_expr, mod_offset, src.op2());

          // Call recurisvely, the array is gone!            
          exprt flattened_byte_update_expr=
            flatten_byte_update(byte_update_expr, ns);
            
          with_exprt with_expr(
            src.op0(), div_offset, flattened_byte_update_expr);
            
          return with_expr;
        }
        else
          throw "flatten_byte_update can only do byte updates of non-byte arrays right now";
      }
    }
    else
    {
      throw "flatten_byte_update can only do arrays of scalars right now";
    }
  }
  else if(t.id()==ID_signedbv ||
          t.id()==ID_unsignedbv ||
          t.id()==ID_floatbv)
  {
    // do a shift, mask and OR
    unsigned width=to_bitvector_type(t).get_width();
    
    if(element_size*8>width)
      throw "flatten_byte_update to update element that is too large";
    
    // build mask
    exprt mask=
      bitnot_exprt(
        from_integer(power(2, element_size*8)-1, unsignedbv_typet(width)));
      
    const typet &offset_type=ns.follow(src.op1().type());
    mult_exprt offset_times_eight(src.op1(), from_integer(8, offset_type));
    
    // shift the mask
    shl_exprt shl_expr(mask, offset_times_eight);

    // do the 'AND'
    bitand_exprt bitand_expr(src.op0(), mask);

    // zero-extend the value
    concatenation_exprt value_extended(
      from_integer(0, unsignedbv_typet(width-integer2long(element_size)*8)), 
      src.op2(), t);
    
    // shift the value
    shl_exprt value_shifted(value_extended, offset_times_eight);
    
    // do the 'OR'
    bitor_exprt bitor_expr(bitand_expr, value_shifted);
    
    return bitor_expr;
  }
  else
  {
    throw "flatten_byte_update can only do array and scalars right now";
  }
}
示例#11
0
文件: padding.cpp 项目: smaorus/rvt
void add_padding(struct_typet &type, const namespacet &ns)
{
  struct_typet::componentst &components=type.components();

  // first do padding for bit-fields

  {  
    unsigned padding_counter=0;
    unsigned bit_field_bits=0;

    for(struct_typet::componentst::iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      if(it->get_is_bit_field())
      {
        // count the bits
        bit_field_bits+=it->type().get_int(ID_width);
      }
      else if(bit_field_bits!=0)
      {
        // not on a byte-boundary?
        if((bit_field_bits%8)!=0)
        {
          unsigned pad=8-bit_field_bits%8;
          unsignedbv_typet padding_type;
          padding_type.set_width(pad);
          
          struct_typet::componentt component;
          component.type()=padding_type;
          component.set_name("$bit_field_pad"+i2string(padding_counter++));
          component.set_is_padding(true);
          component.set_is_bit_field(true);
          
          it=components.insert(it, component);
          it++; // skip over
        
          bit_field_bits+=pad;
        }

        bit_field_bits=0;
      }
    }

    // Add padding at the end?
    if((bit_field_bits%8)!=0)
    {
      unsigned pad=8-bit_field_bits%8;
      unsignedbv_typet padding_type;
      padding_type.set_width(pad);
      
      struct_typet::componentt component;
      component.type()=padding_type;
      component.set_name("$bit_field_pad"+i2string(padding_counter++));
      component.set_is_padding(true);
      component.set_is_bit_field(true);
      
      components.push_back(component);
    }  
  }

  // packed?
  if(type.get_bool(ID_packed))
    return; // done

  mp_integer offset=0;
  unsigned padding_counter=0;
  unsigned max_alignment=0;
  unsigned bit_field_bits=0;

  for(struct_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      it++)
  {
    // ANSI-C says that bit-fields do not get padded!
    if(it->get_is_bit_field())
    {
      // count the bits
      bit_field_bits+=it->type().get_int(ID_width);
    
      // we consider the type for max_alignment, however
      unsigned a=alignment(it->get_bit_field_type(), ns);
      if(max_alignment<a) 
        max_alignment=a;
      continue;
    }
    else if(bit_field_bits!=0)
    {
      // these are now assumed to be multiples of 8
      offset+=bit_field_bits/8;
      bit_field_bits=0;
    }
    
    const typet &it_type=it->type();
    unsigned a=alignment(it_type, ns);
    
    // check minimum alignment
    if(a<config.ansi_c.alignment)
      a=config.ansi_c.alignment;
      
    if(max_alignment<a) 
      max_alignment=a;
  
    if(a!=1)
    {
      // we may need to align it
      unsigned displacement=integer2long(offset%a);

      if(displacement!=0)
      {
        unsigned pad=a-displacement;
      
        unsignedbv_typet padding_type;
        padding_type.set_width(pad*8);
        
        struct_typet::componentt component;
        component.type()=padding_type;
        component.set_name("$pad"+i2string(padding_counter++));
        component.set_is_padding(true);
        
        it=components.insert(it, component);
        it++; // skip over
        
        offset+=pad;
      }
    }
    
    mp_integer size=pointer_offset_size(ns, it_type);
    
    if(size!=-1)
      offset+=size;
  }
  
  if(bit_field_bits!=0)
  {
    // these are now assumed to be multiples of 8
    offset+=bit_field_bits/8;
  }

  // There may be a need for 'end of struct' padding.
  // We use 'max_alignment'.

  if(max_alignment>1)
  {
    // we may need to align it
    unsigned displacement=integer2long(offset%max_alignment);

    if(displacement!=0)
    {
      unsigned pad=max_alignment-displacement;
    
      unsignedbv_typet padding_type;
      padding_type.set_width(pad*8);

      struct_typet::componentst::iterator it;
      
      // we need to insert before any 'flexible member'
      if(!components.empty() &&
         components.back().type().id()==ID_array &&
         to_array_type(components.back().type()).size().is_zero())
      {
        it=components.end();
        it--;
      }
      else
        it=components.end();

      struct_typet::componentt component;
      component.type()=padding_type;
      component.set_name("$pad"+i2string(padding_counter++));
      component.set_is_padding(true);
      
      components.insert(it, component);
    }
  }
}
示例#12
0
exprt pointer_logict::object_rec(
  const mp_integer &offset,
  const typet &pointer_type,
  const exprt &src) const
{
  if(src.type().id()==ID_array)
  {
    mp_integer size=
      pointer_offset_size(src.type().subtype(), ns);

    if(size<=0)
      return src;

    mp_integer index=offset/size;
    mp_integer rest=offset%size;
    if(rest<0)
      rest=-rest;

    index_exprt tmp(src.type().subtype());
    tmp.index()=from_integer(index, typet(ID_integer));
    tmp.array()=src;

    return object_rec(rest, pointer_type, tmp);
  }
  else if(src.type().id()==ID_struct)
  {
    const struct_typet::componentst &components=
      to_struct_type(src.type()).components();

    if(offset<0)
      return src;

    mp_integer current_offset=0;

    for(struct_typet::componentst::const_iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      assert(offset>=current_offset);

      const typet &subtype=it->type();

      mp_integer sub_size=pointer_offset_size(subtype, ns);
      assert(sub_size>0);
      mp_integer new_offset=current_offset+sub_size;

      if(new_offset>offset)
      {
        // found it
        member_exprt tmp(subtype);
        tmp.set_component_name(it->get_name());
        tmp.op0()=src;

        return object_rec(
          offset-current_offset, pointer_type, tmp);
      }

      assert(new_offset<=offset);
      current_offset=new_offset;
      assert(current_offset<=offset);
    }

    return src;
  }
  else if(src.type().id()==ID_union)
    return src;

  return src;
}
示例#13
0
文件: value_set.cpp 项目: lihaol/cbmc
void value_sett::get_value_set_rec(
  const exprt &expr,
  object_mapt &dest,
  const std::string &suffix,
  const typet &original_type,
  const namespacet &ns) const
{
  #if 0
  std::cout << "GET_VALUE_SET_REC EXPR: " << from_expr(ns, "", expr) << "\n";
  std::cout << "GET_VALUE_SET_REC SUFFIX: " << suffix << std::endl;
  #endif

  const typet &expr_type=ns.follow(expr.type());

  if(expr.id()==ID_unknown || expr.id()==ID_invalid)
  {
    insert(dest, exprt(ID_unknown, original_type));
  }
  else if(expr.id()==ID_index)
  {
    assert(expr.operands().size()==2);

    const typet &type=ns.follow(expr.op0().type());

    assert(type.id()==ID_array ||
           type.id()==ID_incomplete_array);

    get_value_set_rec(expr.op0(), dest, "[]"+suffix, original_type, ns);
  }
  else if(expr.id()==ID_member)
  {
    assert(expr.operands().size()==1);

    const typet &type=ns.follow(expr.op0().type());

    assert(type.id()==ID_struct ||
           type.id()==ID_union ||
           type.id()==ID_incomplete_struct ||
           type.id()==ID_incomplete_union);

    const std::string &component_name=
      expr.get_string(ID_component_name);

    get_value_set_rec(expr.op0(), dest,
      "."+component_name+suffix, original_type, ns);
  }
  else if(expr.id()==ID_symbol)
  {
    irep_idt identifier=to_symbol_expr(expr).get_identifier();

    // is it a pointer, integer, array or struct?
    if(expr_type.id()==ID_pointer ||
       expr_type.id()==ID_signedbv ||
       expr_type.id()==ID_unsignedbv ||
       expr_type.id()==ID_struct ||
       expr_type.id()==ID_union ||
       expr_type.id()==ID_array)
    {
      // look it up
      valuest::const_iterator v_it=
        values.find(id2string(identifier)+suffix);

      // try first component name as suffix if not yet found
      if(v_it==values.end() &&
          (expr_type.id()==ID_struct ||
           expr_type.id()==ID_union))
      {
        const struct_union_typet &struct_union_type=
          to_struct_union_type(expr_type);

        const std::string first_component_name=
          struct_union_type.components().front().get_string(ID_name);

        v_it=values.find(
            id2string(identifier)+"."+first_component_name+suffix);
      }

      // not found? try without suffix
      if(v_it==values.end())
        v_it=values.find(identifier);

      if(v_it!=values.end())
        make_union(dest, v_it->second.object_map);
      else
        insert(dest, exprt(ID_unknown, original_type));
    }
    else
      insert(dest, exprt(ID_unknown, original_type));
  }
  else if(expr.id()==ID_if)
  {
    if(expr.operands().size()!=3)
      throw "if takes three operands";

    get_value_set_rec(expr.op1(), dest, suffix, original_type, ns);
    get_value_set_rec(expr.op2(), dest, suffix, original_type, ns);
  }
  else if(expr.id()==ID_address_of)
  {
    if(expr.operands().size()!=1)
      throw expr.id_string()+" expected to have one operand";

    get_reference_set(expr.op0(), dest, ns);
  }
  else if(expr.id()==ID_dereference)
  {
    object_mapt reference_set;
    get_reference_set(expr, reference_set, ns);
    const object_map_dt &object_map=reference_set.read();

    if(object_map.begin()==object_map.end())
      insert(dest, exprt(ID_unknown, original_type));
    else
    {
      for(object_map_dt::const_iterator
          it1=object_map.begin();
          it1!=object_map.end();
          it1++)
      {
        const exprt &object=object_numbering[it1->first];
        get_value_set_rec(object, dest, suffix, original_type, ns);
      }
    }
  }
  else if(expr.id()=="reference_to")
  {
    // old stuff, will go away
    object_mapt reference_set;

    get_reference_set(expr, reference_set, ns);

    const object_map_dt &object_map=reference_set.read();

    if(object_map.begin()==object_map.end())
      insert(dest, exprt(ID_unknown, original_type));
    else
    {
      for(object_map_dt::const_iterator
          it=object_map.begin();
          it!=object_map.end();
          it++)
      {
        const exprt &object=object_numbering[it->first];
        get_value_set_rec(object, dest, suffix, original_type, ns);
      }
    }
  }
  else if(expr.is_constant())
  {
    // check if NULL
    if(expr.get(ID_value)==ID_NULL &&
       expr_type.id()==ID_pointer)
    {
      insert(dest, exprt("NULL-object", expr_type.subtype()), 0);
    }
    else if(expr_type.id()==ID_unsignedbv ||
            expr_type.id()==ID_signedbv)
    {
      // an integer constant got turned into a pointer
      insert(dest, exprt(ID_integer_address, unsigned_char_type()));
    }
    else
      insert(dest, exprt(ID_unknown, original_type));
  }
  else if(expr.id()==ID_typecast)
  {
    if(expr.operands().size()!=1)
      throw "typecast takes one operand";

    // let's see what gets converted to what

    const typet &op_type=ns.follow(expr.op0().type());

    if(op_type.id()==ID_pointer)
    {
      // pointer-to-pointer -- we just ignore these
      get_value_set_rec(expr.op0(), dest, suffix, original_type, ns);
    }
    else if(op_type.id()==ID_unsignedbv ||
            op_type.id()==ID_signedbv)
    {
      // integer-to-pointer

      if(expr.op0().is_zero())
        insert(dest, exprt("NULL-object", expr_type.subtype()), 0);
      else
      {
        // see if we have something for the integer
        object_mapt tmp;

        get_value_set_rec(expr.op0(), tmp, suffix, original_type, ns);

        if(tmp.read().size()==0)
        {
          // if not, throw in integer
          insert(dest, exprt(ID_integer_address, unsigned_char_type()));
        }
        else if(tmp.read().size()==1 &&
                object_numbering[tmp.read().begin()->first].id()==ID_unknown)
        {
          // if not, throw in integer
          insert(dest, exprt(ID_integer_address, unsigned_char_type()));
        }
        else
        {
          // use as is
          dest.write().insert(tmp.read().begin(), tmp.read().end());
        }
      }
    }
    else
      insert(dest, exprt(ID_unknown, original_type));
  }
  else if(expr.id()==ID_plus ||
          expr.id()==ID_minus)
  {
    if(expr.operands().size()<2)
      throw expr.id_string()+" expected to have at least two operands";

    object_mapt pointer_expr_set;
    mp_integer i;
    bool i_is_set=false;

    // special case for pointer+integer

    if(expr.operands().size()==2 &&
       expr_type.id()==ID_pointer)
    {
      exprt ptr_operand;

      if(expr.op0().type().id()!=ID_pointer &&
         expr.op0().is_constant())
      {
        i_is_set=!to_integer(expr.op0(), i);
        ptr_operand=expr.op1();
      }
      else
      {
        i_is_set=!to_integer(expr.op1(), i);
        ptr_operand=expr.op0();
      }

      if(i_is_set)
      {
        i*=pointer_offset_size(ptr_operand.type().subtype(), ns);

        if(expr.id()==ID_minus) i.negate();
      }

      get_value_set_rec(
        ptr_operand, pointer_expr_set, "", ptr_operand.type(), ns);
    }
    else
    {
      // we get the points-to for all operands, even integers
      forall_operands(it, expr)
      {
        get_value_set_rec(
          *it, pointer_expr_set, "", it->type(), ns);
      }
    }

    for(object_map_dt::const_iterator
        it=pointer_expr_set.read().begin();
        it!=pointer_expr_set.read().end();
        it++)
    {
      objectt object=it->second;

      // adjust by offset
      if(object.offset_is_zero() && i_is_set)
        object.offset=i;
      else
        object.offset_is_set=false;

      insert(dest, it->first, object);
    }
  }
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);
}
示例#15
0
bool simplify_exprt::simplify_pointer_offset(exprt &expr)
{
    if(expr.operands().size()!=1) return true;

    exprt &ptr=expr.op0();

    if(ptr.id()==ID_if && ptr.operands().size()==3)
    {
        if_exprt if_expr=lift_if(expr, 0);
        simplify_pointer_offset(if_expr.true_case());
        simplify_pointer_offset(if_expr.false_case());
        simplify_if(if_expr);
        expr.swap(if_expr);

        return false;
    }

    if(ptr.type().id()!=ID_pointer) return true;

    if(ptr.id()==ID_address_of)
    {
        if(ptr.operands().size()!=1) return true;

        mp_integer offset=compute_pointer_offset(ptr.op0(), ns);

        if(offset!=-1)
        {
            expr=from_integer(offset, expr.type());
            return false;
        }
    }
    else if(ptr.id()==ID_typecast) // pointer typecast
    {
        if(ptr.operands().size()!=1) return true;

        const typet &op_type=ns.follow(ptr.op0().type());

        if(op_type.id()==ID_pointer)
        {
            // Cast from pointer to pointer.
            // This just passes through, remove typecast.
            exprt tmp=ptr.op0();
            ptr=tmp;

            // recursive call
            simplify_node(expr);
            return false;
        }
        else if(op_type.id()==ID_signedbv ||
                op_type.id()==ID_unsignedbv)
        {
            // Cast from integer to pointer, say (int *)x.

            if(ptr.op0().is_constant())
            {
                // (T *)0x1234 -> 0x1234
                exprt tmp=ptr.op0();
                tmp.make_typecast(expr.type());
                simplify_node(tmp);
                expr.swap(tmp);
                return false;
            }
            else
            {
                // We do a bit of special treatment for (TYPE *)(a+(int)&o),
                // which is re-written to 'a'.

                typet type=ns.follow(expr.type());
                exprt tmp=ptr.op0();
                if(tmp.id()==ID_plus && tmp.operands().size()==2)
                {
                    if(tmp.op0().id()==ID_typecast &&
                            tmp.op0().operands().size()==1 &&
                            tmp.op0().op0().id()==ID_address_of)
                    {
                        expr=tmp.op1();
                        if(type!=expr.type())
                            expr.make_typecast(type);

                        simplify_node(expr);
                        return false;
                    }
                    else if(tmp.op1().id()==ID_typecast &&
                            tmp.op1().operands().size()==1 &&
                            tmp.op1().op0().id()==ID_address_of)
                    {
                        expr=tmp.op0();
                        if(type!=expr.type())
                            expr.make_typecast(type);

                        simplify_node(expr);
                        return false;
                    }
                }
            }
        }
    }
    else if(ptr.id()==ID_plus) // pointer arithmetic
    {
        exprt::operandst ptr_expr;
        exprt::operandst int_expr;

        for(const auto & op : ptr.operands())
        {
            if(op.type().id()==ID_pointer)
                ptr_expr.push_back(op);
            else if(!op.is_zero())
            {
                exprt tmp=op;
                if(tmp.type()!=expr.type())
                {
                    tmp.make_typecast(expr.type());
                    simplify_node(tmp);
                }

                int_expr.push_back(tmp);
            }
        }

        if(ptr_expr.size()!=1 || int_expr.empty())
            return true;

        typet pointer_type=ptr_expr.front().type();

        mp_integer element_size=
            pointer_offset_size(pointer_type.subtype(), ns);

        if(element_size==0) return true;

        // this might change the type of the pointer!
        exprt pointer_offset(ID_pointer_offset, expr.type());
        pointer_offset.copy_to_operands(ptr_expr.front());
        simplify_node(pointer_offset);

        exprt sum;

        if(int_expr.size()==1)
            sum=int_expr.front();
        else
        {
            sum=exprt(ID_plus, expr.type());
            sum.operands()=int_expr;
        }

        simplify_node(sum);

        exprt size_expr=
            from_integer(element_size, expr.type());

        binary_exprt product(sum, ID_mult, size_expr, expr.type());

        simplify_node(product);

        expr=binary_exprt(pointer_offset, ID_plus, product, expr.type());

        simplify_node(expr);

        return false;
    }
    else if(ptr.id()==ID_constant &&
            ptr.get(ID_value)==ID_NULL)
    {
        expr=gen_zero(expr.type());

        simplify_node(expr);

        return false;
    }

    return true;
}
示例#16
0
void add_padding(struct_typet &type, const namespacet &ns)
{
  struct_typet::componentst &components=type.components();

  // First do padding for bit-fields to make them
  // appear on byte boundaries.

  {  
    unsigned padding_counter=0;
    unsigned bit_field_bits=0;

    for(struct_typet::componentst::iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      if(it->type().id()==ID_c_bit_field &&
         to_c_bit_field_type(it->type()).get_width()!=0)
      {
        // count the bits
        unsigned width=to_c_bit_field_type(it->type()).get_width();
        bit_field_bits+=width;
      }
      else if(bit_field_bits!=0)
      {
        // not on a byte-boundary?
        if((bit_field_bits%8)!=0)
        {
          unsigned pad=8-bit_field_bits%8;
          c_bit_field_typet padding_type(unsignedbv_typet(pad), pad);
          
          struct_typet::componentt component;
          component.type()=padding_type;
          component.set_name("$bit_field_pad"+i2string(padding_counter++));
          component.set_is_padding(true);
          
          it=components.insert(it, component);
          it++; // skip over
        
          bit_field_bits+=pad;
        }

        bit_field_bits=0;
      }
    }

    // Add padding at the end?
    if((bit_field_bits%8)!=0)
    {
      unsigned pad=8-bit_field_bits%8;
      c_bit_field_typet padding_type(unsignedbv_typet(pad), pad);
      
      struct_typet::componentt component;
      component.type()=padding_type;
      component.set_name("$bit_field_pad"+i2string(padding_counter++));
      component.set_is_padding(true);
      
      components.push_back(component);
    }  
  }

  // Is the struct packed?
  if(type.get_bool(ID_C_packed))
    return; // done

  mp_integer offset=0;
  unsigned padding_counter=0;
  mp_integer max_alignment=0;
  unsigned bit_field_bits=0;

  for(struct_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      it++)
  {
    const typet &it_type=it->type();
    mp_integer a=1;
    
    if(it_type.id()==ID_c_bit_field)
    {
      a=alignment(to_c_bit_field_type(it_type).subtype(), ns);
      
      // A zero-width bit-field causes alignment to the base-type.
      if(to_c_bit_field_type(it_type).get_width()==0)
      {
      }
      else
      {
        // Otherwise, ANSI-C says that bit-fields do not get padded!
        // We consider the type for max_alignment, however.
        if(max_alignment<a) 
          max_alignment=a;
        
        unsigned w=to_c_bit_field_type(it_type).get_width();
        unsigned bytes;
        for(bytes=0; w>bit_field_bits; ++bytes, bit_field_bits+=8);
        bit_field_bits-=w;
        offset+=bytes;
        continue;
      }
    }
    else if(it->type().get_bool(ID_C_packed) ||
            ns.follow(it->type()).get_bool(ID_C_packed))
    {
      // the field or type is "packed"
    }
    else
      a=alignment(it_type, ns);
      
    // check minimum alignment
    if(a<config.ansi_c.alignment)
      a=config.ansi_c.alignment;
      
    if(max_alignment<a) 
      max_alignment=a;
      
    if(a!=1)
    {
      // we may need to align it
      mp_integer displacement=offset%a;

      if(displacement!=0)
      {
        mp_integer pad=a-displacement;
      
        unsignedbv_typet padding_type;
        padding_type.set_width(integer2unsigned(pad*8));
        
        struct_typet::componentt component;
        component.type()=padding_type;
        component.set_name("$pad"+i2string(padding_counter++));
        component.set_is_padding(true);
        
        it=components.insert(it, component);
        it++; // skip over
        
        offset+=pad;
      }
    }

    mp_integer size=pointer_offset_size(ns, it_type);

    if(size!=-1)
      offset+=size;
  }
  
  if(bit_field_bits!=0)
  {
    // these are now assumed to be multiples of 8
    offset+=bit_field_bits/8;
  }
  
  // any explicit alignment for the struct?
  if(type.find(ID_C_alignment).is_not_nil())
  {
    const exprt &alignment=
      static_cast<const exprt &>(type.find(ID_C_alignment));
    if(alignment.id()!=ID_default)
    {
      exprt tmp=alignment;
      simplify(tmp, ns);
      mp_integer tmp_i;
      if(!to_integer(tmp, tmp_i) && tmp_i>max_alignment)
        max_alignment=tmp_i;
    }
  }

  // There may be a need for 'end of struct' padding.
  // We use 'max_alignment'.
  
  if(max_alignment>1)
  {
    // we may need to align it
    mp_integer displacement=offset%max_alignment;

    if(displacement!=0)
    {
      mp_integer pad=max_alignment-displacement;
    
      unsignedbv_typet padding_type;
      padding_type.set_width(integer2unsigned(pad*8));

      // we insert after any final 'flexible member'
      struct_typet::componentt component;
      component.type()=padding_type;
      component.set_name("$pad"+i2string(padding_counter++));
      component.set_is_padding(true);
      
      components.push_back(component);
    }
  }

}
示例#17
0
bool simplify_exprt::simplify_index(exprt &expr)
{
  bool result=true;

  // extra arithmetic optimizations
  const exprt &index=to_index_expr(expr).index();
  const exprt &array=to_index_expr(expr).array();

  if(index.id()==ID_div &&
     index.operands().size()==2)
  {
    if(index.op0().id()==ID_mult &&
       index.op0().operands().size()==2 &&
       index.op0().op1()==index.op1())
    {
      exprt tmp=index.op0().op0();
      expr.op1()=tmp;
      result=false;
    }
    else if(index.op0().id()==ID_mult &&
            index.op0().operands().size()==2 &&
            index.op0().op0()==index.op1())
    {
      exprt tmp=index.op0().op1();
      expr.op1()=tmp;
      result=false;
    }
  }

  if(array.id()==ID_lambda)
  {
    // simplify (lambda i: e)(x) to e[i/x]

    const exprt &lambda_expr=array;

    if(lambda_expr.operands().size()!=2)
      return true;

    if(expr.op1().type()==lambda_expr.op0().type())
    {
      exprt tmp=lambda_expr.op1();
      replace_expr(lambda_expr.op0(), expr.op1(), tmp);
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()==ID_with)
  {
    // we have (a WITH [i:=e])[j]

    const exprt &with_expr=array;

    if(with_expr.operands().size()!=3)
      return true;

    if(with_expr.op1()==expr.op1())
    {
      // simplify (e with [i:=v])[i] to v
      exprt tmp=with_expr.op2();
      expr.swap(tmp);
      return false;
    }
    else
    {
      // Turn (a with i:=x)[j] into (i==j)?x:a[j].
      // watch out that the type of i and j might be different.
      equal_exprt equality_expr(expr.op1(), with_expr.op1());

      if(equality_expr.lhs().type()!=equality_expr.rhs().type())
        equality_expr.rhs().make_typecast(equality_expr.lhs().type());

      simplify_inequality(equality_expr);

      index_exprt new_index_expr;
      new_index_expr.type()=expr.type();
      new_index_expr.array()=with_expr.op0();
      new_index_expr.index()=expr.op1();

      simplify_index(new_index_expr); // recursive call

      if(equality_expr.is_true())
      {
        expr=with_expr.op2();
        return false;
      }
      else if(equality_expr.is_false())
      {
        expr.swap(new_index_expr);
        return false;
      }

      if_exprt if_expr(equality_expr, with_expr.op2(), new_index_expr);
      simplify_if(if_expr);

      expr.swap(if_expr);

      return false;
    }
  }
  else if(array.id()==ID_constant ||
          array.id()==ID_array)
  {
    mp_integer i;

    if(to_integer(expr.op1(), i))
    {
    }
    else if(i<0 || i>=array.operands().size())
    {
      // out of bounds
    }
    else
    {
      // ok
      exprt tmp=array.operands()[integer2size_t(i)];
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()==ID_string_constant)
  {
    mp_integer i;

    const irep_idt &value=array.get(ID_value);

    if(to_integer(expr.op1(), i))
    {
    }
    else if(i<0 || i>value.size())
    {
      // out of bounds
    }
    else
    {
      // terminating zero?
      char v=(i==value.size())?0:value[integer2size_t(i)];
      exprt tmp=from_integer(v, expr.type());
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()==ID_array_of)
  {
    if(array.operands().size()==1)
    {
      exprt tmp=array.op0();
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()=="array-list")
  {
    // These are index/value pairs, alternating.
    for(size_t i=0; i<array.operands().size()/2; i++)
    {
      exprt tmp_index=array.operands()[i*2];
      tmp_index.make_typecast(index.type());
      simplify(tmp_index);
      if(tmp_index==index)
      {
        exprt tmp=array.operands()[i*2+1];
        expr.swap(tmp);
        return false;
      }
    }
  }
  else if(array.id()==ID_byte_extract_little_endian ||
          array.id()==ID_byte_extract_big_endian)
  {
    const typet &array_type=ns.follow(array.type());

    if(array_type.id()==ID_array)
    {
      // This rewrites byte_extract(s, o, array_type)[i]
      // to byte_extract(s, o+offset, sub_type)

      mp_integer sub_size=pointer_offset_size(array_type.subtype(), ns);
      if(sub_size==-1)
        return true;

      // add offset to index
      mult_exprt offset(from_integer(sub_size, array.op1().type()), index);
      plus_exprt final_offset(array.op1(), offset);
      simplify_node(final_offset);

      exprt result(array.id(), expr.type());
      result.copy_to_operands(array.op0(), final_offset);
      expr.swap(result);

      simplify_rec(expr);

      return false;
    }
  }
  else if(array.id()==ID_if)
  {
    const if_exprt &if_expr=to_if_expr(array);
    exprt cond=if_expr.cond();

    index_exprt idx_false=to_index_expr(expr);
    idx_false.array()=if_expr.false_case();

    to_index_expr(expr).array()=if_expr.true_case();

    expr=if_exprt(cond, expr, idx_false, expr.type());
    simplify_rec(expr);

    return false;
  }

  return result;
}
示例#18
0
bool simplify_exprt::simplify_address_of_arg(exprt &expr)
{
    if(expr.id()==ID_index)
    {
        if(expr.operands().size()==2)
        {
            bool result=true;
            if(!simplify_address_of_arg(expr.op0())) result=false;
            if(!simplify_rec(expr.op1())) result=false;

            // rewrite (*(type *)int) [index] by
            // pushing the index inside

            mp_integer address;
            if(is_dereference_integer_object(expr.op0(), address))
            {
                // push index into address

                mp_integer step_size, index;

                step_size=pointer_offset_size(expr.type(), ns);

                if(!to_integer(expr.op1(), index) &&
                        step_size!=-1)
                {
                    unsignedbv_typet int_type(config.ansi_c.pointer_width);
                    pointer_typet pointer_type;
                    pointer_type.subtype()=expr.type();
                    typecast_exprt typecast_expr(
                        from_integer(step_size*index+address, int_type), pointer_type);
                    exprt new_expr=dereference_exprt(typecast_expr, expr.type());
                    expr=new_expr;
                    result=true;
                }
            }

            return result;
        }
    }
    else if(expr.id()==ID_member)
    {
        if(expr.operands().size()==1)
        {
            bool result=true;
            if(!simplify_address_of_arg(expr.op0())) result=false;

            const typet &op_type=ns.follow(expr.op0().type());

            if(op_type.id()==ID_struct)
            {
                // rewrite NULL -> member by
                // pushing the member inside

                mp_integer address;
                if(is_dereference_integer_object(expr.op0(), address))
                {
                    const struct_typet &struct_type=to_struct_type(op_type);
                    const irep_idt &member=to_member_expr(expr).get_component_name();
                    mp_integer offset=member_offset(struct_type, member, ns);
                    if(offset!=-1)
                    {
                        unsignedbv_typet int_type(config.ansi_c.pointer_width);
                        pointer_typet pointer_type;
                        pointer_type.subtype()=expr.type();
                        typecast_exprt typecast_expr(
                            from_integer(address+offset, int_type), pointer_type);
                        exprt new_expr=dereference_exprt(typecast_expr, expr.type());
                        expr=new_expr;
                        result=true;
                    }
                }
            }

            return result;
        }
    }
    else if(expr.id()==ID_dereference)
    {
        if(expr.operands().size()==1)
            return simplify_rec(expr.op0());
    }
    else if(expr.id()==ID_if)
    {
        if(expr.operands().size()==3)
        {
            bool result=true;
            if(!simplify_rec(expr.op0())) result=false;
            if(!simplify_address_of_arg(expr.op1())) result=false;
            if(!simplify_address_of_arg(expr.op2())) result=false;

            // op0 is a constant?
            if(expr.op0().is_true())
            {
                result=false;
                exprt tmp;
                tmp.swap(expr.op1());
                expr.swap(tmp);
            }
            else if(expr.op0().is_false())
            {
                result=false;
                exprt tmp;
                tmp.swap(expr.op2());
                expr.swap(tmp);
            }

            return result;
        }
    }

    return true;
}
示例#19
0
std::string as_vcd_binary(
  const exprt &expr,
  const namespacet &ns)
{
  const typet &type=ns.follow(expr.type());

  if(expr.id()==ID_constant)
  {
    if(type.id()==ID_unsignedbv ||
       type.id()==ID_signedbv ||
       type.id()==ID_bv ||
       type.id()==ID_fixedbv ||
       type.id()==ID_floatbv ||
       type.id()==ID_pointer)
      return expr.get_string(ID_value);
  }
  else if(expr.id()==ID_array)
  {
    std::string result;

    forall_operands(it, expr)
      result+=as_vcd_binary(*it, ns);

    return result;
  }
  else if(expr.id()==ID_struct)
  {
    std::string result;

    forall_operands(it, expr)
      result+=as_vcd_binary(*it, ns);

    return result;
  }
  else if(expr.id()==ID_union)
  {
    assert(expr.operands().size()==1);
    return as_vcd_binary(expr.op0(), ns);
  }

  // build "xxx"

  mp_integer width;

  if(type.id()==ID_unsignedbv ||
     type.id()==ID_signedbv ||
     type.id()==ID_floatbv ||
     type.id()==ID_fixedbv ||
     type.id()==ID_pointer ||
     type.id()==ID_bv)
    width=string2integer(type.get_string(ID_width));
  else
    width=pointer_offset_size(type, ns)*8;

  if(width>=0)
  {
    std::string result;

    for(; width!=0; --width)
      result+='x';

    return result;
  }

  return "";
}
示例#20
0
bool value_set_dereferencet::memory_model_bytes(
  exprt &value,
  const typet &to_type,
  const guardt &guard,
  const exprt &offset)
{
  const typet from_type=value.type();

  // We simply refuse to convert to/from code.
  if(from_type.id()==ID_code || to_type.id()==ID_code)
    return false;

  // We won't do this without a commitment to an endianness.
  if(config.ansi_c.endianness==configt::ansi_ct::endiannesst::NO_ENDIANNESS)
    return false;

  // But everything else we will try!
  // We just rely on byte_extract to do the job!

  exprt result;

  // See if we have an array of bytes already,
  // and we want something byte-sized.
  if(ns.follow(from_type).id()==ID_array &&
     pointer_offset_size(ns.follow(from_type).subtype(), ns)==1 &&
     pointer_offset_size(to_type, ns)==1 &&
     is_a_bv_type(ns.follow(from_type).subtype()) &&
     is_a_bv_type(to_type))
  {
    // yes, can use 'index'
    result=index_exprt(value, offset, ns.follow(from_type).subtype());

    // possibly need to convert
    if(!base_type_eq(result.type(), to_type, ns))
      result.make_typecast(to_type);
  }
  else
  {
    // no, use 'byte_extract'
    result=exprt(byte_extract_id(), to_type);
    result.copy_to_operands(value, offset);
  }

  value=result;

  // are we within the bounds?
  if(options.get_bool_option("pointer-check"))
  {
    // upper bound
    {
      exprt from_width=size_of_expr(from_type, ns);
      INVARIANT(
        from_width.is_not_nil(),
        "unknown or invalid type size:\n"+from_type.pretty());

      exprt to_width=
        to_type.id()==ID_empty?
        from_integer(0, size_type()):size_of_expr(to_type, ns);
      INVARIANT(
        to_width.is_not_nil(),
        "unknown or invalid type size:\n"+to_type.pretty());
      INVARIANT(
        from_width.type()==to_width.type(),
        "type mismatch on result of size_of_expr");

      minus_exprt bound(from_width, to_width);
      if(bound.type()!=offset.type())
        bound.make_typecast(offset.type());

      binary_relation_exprt
        offset_upper_bound(offset, ID_gt, bound);

      guardt tmp_guard(guard);
      tmp_guard.add(offset_upper_bound);
      dereference_callback.dereference_failure(
        "pointer dereference",
        "object upper bound", tmp_guard);
    }

    // lower bound is easy
    if(!offset.is_zero())
    {
      binary_relation_exprt
        offset_lower_bound(
          offset, ID_lt, from_integer(0, offset.type()));

      guardt tmp_guard(guard);
      tmp_guard.add(offset_lower_bound);
      dereference_callback.dereference_failure(
        "pointer dereference",
        "object lower bound", tmp_guard);
    }
  }

  return true;
}