Exemple #1
0
void goto_symext::process_array_expr_rec(
  exprt &expr,
  const typet &type) const
{
  if(expr.id()==ID_if)
  {
    if_exprt &if_expr=to_if_expr(expr);
    process_array_expr_rec(if_expr.true_case(), type);
    process_array_expr_rec(if_expr.false_case(), type);
  }
  else if(expr.id()==ID_index)
  {
    // strip index
    index_exprt &index_expr=to_index_expr(expr);
    exprt tmp=index_expr.array();
    expr.swap(tmp);
  }
  else if(expr.id()==ID_typecast)
  {
    // strip
    exprt tmp=to_typecast_expr(expr).op0();
    expr.swap(tmp);
    process_array_expr_rec(expr, type);
  }
  else if(expr.id()==ID_address_of)
  {
    // strip
    exprt tmp=to_address_of_expr(expr).op0();
    expr.swap(tmp);
    process_array_expr_rec(expr, type);
  }
  else if(expr.id()==ID_symbol &&
          expr.get_bool(ID_C_SSA_symbol) &&
          to_ssa_expr(expr).get_original_expr().id()==ID_index)
  {
    const ssa_exprt &ssa=to_ssa_expr(expr);
    const index_exprt &index_expr=to_index_expr(ssa.get_original_expr());
    exprt tmp=index_expr.array();
    expr.swap(tmp);
  }
  else
    Forall_operands(it, expr)
      process_array_expr_rec(*it, it->type());

  if(!base_type_eq(expr.type(), type, ns))
  {
    byte_extract_exprt be(byte_extract_id());
    be.type()=type;
    be.op()=expr;
    be.offset()=gen_zero(index_type());

    expr.swap(be);
  }
}
Exemple #2
0
void goto_symext::process_array_expr(exprt &expr)
{
  // This may change the type of the expression!

  if(expr.id()==ID_if)
  {
    if_exprt &if_expr=to_if_expr(expr);
    process_array_expr(if_expr.true_case());

    process_array_expr_rec(if_expr.false_case(),
                           if_expr.true_case().type());

    if_expr.type()=if_expr.true_case().type();
  }
  else if(expr.id()==ID_index)
  {
    // strip index
    index_exprt &index_expr=to_index_expr(expr);
    exprt tmp=index_expr.array();
    expr.swap(tmp);
  }
  else if(expr.id()==ID_typecast)
  {
    // strip
    exprt tmp=to_typecast_expr(expr).op0();
    expr.swap(tmp);
    process_array_expr(expr);
  }
  else if(expr.id()==ID_address_of)
  {
    // strip
    exprt tmp=to_address_of_expr(expr).op0();
    expr.swap(tmp);
    process_array_expr(expr);
  }
  else if(expr.id()==ID_symbol &&
          expr.get_bool(ID_C_SSA_symbol) &&
          to_ssa_expr(expr).get_original_expr().id()==ID_index)
  {
    const ssa_exprt &ssa=to_ssa_expr(expr);
    const index_exprt &index_expr=to_index_expr(ssa.get_original_expr());
    exprt tmp=index_expr.array();
    expr.swap(tmp);
  }
  else
    Forall_operands(it, expr)
      process_array_expr(*it);
}
bool clang_c_convertert::convert_integer_literal(
  const clang::IntegerLiteral &integer_literal,
  exprt &dest)
{
  typet type;
  if(get_type(integer_literal.getType(), type))
    return true;

  assert(type.is_unsignedbv() || type.is_signedbv());

  llvm::APInt val = integer_literal.getValue();

  exprt the_val;
  if (type.is_unsignedbv())
  {
    the_val =
      constant_exprt(
        integer2binary(val.getZExtValue(), bv_width(type)),
        integer2string(val.getZExtValue()),
        type);
  }
  else
  {
    the_val =
      constant_exprt(
        integer2binary(val.getSExtValue(), bv_width(type)),
        integer2string(val.getSExtValue()),
        type);
  }

  dest.swap(the_val);
  return false;
}
Exemple #4
0
void cpp_typecheckt::new_temporary(
  const source_locationt &source_location,
  const typet &type,
  const exprt::operandst &ops,
  exprt &temporary)
{
  // create temporary object
  exprt tmp_object_expr=exprt(ID_side_effect, type);
  tmp_object_expr.set(ID_statement, ID_temporary_object);
  tmp_object_expr.add_source_location()= source_location;

  exprt new_object(ID_new_object);
  new_object.add_source_location()=tmp_object_expr.source_location();
  new_object.set(ID_C_lvalue, true);
  new_object.type()=tmp_object_expr.type();

  already_typechecked(new_object);

  codet new_code =
    cpp_constructor(source_location, new_object, ops);

  if(new_code.is_not_nil())
  {
    if(new_code.get(ID_statement)==ID_assign)
      tmp_object_expr.move_to_operands(new_code.op1());
    else
      tmp_object_expr.add(ID_initializer)=new_code;
  }

  temporary.swap(tmp_object_expr);
}
bool simplify_exprt::simplify_ieee_float_relation(exprt &expr)
{
  assert(expr.id()==ID_ieee_float_equal ||
         expr.id()==ID_ieee_float_notequal);

  exprt::operandst &operands=expr.operands();

  if(expr.type().id()!=ID_bool)
    return true;

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

  // types must match
  if(expr.op0().type()!=expr.op1().type())
    return true;

  if(expr.op0().type().id()!=ID_floatbv)
    return true;

  // first see if we compare to a constant

  if(expr.op0().is_constant() &&
     expr.op1().is_constant())
  {
    ieee_floatt f0(to_constant_expr(expr.op0()));
    ieee_floatt f1(to_constant_expr(expr.op1()));

    if(expr.id()==ID_ieee_float_notequal)
      expr.make_bool(f0.ieee_not_equal(f1));
    else if(expr.id()==ID_ieee_float_equal)
      expr.make_bool(f0.ieee_equal(f1));
    else
      assert(false);

    return false;
  }

  if(expr.op0()==expr.op1())
  {
    // x!=x is the same as saying isnan(op)
    exprt isnan(ID_isnan, bool_typet());
    isnan.copy_to_operands(expr.op0());

    if(expr.id()==ID_ieee_float_notequal)
    {
    }
    else if(expr.id()==ID_ieee_float_equal)
      isnan.make_not();
    else
      assert(false);

    expr.swap(isnan);
    return false;
  }

  return true;
}
void c_typecastt::do_typecast(exprt &expr, const typet &type)
{
  // special case: array -> pointer is actually
  // something like address_of
  
  const typet &expr_type=ns.follow(expr.type());

  if(expr_type.id()==ID_array)
  {
    index_exprt index;
    index.array()=expr;
    index.index()=gen_zero(index_type());
    index.type()=expr_type.subtype();
    expr=address_of_exprt(index);
    if(ns.follow(expr.type())!=ns.follow(type))
      expr.make_typecast(type);
    return;
  }

  if(expr_type!=type)
  {
    // C booleans are special: we compile to ?0:1
    
    if(type.get(ID_C_c_type)==ID_bool)
    {
      if(expr_type.id()==ID_bool) // bool -> _Bool
      {
        exprt result=if_exprt(expr, gen_one(type), gen_zero(type));
        expr.swap(result);
      }
      else // * -> _Bool
      {
        equal_exprt equal_zero(expr, gen_zero(expr_type));
        exprt result=if_exprt(equal_zero, gen_zero(type), gen_one(type));
        expr.swap(result);
      }
    }
    else
    {    
      expr.make_typecast(type);
    }
  }
}
void convert_string_literal(const std::string &src, exprt &dest)
{
  std::string value;
  convert_string_literal(src, value);

  string_constantt result;
  result.set_value(value);

  dest.swap(result);
}
Exemple #8
0
void preconditiont::compute_rec(exprt &dest)
{
  if(dest.id()==ID_address_of)
  {
    // only do index!
    assert(dest.operands().size()==1);
    compute_address_of(dest.op0());
  }
  else if(dest.id()==ID_symbol)
  {
    if(dest.get(ID_identifier)==
       s.get_original_name(SSA_step.ssa_lhs.get_identifier()))
    {
      dest=SSA_step.ssa_rhs;
      s.get_original_name(dest);
    }
  }
  else if(dest.id()==ID_dereference)
  {
    assert(dest.operands().size()==1);

    const irep_idt &lhs_identifier=
      s.get_original_name(SSA_step.ssa_lhs.get_identifier());
  
    // aliasing may happen here

    value_setst::valuest expr_set;
    value_sets.get_values(target, dest.op0(), expr_set);
    hash_set_cont<irep_idt, irep_id_hash> symbols;

    for(value_setst::valuest::const_iterator
        it=expr_set.begin();
        it!=expr_set.end();
        it++)
      find_symbols(*it, symbols);
    
    if(symbols.find(lhs_identifier)!=symbols.end())
    {
      // may alias!
      exprt tmp;
      tmp.swap(dest.op0());
      dereference(target, tmp, ns, value_sets);
      dest.swap(tmp);
      compute_rec(dest);
    }
    else
    {
      // nah, ok
      compute_rec(dest.op0());
    }
  }
  else
    Forall_operands(it, dest)
      compute_rec(*it);
}
Exemple #9
0
bool value_sett::eval_pointer_offset(
  exprt &expr,
  const namespacet &ns) const
{
  bool mod=false;

  if(expr.id()==ID_pointer_offset)
  {
    assert(expr.operands().size()==1);

    object_mapt reference_set;
    get_value_set(expr.op0(), reference_set, ns, true);

    exprt new_expr;
    mp_integer previous_offset=0;

    const object_map_dt &object_map=reference_set.read();
    for(object_map_dt::const_iterator
        it=object_map.begin();
        it!=object_map.end();
        it++)
      if(!it->second.offset_is_set)
        return false;
      else
      {
        const exprt &object=object_numbering[it->first];
        mp_integer ptr_offset=compute_pointer_offset(object, ns);

        if(ptr_offset<0)
          return false;

        ptr_offset+=it->second.offset;

        if(mod && ptr_offset!=previous_offset)
          return false;

        new_expr=from_integer(ptr_offset, index_type());
        previous_offset=ptr_offset;
        mod=true;
      }

    if(mod)
      expr.swap(new_expr);
  }
  else
  {
    Forall_operands(it, expr)
      mod=eval_pointer_offset(*it, ns) || mod;
  }

  return mod;
}
bool clang_c_convertert::convert_string_literal(
  const clang::StringLiteral &string_literal,
  exprt &dest)
{
  typet type;
  if(get_type(string_literal.getType(), type))
    return true;

  string_constantt string(string_literal.getBytes().str(), type);
  dest.swap(string);

  return false;
}
Exemple #11
0
void goto_symext::replace_nondet(exprt &expr)
{
  if(expr.id()==ID_side_effect &&
     expr.get(ID_statement)==ID_nondet)
  {
    exprt new_expr(ID_nondet_symbol, expr.type());
    new_expr.set(ID_identifier, "symex::nondet"+std::to_string(nondet_count++));
    new_expr.add_source_location()=expr.source_location();
    expr.swap(new_expr);
  }
  else
    Forall_operands(it, expr)
      replace_nondet(*it);
}
Exemple #12
0
void goto_symext::rewrite_quantifiers(exprt &expr, statet &state)
{
  if(expr.id()==ID_forall)
  {
    // forall X. P -> P
    // we keep the quantified variable unique by means of L2 renaming
    assert(expr.operands().size()==2);
    assert(expr.op0().id()==ID_symbol);
    symbol_exprt tmp0=
      to_symbol_expr(to_ssa_expr(expr.op0()).get_original_expr());
    symex_decl(state, tmp0);
    exprt tmp=expr.op1();
    expr.swap(tmp);
  }
}
Exemple #13
0
void goto_convertt::rewrite_boolean(exprt &expr)
{
  assert(expr.id()==ID_and || expr.id()==ID_or);
  
  if(!expr.is_boolean())
    throw "`"+expr.id_string()+"' "
          "must be Boolean, but got "+expr.pretty();

  // re-write "a && b" into nested a?b:0
  // re-write "a || b" into nested a?1:b

  exprt tmp;
  
  if(expr.id()==ID_and)
    tmp=true_exprt();
  else // ID_or
    tmp=false_exprt();
    
  exprt::operandst &ops=expr.operands();

  // start with last one
  for(int i=int(ops.size())-1; i>=0; i--)
  {
    exprt &op=ops[i];

    if(!op.is_boolean())
     throw "`"+expr.id_string()+"' takes Boolean "
           "operands only, but got "+op.pretty();

    if(expr.id()==ID_and)
    {
      if_exprt if_e(op, tmp, false_exprt());
      tmp.swap(if_e);
    }
    else // ID_or
    {
      if_exprt if_e(op, true_exprt(), tmp);
      tmp.swap(if_e);
    }
  }

  expr.swap(tmp);
}
Exemple #14
0
void cnf_join_binary(exprt &expr)
{
  Forall_operands(it, expr)
    cnf_join_binary(*it);

  if(expr.id()==ID_and || expr.id()==ID_or || expr.id()==ID_xor ||
     expr.id()==ID_bitand || expr.id()==ID_bitor || expr.id()==ID_bitxor)
  {
    exprt tmp;

    if(expr.operands().size()==1)
    {
      tmp.swap(expr.op0());
      expr.swap(tmp);
    }
    else
    {
      unsigned count=0;

      forall_operands(it, expr)
      {
        if(it->id()==expr.id())
          count+=it->operands().size();
        else
          count++;
      }

      tmp.operands().reserve(count);

      Forall_operands(it, expr)
      {
        if(it->id()==expr.id())
        {
          Forall_operands(it2, *it)
            tmp.move_to_operands(*it2);
        }
        else
          tmp.move_to_operands(*it);
      }

      expr.operands().swap(tmp.operands());
    }
  }
Exemple #15
0
void gen_binary(exprt &expr, const std::string &id, bool default_value)
{
  if(expr.operands().size()==0)
  {
    if(default_value)
      expr.make_true();
    else
      expr.make_false();
  }
  else if(expr.operands().size()==1)
  {
    exprt tmp;
    tmp.swap(expr.op0());
    expr.swap(tmp);
  }
  else
  {
    expr.id(id);
    expr.type()=typet("bool");
  }
}
Exemple #16
0
void guardt::guard_expr(exprt &dest) const
{
  if(is_true())
  {
    // do nothing
  }
  else
  {
    if(dest.is_false())
    {
      dest=as_expr();
      dest.make_not();
    }
    else
    {
      implies_exprt tmp;
      tmp.op0()=as_expr();
      tmp.op1().swap(dest);
      dest.swap(tmp);
    }
  }
}
bool simplify_exprt::simplify_address_of(exprt &expr)
{
    if(expr.operands().size()!=1) return true;

    if(ns.follow(expr.type()).id()!=ID_pointer) return true;

    exprt &object=expr.op0();

    bool result=simplify_address_of_arg(object);

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

        if(!index_expr.index().is_zero())
        {
            // we normalize &a[i] to (&a[0])+i
            exprt offset;
            offset.swap(index_expr.op1());
            index_expr.op1()=gen_zero(offset.type());

            exprt addition(ID_plus, expr.type());
            addition.move_to_operands(expr, offset);

            expr.swap(addition);
            return false;
        }
    }
    else if(object.id()==ID_dereference)
    {
        // simplify &*p to p
        assert(object.operands().size()==1);
        exprt tmp=object.op0();
        expr=tmp;
        return false;
    }

    return result;
}
Exemple #18
0
void local_SSAt::replace_side_effects_rec(
  exprt &expr, locationt loc, unsigned &counter) const
{
  Forall_operands(it, expr)
    replace_side_effects_rec(*it, loc, counter);

  if(expr.id()==ID_side_effect)
  {
    const side_effect_exprt &side_effect_expr=
      to_side_effect_expr(expr);
    const irep_idt statement=side_effect_expr.get_statement();

    if(statement==ID_nondet)
    {
      // turn into nondet_symbol
      exprt nondet_symbol(ID_nondet_symbol, expr.type());
      counter++;
      const irep_idt identifier=
        "ssa::nondet"+
        i2string(loc->location_number)+
        "."+i2string(counter)+suffix;
      nondet_symbol.set(ID_identifier, identifier);
      
      expr.swap(nondet_symbol);
    }
    else if(statement==ID_malloc)
    {
      counter++;
      std::string tmp_suffix=
        i2string(loc->location_number)+
        "."+i2string(counter)+suffix;
      expr=malloc_ssa(side_effect_expr, tmp_suffix, ns);
    }
    else
      throw "unexpected side effect: "+id2string(statement);
  }
}
Exemple #19
0
void make_it_a_predicate(
  const predicatest &predicates,
  exprt &expr,
  const namespacet &ns)
{
  bool negation;
  canonicalize(expr, negation, ns);

  // see if we have it
  unsigned nr;
  if(predicates.find(expr, nr))
  {
    // yes, we do!

    // see if it is a constant
    if(predicates[nr].is_true())
      expr.make_true();
    else if(predicates[nr].is_false())
      expr.make_false();
    else
    {
      expr=exprt(ID_predicate_symbol, typet(ID_bool));
      expr.set(ID_identifier, nr);
    }

    if(negation)
      expr.make_not();
  }
  else
  {
    // nah, we don't
    // make it nondeterministic choice
    exprt tmp(ID_nondet_symbol, typet(ID_bool));
    tmp.add(ID_expression).swap(expr);
    expr.swap(tmp);
  }
}
Exemple #20
0
void goto_symext::replace_array_equal(exprt &expr)
{
  if(expr.id()==ID_array_equal)
  {
    assert(expr.operands().size()==2);
   
    // we expect two index expressions
    process_array_expr(expr.op0());
    process_array_expr(expr.op1());

    // type checking
    if(ns.follow(expr.op0().type())!=
       ns.follow(expr.op1().type()))
      expr=false_exprt();
    else
    {
      equal_exprt equality_expr(expr.op0(), expr.op1());
      expr.swap(equality_expr);
    }
  }

  Forall_operands(it, expr)
    replace_array_equal(*it);
}
Exemple #21
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;
}
Exemple #22
0
void goto_convertt::clean_expr(
  exprt &expr,
  goto_programt &dest,
  bool result_is_used)
{
  // this cleans:
  //   && || ?: comma (control-dependency)
  //   function calls
  //   object constructors like arrays, string constants, structs
  //   ++ --
  //   compound assignments
  //   compound literals

  if(!needs_cleaning(expr)) return;

  if(expr.id()==ID_and || expr.id()==ID_or)
  {
    // rewrite into ?:
    rewrite_boolean(expr);
    
    // recursive call
    clean_expr(expr, dest, result_is_used);
    return;
  }
  else if(expr.id()==ID_if)
  {
    // first clean condition
    clean_expr(to_if_expr(expr).cond(), dest, true);

    // possibly done now
    if(!needs_cleaning(to_if_expr(expr).true_case()) &&
       !needs_cleaning(to_if_expr(expr).false_case()))
      return;

    // copy expression
    if_exprt if_expr=to_if_expr(expr);
    
    if(!if_expr.cond().is_boolean())
      throw "first argument of `if' must be boolean, but got "
        +if_expr.cond().to_string();

    const locationt location=expr.find_location();
  
    // We do some constant-folding here, to mimic
    // what typical compilers do.
    {
      exprt tmp_cond=if_expr.cond();
      simplify(tmp_cond, ns);
      if(tmp_cond.is_true())
      {
        clean_expr(if_expr.true_case(), dest, result_is_used);
        expr=if_expr.true_case();
        return;
      }
      else if(tmp_cond.is_false())
      {
        clean_expr(if_expr.false_case(), dest, result_is_used);
        expr=if_expr.false_case();
        return;
      }
    }

    goto_programt tmp_true;
    clean_expr(if_expr.true_case(), tmp_true, result_is_used);

    goto_programt tmp_false;
    clean_expr(if_expr.false_case(), tmp_false, result_is_used);
    
    if(result_is_used)
    {
      symbolt &new_symbol=
        new_tmp_symbol(expr.type(), "if_expr", dest, location);

      code_assignt assignment_true;
      assignment_true.lhs()=new_symbol.symbol_expr();
      assignment_true.rhs()=if_expr.true_case();
      assignment_true.location()=location;
      convert(assignment_true, tmp_true);

      code_assignt assignment_false;
      assignment_false.lhs()=new_symbol.symbol_expr();
      assignment_false.rhs()=if_expr.false_case();
      assignment_false.location()=location;
      convert(assignment_false, tmp_false);

      // overwrites expr
      expr=new_symbol.symbol_expr();
    }
    else
    {
      // preserve the expressions for possible later checks
      if(if_expr.true_case().is_not_nil())
      {
        code_expressiont code_expression(if_expr.true_case());
        convert(code_expression, tmp_true);
      }
      
      if(if_expr.false_case().is_not_nil())
      {
        code_expressiont code_expression(if_expr.false_case());
        convert(code_expression, tmp_false);
      }
      
      expr=nil_exprt();
    }

    // generate guard for argument side-effects    
    generate_ifthenelse(
      if_expr.cond(), tmp_true, tmp_false,
      location, dest);

    return;
  }
  else if(expr.id()==ID_comma)
  {
    if(result_is_used)
    {
      exprt result;
    
      Forall_operands(it, expr)
      {
        bool last=(it==--expr.operands().end());
        
        // special treatment for last one
        if(last)
        {
          result.swap(*it);
          clean_expr(result, dest, true);
        }
        else
        {
          clean_expr(*it, dest, false);

          // remember these for later checks
          if(it->is_not_nil())
            convert(code_expressiont(*it), dest);
        }
      }

      expr.swap(result);
    }
    else // result not used
    {
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;
}
bool simplify_exprt::simplify_floatbv_typecast(exprt &expr)
{
  // These casts usually reduce precision, and thus, usually round.

  assert(expr.operands().size()==2);

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

  // eliminate redundant casts
  if(dest_type==src_type)
  {
    expr=expr.op0();
    return false;
  }

  exprt op0=expr.op0();
  exprt op1=expr.op1(); // rounding mode

  // We can soundly re-write (float)((double)x op (double)y)
  // to x op y. True for any rounding mode!

  #if 0
  if(op0.id()==ID_floatbv_div ||
     op0.id()==ID_floatbv_mult ||
     op0.id()==ID_floatbv_plus ||
     op0.id()==ID_floatbv_minus)
  {
    if(op0.operands().size()==3 &&
       op0.op0().id()==ID_typecast &&
       op0.op1().id()==ID_typecast &&
       op0.op0().operands().size()==1 &&
       op0.op1().operands().size()==1 &&
       ns.follow(op0.op0().type())==dest_type &&
       ns.follow(op0.op1().type())==dest_type)
    {
      exprt result(op0.id(), expr.type());
      result.operands().resize(3);
      result.op0()=op0.op0().op0();
      result.op1()=op0.op1().op0();
      result.op2()=op1;

      simplify_node(result);
      expr.swap(result);
      return false;
    }
  }
  #endif

  // constant folding
  if(op0.is_constant() && op1.is_constant())
  {
    mp_integer rounding_mode;
    if(!to_integer(op1, rounding_mode))
    {
      if(src_type.id()==ID_floatbv)
      {
        if(dest_type.id()==ID_floatbv) // float to float
        {
          ieee_floatt result(to_constant_expr(op0));
          result.rounding_mode=(ieee_floatt::rounding_modet)integer2size_t(rounding_mode);
          result.change_spec(to_floatbv_type(dest_type));
          expr=result.to_expr();
          return false;
        }
        else if(dest_type.id()==ID_signedbv ||
                dest_type.id()==ID_unsignedbv)
        {
          if(rounding_mode==ieee_floatt::ROUND_TO_ZERO)
          {
            ieee_floatt result(to_constant_expr(op0));
            result.rounding_mode=(ieee_floatt::rounding_modet)integer2size_t(rounding_mode);
            mp_integer value=result.to_integer();
            expr=from_integer(value, dest_type);
            return false;
          }
        }
      }
      else if(src_type.id()==ID_signedbv ||
              src_type.id()==ID_unsignedbv)
      {
        mp_integer value;
        if(!to_integer(op0, value))
        {
          if(dest_type.id()==ID_floatbv) // int to float
          {
            ieee_floatt result;
            result.rounding_mode=(ieee_floatt::rounding_modet)integer2size_t(rounding_mode);
            result.spec=to_floatbv_type(dest_type);
            result.from_integer(value);
            expr=result.to_expr();
            return false;
          }
        }
      }
    }
  }

  #if 0
  // (T)(a?b:c) --> a?(T)b:(T)c
  if(expr.op0().id()==ID_if &&
     expr.op0().operands().size()==3)
  {
    exprt tmp_op1=binary_exprt(expr.op0().op1(), ID_floatbv_typecast, expr.op1(), dest_type);
    exprt tmp_op2=binary_exprt(expr.op0().op2(), ID_floatbv_typecast, expr.op1(), dest_type);
    simplify_floatbv_typecast(tmp_op1);
    simplify_floatbv_typecast(tmp_op2);
    expr=if_exprt(expr.op0().op0(), tmp_op1, tmp_op2, dest_type);
    simplify_if(expr);
    return false;
  }
  #endif

  return true;
}
void goto_program_dereferencet::dereference_rec(
  exprt &expr,
  guardt &guard,
  const value_set_dereferencet::modet mode)
{
  if(!dereference.has_dereference(expr))
    return;

  if(expr.id()==ID_and || expr.id()==ID_or)
  {
    if(!expr.is_boolean())
      throw expr.id_string()+" must be Boolean, but got "+
            expr.pretty();

    guardt old_guard=guard;

    for(unsigned i=0; i<expr.operands().size(); i++)
    {
      exprt &op=expr.operands()[i];

      if(!op.is_boolean())
        throw expr.id_string()+" takes Boolean operands only, but got "+
              op.pretty();

      if(dereference.has_dereference(op))
        dereference_rec(op, guard, value_set_dereferencet::modet::READ);

      if(expr.id()==ID_or)
      {
        exprt tmp(op);
        tmp.make_not();
        guard.add(tmp);
      }
      else
        guard.add(op);
    }

    guard.swap(old_guard);

    return;
  }
  else if(expr.id()==ID_if)
  {
    if(expr.operands().size()!=3)
      throw "if takes three arguments";

    if(!expr.op0().is_boolean())
    {
      std::string msg=
        "first argument of if must be boolean, but got "
        +expr.op0().pretty();
      throw msg;
    }

    dereference_rec(expr.op0(), guard, value_set_dereferencet::modet::READ);

    bool o1=dereference.has_dereference(expr.op1());
    bool o2=dereference.has_dereference(expr.op2());

    if(o1)
    {
      guardt old_guard=guard;
      guard.add(expr.op0());
      dereference_rec(expr.op1(), guard, mode);
      guard.swap(old_guard);
    }

    if(o2)
    {
      guardt old_guard=guard;
      exprt tmp(expr.op0());
      tmp.make_not();
      guard.add(tmp);
      dereference_rec(expr.op2(), guard, mode);
      guard.swap(old_guard);
    }

    return;
  }

  if(expr.id()==ID_address_of ||
     expr.id()=="reference_to")
  {
    // turn &*p to p
    // this has *no* side effect!

    assert(expr.operands().size()==1);

    if(expr.op0().id()==ID_dereference)
    {
      assert(expr.op0().operands().size()==1);

      exprt tmp;
      tmp.swap(expr.op0().op0());

      if(tmp.type()!=expr.type())
        tmp.make_typecast(expr.type());

      expr.swap(tmp);
    }
  }

  Forall_operands(it, expr)
    dereference_rec(*it, guard, mode);

  if(expr.id()==ID_dereference)
  {
    if(expr.operands().size()!=1)
      throw "dereference expects one operand";

    dereference_location=expr.find_source_location();

    exprt tmp=dereference.dereference(
      expr.op0(), guard, mode);

    expr.swap(tmp);
  }
  else if(expr.id()==ID_index)
  {
    // this is old stuff and will go away

    if(expr.operands().size()!=2)
      throw "index expects two operands";

    if(expr.op0().type().id()==ID_pointer)
    {
      dereference_location=expr.find_source_location();

      exprt tmp1(ID_plus, expr.op0().type());
      tmp1.operands().swap(expr.operands());

      exprt tmp2=dereference.dereference(tmp1, guard, mode);
      tmp2.swap(expr);
    }
  }
}
Exemple #26
0
void simplify_byte_expr(exprt &dest,
                        const namespacet &ns)
{

  /*
   * byte_update(byte_update(e, i, v, t), i, v', t)
   *             -----------------------
   *                    root
   *  =>
   * byte_update(e, i, v', t)
   */
  if(dest.id()==ID_byte_update_little_endian
  || dest.id()==ID_byte_update_big_endian)
  {

    exprt &root=dest.op0();
    exprt &offset=dest.op1();
    const typet &type=root.type();

    if(root.id()==ID_byte_update_little_endian
    || root.id()==ID_byte_update_big_endian)
    {
      exprt &nested_root=root.op0();
      exprt &nested_offset=root.op1();
      const typet &nested_type=root.type();


      if(offset == nested_offset
      && type == nested_type)
      {

        #ifdef DEBUG
        std::cout << "simplify_byte_expr " << from_expr(dest) << std::endl;
        #endif

        root.swap(nested_root);

        #ifdef DEBUG
        std::cout << "  ==> " << from_expr(dest) << std::endl;
        #endif
      }
    }
  }

  /*
   * byte_extract(byte_update(e, i, v, t), i, t)
   *  =>
   * v
   */
  else
  if(dest.id()==ID_byte_extract_little_endian
  || dest.id()==ID_byte_extract_big_endian)
  {
    exprt &root=dest.op0();
    exprt &offset=dest.op1();
    const typet &type=dest.type();

    if(root.id()==ID_byte_update_little_endian
    || root.id()==ID_byte_update_big_endian)
    {
      exprt &nested_offset=root.op1();
      exprt &nested_with=root.op2();
      const typet &nested_type=root.type();


      if(offset == nested_offset
      && type == nested_type)
      {
        #ifdef DEBUG
        std::cout << "simplify_byte_expr " << from_expr(dest) << std::endl;
        #endif

        dest.swap(nested_with);

        //#ifdef DEBUG
        std::cout << "  ==> " << from_expr(dest) << std::endl;
        //#endif
      }
    }
  }

  if(dest.has_operands())
    Forall_operands(it, dest)
      simplify_byte_expr(*it, ns);
}
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;
}
Exemple #28
0
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);
  }
}
bool simplify_exprt::simplify_floatbv_op(exprt &expr)
{
  const typet &type=ns.follow(expr.type());

  if(type.id()!=ID_floatbv)
    return true;

  assert(expr.operands().size()==3);

  exprt op0=expr.op0();
  exprt op1=expr.op1();
  exprt op2=expr.op2(); // rounding mode

  assert(ns.follow(op0.type())==type);
  assert(ns.follow(op1.type())==type);

  // Remember that floating-point addition is _NOT_ associative.
  // Thus, we don't re-sort the operands.
  // We only merge constants!

  if(op0.is_constant() && op1.is_constant() && op2.is_constant())
  {
    ieee_floatt v0(to_constant_expr(op0));
    ieee_floatt v1(to_constant_expr(op1));

    mp_integer rounding_mode;
    if(!to_integer(op2, rounding_mode))
    {
      v0.rounding_mode=(ieee_floatt::rounding_modet)integer2size_t(rounding_mode);
      v1.rounding_mode=v0.rounding_mode;

      ieee_floatt result=v0;

      if(expr.id()==ID_floatbv_plus)
        result+=v1;
      else if(expr.id()==ID_floatbv_minus)
        result-=v1;
      else if(expr.id()==ID_floatbv_mult)
        result*=v1;
      else if(expr.id()==ID_floatbv_div)
        result/=v1;
      else
        assert(false);

      expr=result.to_expr();
      return false;
    }
  }

  // division by one? Exact for all rounding modes.
  if (expr.id()==ID_floatbv_div &&
      op1.is_constant() && op1.is_one())
  {
    exprt tmp;
    tmp.swap(op0);
    expr.swap(tmp);
    return false;
  }

  return true;
}
Exemple #30
0
bool ranking_synthesis_seneschalt::read_output(exprt &rf)
{
  // Check if there is a result at all...
  std::ifstream err("seneschal.err");
  bool result_found=false;
  while(err)
  {
    std::string line;
    std::getline(err, line);

    if(line=="Solving ... no solution" ||
       line=="Solving ... found a solution")
    {
      result_found = true;
      break;
    }
  }
  err.close();

  if(!result_found) return false;

  // There is a result!
  std::ifstream in("seneschal.out");

  std::string rank_string;
  std::string bound_string;

  while(in)
  {
    std::string line;

    std::getline(in, line);

    if(line.substr(0,7)=="Ranking")
    {
      std::vector<std::string> tokens;
      tokenize(line, tokens, " =[],\tr");

      bool work=false;
      for(std::vector<std::string>::const_iterator it=tokens.begin();
          it!=tokens.end();
          it++)
      {
        // std::cout << "TOKEN: " << *it << std::endl;

        if(*it=="Ranking")
        {
          result_found=true;
          work=true;
        }
        else if(*it=="function:") /* SKIP */ ;
        else if(work)
        {
          rank_string += " " + *it;
        }
      }
    }
    else if(line.substr(0,25)=="Lower bound (post-state):")
    {
      std::vector<std::string> tokens;
      tokenize(line, tokens, " =[],\t");

      std::vector<std::string>::const_iterator it=tokens.begin();
      it++; it++; it++;
      if(it!=tokens.end())
      {
        //std::cout << "TOKEN: " << *it << std::endl;

        bound_string = *it;
      }
    };
  }

  if(rank_string!="")
  {
    bound = string2integer(bound_string);

    if(bound!=0)
      rank_string = "(" + rank_string + ") - (" + bound_string + ")";

    exprt rfl;

    if(parse_rank_function(rank_string, trans_context, ns, *message_handler, rfl))
      throw ("RF EXTRACTION ERROR");

    replace_expr(variable_map, rfl);
    std::cout << "FOUND FUNCTION: " << from_expr(ns, "", rfl) << std::endl;

    rf.swap(rfl);

    std::cout << "BOUND: " << bound << std::endl;
  }
    
  return true;
}