コード例 #1
0
ファイル: ssa_dereference.cpp プロジェクト: diffblue/2ls
exprt dereference_rec(
  const exprt &src,
  const ssa_value_domaint &ssa_value_domain,
  const std::string &nondet_prefix,
  const namespacet &ns)
{
  if(src.id()==ID_dereference)
  {
    const exprt &pointer=dereference_rec(
      to_dereference_expr(src).pointer(),
      ssa_value_domain,
      nondet_prefix,
      ns);

    const typet &pointed_type=ns.follow(pointer.type().subtype());

    const ssa_value_domaint::valuest values=ssa_value_domain(pointer, ns);

    exprt result;
    if(values.value_set.empty())
    {
      result=pointed_object(pointer, ns);
    }
    else
    {
      auto it=values.value_set.begin();

      if(values.null || values.unknown ||
         (values.value_set.size()>1 && it->type().get_bool("#dynamic")))
      {
        std::string dyn_type_name=pointed_type.id_string();
        if(pointed_type.id()==ID_struct)
          dyn_type_name+="_"+id2string(to_struct_type(pointed_type).get_tag());
        irep_idt identifier="ssa::"+dyn_type_name+"_obj$unknown";

        result=symbol_exprt(identifier, src.type());
        result.set("#unknown_obj", true);
      }
      else
      {
        result=ssa_alias_value(src, (it++)->get_expr(), ns);
        result.set("#heap_access", result.type().get_bool("#dynamic"));
      }

      for(; it!=values.value_set.end(); ++it)
      {
        exprt guard=ssa_alias_guard(src, it->get_expr(), ns);
        exprt value=ssa_alias_value(src, it->get_expr(), ns);
        result=if_exprt(guard, value, result);
        result.set(
          "#heap_access",
          result.get_bool("#heap_access") ||
          value.type().get_bool("#dynamic"));
      }
    }

    return result;
  }
  else if(src.id()==ID_member)
  {
    member_exprt tmp=to_member_expr(src);
    tmp.struct_op()=
      dereference_rec(tmp.struct_op(), ssa_value_domain, nondet_prefix, ns);
    tmp.set("#heap_access", tmp.struct_op().get_bool("#heap_access"));

    #ifdef DEBUG
    std::cout << "dereference_rec tmp: " << from_expr(ns, "", tmp) << '\n';
    #endif

    if(tmp.struct_op().is_nil())
      return nil_exprt();

    return lift_if(tmp);
  }
  else if(src.id()==ID_address_of)
  {
    address_of_exprt tmp=to_address_of_expr(src);
    tmp.object()=
      dereference_rec(tmp.object(), ssa_value_domain, nondet_prefix, ns);
    tmp.set("#heap_access", tmp.object().get_bool("#heap_access"));

    if(tmp.object().is_nil())
      return nil_exprt();

    return lift_if(tmp);
  }
  else
  {
    exprt tmp=src;
    Forall_operands(it, tmp)
    {
      *it=dereference_rec(*it, ssa_value_domain, nondet_prefix, ns);
      if(it->get_bool("#heap_access"))
        tmp.set("#heap_access", true);
    }
    return tmp;
  }
コード例 #2
0
ファイル: abstract_expression.cpp プロジェクト: olivo/BP
void abstract_expression(
  const predicatest &predicates,
  exprt &expr,
  const namespacet &ns)
{
  if(expr.type().id()!=ID_bool)
    throw "abstract_expression expects expression of type Boolean";

  simplify(expr, ns);

  if(is_valid(expr, ns))
  {
	  // If expr is valid, we can abstract it as 'true'
	  expr.make_true();
  } else if(is_unsatisfiable(expr, ns))
  {
	  // If expr is unsatisfiable, we can abstract it as 'false'
	  expr.make_false();
  } else if(expr.id()==ID_and || expr.id()==ID_or ||
     expr.id()==ID_implies || expr.id()==ID_xor)
  {
    Forall_operands(it, expr)
      abstract_expression(predicates, *it, ns);
  }
  else if(expr.id()==ID_not)
  {
    assert(expr.operands().size()==1);

    abstract_expression(predicates, expr.op0(), ns);

    // remove double negation
    if(expr.op0().id()==ID_not &&
       expr.op0().operands().size()==1)
    {
      exprt tmp;
      tmp.swap(expr.op0().op0());
      expr.swap(tmp);
    }
  }
  else if(expr.id()==ID_if)
  {
    assert(expr.operands().size()==3);
  
    Forall_operands(it, expr)
      abstract_expression(predicates, *it, ns);

    exprt true_expr(ID_and, bool_typet());
    true_expr.copy_to_operands(expr.op0(), expr.op1());
    
    exprt false_expr(ID_and, bool_typet());
    false_expr.copy_to_operands(gen_not(expr.op0()), expr.op2());
    
    exprt or_expr(ID_or, bool_typet());
    or_expr.move_to_operands(true_expr, false_expr);
    
    expr.swap(or_expr);
  }
  else if(expr.id()==ID_equal || expr.id()==ID_notequal)
  {
    if(expr.operands().size()!=2)
      throw expr.id_string()+" takes two operands";

    // Is it equality on Booleans?

    if(expr.op0().type().id()==ID_bool &&
       expr.op1().type().id()==ID_bool)
    {
      // leave it in

      Forall_operands(it, expr)
        abstract_expression(predicates, *it, ns);
    }
    else // other types, make it a predicate
    {
      if(has_non_boolean_if(expr))
      {
        lift_if(expr);
        abstract_expression(predicates, expr, ns);
      }
      else
        make_it_a_predicate(predicates, expr, ns);
    }
  }
  else if(expr.is_constant())
  {
    // leave it as is
  }
  else if(has_non_boolean_if(expr))
  {
    lift_if(expr);
    abstract_expression(predicates, expr, ns);
  }
  else
  {
    make_it_a_predicate(predicates, expr, ns);
  }
}
コード例 #3
0
exprt dereference_rec(
 const exprt &src,
 const ssa_value_domaint &ssa_value_domain, 
 const std::string &nondet_prefix,
 const namespacet &ns)
{
  if(src.id()==ID_dereference)
  {
    const exprt &pointer=to_dereference_expr(src).pointer();
    exprt pointer_deref=dereference(pointer, ssa_value_domain, nondet_prefix, ns);

    // We use the identifier produced by
    // local_SSAt::replace_side_effects_rec
    exprt result=symbol_exprt(nondet_prefix, src.type());

    // query the value sets
    const ssa_value_domaint::valuest values=
      ssa_value_domain(pointer, ns);

    for(ssa_value_domaint::valuest::value_sett::const_iterator
        it=values.value_set.begin();
        it!=values.value_set.end();
        it++)
    {
      exprt guard=ssa_alias_guard(src, it->get_expr(), ns);
      exprt value=ssa_alias_value(src, it->get_expr(), ns);
      result=if_exprt(guard, value, result);
    }

    return result;
  }
  else if(src.id()==ID_member)
  {
    member_exprt tmp=to_member_expr(src);
    tmp.struct_op()=dereference_rec(tmp.struct_op(), ssa_value_domain, nondet_prefix, ns);
    
    #ifdef DEBUG
    std::cout << "dereference_rec tmp: " << from_expr(ns, "", tmp) << '\n';
    #endif

    if(tmp.struct_op().is_nil())
      return nil_exprt();
      
    return lift_if(tmp);
  }
  else if(src.id()==ID_address_of)
  {
    address_of_exprt tmp=to_address_of_expr(src);
    tmp.object()=dereference_rec(tmp.object(), ssa_value_domain, nondet_prefix, ns);

    if(tmp.object().is_nil())
      return nil_exprt();
    
    return lift_if(tmp);
  }
  else
  {
    exprt tmp=src;
    Forall_operands(it, tmp)
      *it=dereference_rec(*it, ssa_value_domain, nondet_prefix, ns);
    return tmp;
  }
}
コード例 #4
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;
}