예제 #1
0
bvt boolbvt::convert_power(const binary_exprt &expr)
{
  const typet &type=ns.follow(expr.type());

  std::size_t width=boolbv_width(type);

  if(width==0)
    return conversion_failed(expr);

  if(type.id()==ID_unsignedbv ||
     type.id()==ID_signedbv)
  {
    // Let's do the special case 2**x
    bvt op0=convert_bv(expr.op0());
    bvt op1=convert_bv(expr.op1());

    literalt eq_2=
      bv_utils.equal(op0, bv_utils.build_constant(2, op0.size()));

    bvt one=bv_utils.build_constant(1, width);
    bvt shift=bv_utils.shift(one, bv_utilst::LEFT, op1);

    bvt nondet=prop.new_variables(width);

    return bv_utils.select(eq_2, shift, nondet);
  }

  return conversion_failed(expr);
}
예제 #2
0
literalt boolbvt::convert_ieee_float_rel(const exprt &expr)
{
  const exprt::operandst &operands=expr.operands();
  const irep_idt &rel=expr.id();

  if(operands.size()==2)
  {
    const exprt &op0=expr.op0();
    const exprt &op1=expr.op1();

    bvtypet bvtype0=get_bvtype(op0.type());
    bvtypet bvtype1=get_bvtype(op1.type());

    const bvt &bv0=convert_bv(op0);
    const bvt &bv1=convert_bv(op1);

    if(bv0.size()==bv1.size() && !bv0.empty() &&
       bvtype0==IS_FLOAT && bvtype1==IS_FLOAT)
    {
      float_utilst float_utils(prop);
      float_utils.spec=to_floatbv_type(op0.type());

      if(rel==ID_ieee_float_equal)
        return float_utils.relation(bv0, float_utilst::EQ, bv1);
      else if(rel==ID_ieee_float_notequal)
        return !float_utils.relation(bv0, float_utilst::EQ, bv1);
      else
        return SUB::convert_rest(expr);
    }
  }

  return SUB::convert_rest(expr);
}
예제 #3
0
literalt boolbvt::convert_verilog_case_equality(
  const binary_relation_exprt &expr)
{
  // This is 4-valued comparison, i.e., z===z, x===x etc.
  // The result is always Boolean.

  if(!base_type_eq(expr.lhs().type(), expr.rhs().type(), ns))
  {
    std::cout << "######### lhs: " << expr.lhs().pretty() << '\n';
    std::cout << "######### rhs: " << expr.rhs().pretty() << '\n';
    throw "verilog_case_equality without matching types";
  }

  const bvt &bv0=convert_bv(expr.lhs());
  const bvt &bv1=convert_bv(expr.rhs());

  if(bv0.size()!=bv1.size())
  {
    std::cerr << "lhs: " << expr.lhs().pretty() << '\n';
    std::cerr << "lhs size: " << bv0.size() << '\n';
    std::cerr << "rhs: " << expr.rhs().pretty() << '\n';
    std::cerr << "rhs size: " << bv1.size() << '\n';
    throw "unexpected size mismatch on verilog_case_equality";
  }

  if(expr.id()==ID_verilog_case_inequality)
    return !bv_utils.equal(bv0, bv1);
  else
    return bv_utils.equal(bv0, bv1);
}
예제 #4
0
void boolbvt::convert_floatbv_typecast(
  const floatbv_typecast_exprt &expr, bvt &bv)
{
  const exprt &op0=expr.op(); // number to convert
  const exprt &op1=expr.rounding_mode(); // rounding mode

  bvt bv0=convert_bv(op0);
  bvt bv1=convert_bv(op1);

  const typet &src_type=ns.follow(expr.op0().type());
  const typet &dest_type=ns.follow(expr.type());
  
  if(src_type==dest_type) // redundant type cast?
  {
    bv=bv0;
    return;
  }

  float_utilst float_utils(prop);
  
  float_utils.set_rounding_mode(convert_bv(op1));
  
  if(src_type.id()==ID_floatbv &&
     dest_type.id()==ID_floatbv)
  {
    float_utils.spec=to_floatbv_type(src_type);
    bv=float_utils.conversion(bv0, to_floatbv_type(dest_type));
  }
  else if(src_type.id()==ID_signedbv &&
          dest_type.id()==ID_floatbv)
  {
    float_utils.spec=to_floatbv_type(dest_type);
    bv=float_utils.from_signed_integer(bv0);
  }
  else if(src_type.id()==ID_unsignedbv &&
          dest_type.id()==ID_floatbv)
  {
    float_utils.spec=to_floatbv_type(dest_type);
    bv=float_utils.from_unsigned_integer(bv0);
  }
  else if(src_type.id()==ID_floatbv &&
          dest_type.id()==ID_signedbv)
  {
    std::size_t dest_width=to_signedbv_type(dest_type).get_width();
    float_utils.spec=to_floatbv_type(src_type);
    bv=float_utils.to_signed_integer(bv0, dest_width);
  }
  else if(src_type.id()==ID_floatbv &&
          dest_type.id()==ID_unsignedbv)
  {
    std::size_t dest_width=to_unsignedbv_type(dest_type).get_width();
    float_utils.spec=to_floatbv_type(src_type);
    bv=float_utils.to_unsigned_integer(bv0, dest_width);
  }
  else
    return conversion_failed(expr, bv);
}
예제 #5
0
void boolbvt::convert_div(const exprt &expr, bvt &bv)
{
  if(expr.type().id()!=ID_unsignedbv &&
     expr.type().id()!=ID_signedbv &&
     expr.type().id()!=ID_fixedbv)
    return conversion_failed(expr, bv);

  unsigned width=boolbv_width(expr.type());
  
  if(width==0)
    return conversion_failed(expr, bv);

  if(expr.operands().size()!=2)
    throw "division takes two operands";

  if(expr.op0().type().id()!=expr.type().id() ||
     expr.op1().type().id()!=expr.type().id())
    return conversion_failed(expr, bv);

  bvt op0=convert_bv(expr.op0());
  bvt op1=convert_bv(expr.op1());

  if(op0.size()!=width ||
     op1.size()!=width)
    throw "convert_div: unexpected operand width";

  bvt res, rem;

  if(expr.type().id()==ID_fixedbv)
  {
    unsigned fraction_bits=
      to_fixedbv_type(expr.type()).get_fraction_bits();

    bvt zeros;
    zeros.resize(fraction_bits, const_literal(false));

    // add fraction_bits least-significant bits
    op0.insert(op0.begin(), zeros.begin(), zeros.end());
    op1=bv_utils.sign_extension(op1, op1.size()+fraction_bits);
  
    bv_utils.divider(op0, op1, res, rem, bv_utilst::SIGNED);
    
    // cut it down again
    res.resize(width);
  }
  else
  {
    bv_utilst::representationt rep=
      expr.type().id()==ID_signedbv?bv_utilst::SIGNED:
                                   bv_utilst::UNSIGNED;

    bv_utils.divider(op0, op1, res, rem, rep);
  }

  bv=res;
}
void boolbvt::convert_concatenation(const exprt &expr, bvt &bv)
{
  unsigned width=boolbv_width(expr.type());
  
  if(width==0)
    return conversion_failed(expr, bv);
    
  const exprt::operandst &operands=expr.operands();

  if(operands.size()==0)
    throw "concatenation takes at least one operand";

  unsigned offset=width;
  bv.resize(width);

  forall_expr(it, operands)
  {
    const bvt &op=convert_bv(*it);

    if(op.size()>offset)
      throw "concatenation operand width too big";

    offset-=op.size();

    for(unsigned i=0; i<op.size(); i++)
      bv[offset+i]=op[i];
  }    

  if(offset!=0)
    throw "concatenation operand width too small";
}
예제 #7
0
bvt boolbvt::convert_array(const exprt &expr)
{
  std::size_t width=boolbv_width(expr.type());

  if(width==0)
    return conversion_failed(expr);

  if(expr.type().id()==ID_array)
  {
    assert(expr.has_operands());
    const exprt::operandst &operands=expr.operands();
    assert(!operands.empty());
    std::size_t op_width=width/operands.size();

    bvt bv;
    bv.reserve(width);

    forall_expr(it, operands)
    {
      const bvt &tmp=convert_bv(*it);

      if(tmp.size()!=op_width)
        throw "convert_array: unexpected operand width";

      forall_literals(it2, tmp)
        bv.push_back(*it2);
    }

    return bv;
  }
예제 #8
0
파일: boolbv_with.cpp 프로젝트: lihaol/cbmc
void boolbvt::convert_with_union(
  const union_typet &type,
  const exprt &op1,
  const exprt &op2,
  const bvt &prev_bv,
  bvt &next_bv)
{
  next_bv=prev_bv;

  const bvt &op2_bv=convert_bv(op2);

  if(next_bv.size()<op2_bv.size())
  {
    error().source_location=type.source_location();
    error() << "convert_with_union: unexpected operand op2 width" << eom;
    throw 0;
  }

  if(config.ansi_c.endianness==configt::ansi_ct::endiannesst::IS_LITTLE_ENDIAN)
  {
    for(std::size_t i=0; i<op2_bv.size(); i++)
      next_bv[i]=op2_bv[i];
  }
  else
  {
    assert(config.ansi_c.endianness==configt::ansi_ct::endiannesst::IS_BIG_ENDIAN);

    endianness_mapt map_u(type, false, ns);
    endianness_mapt map_op2(op2.type(), false, ns);

    for(std::size_t i=0; i<op2_bv.size(); i++)
      next_bv[map_u.map_bit(i)]=op2_bv[map_op2.map_bit(i)];
  }
}
예제 #9
0
void boolbvt::convert_replication(const exprt &expr, bvt &bv)
{
  unsigned width=boolbv_width(expr.type());
  
  if(width==0)
    return conversion_failed(expr, bv);

  if(expr.operands().size()!=2)
    throw "replication takes two operands";

  mp_integer times;
  if(to_integer(expr.op0(), times))
    throw "replication takes constant as first parameter";
  const unsigned u_times=integer2unsigned(times);

  const bvt &op=convert_bv(expr.op1());

  unsigned offset=0;
  bv.resize(width);

  for(unsigned i=0; i<u_times; i++)
  {
    if(op.size()+offset>width)
      throw "replication operand width too big";

    for(unsigned i=0; i<op.size(); i++)
      bv[i+offset]=op[i];

    offset+=op.size();
  }    

  if(offset!=bv.size())
    throw "replication operand width too small";
}
예제 #10
0
void boolbvt::convert_constant(const constant_exprt &expr, bvt &bv)
{
  unsigned width=boolbv_width(expr.type());
  
  if(width==0)
    return conversion_failed(expr, bv);

  bv.resize(width);
  
  const typet &expr_type=expr.type();
  
  if(expr_type.id()==ID_array)
  {
    unsigned op_width=width/expr.operands().size();
    unsigned offset=0;

    forall_operands(it, expr)
    {
      const bvt &tmp=convert_bv(*it);

      if(tmp.size()!=op_width)
        throw "convert_constant: unexpected operand width";

      for(unsigned j=0; j<op_width; j++)
        bv[offset+j]=tmp[j];

      offset+=op_width;
    }   
    
    return;
  }
예제 #11
0
bvt boolbvt::convert_struct(const struct_exprt &expr)
{
  const struct_typet &struct_type=to_struct_type(ns.follow(expr.type()));

  std::size_t width=boolbv_width(struct_type);

  const struct_typet::componentst &components=struct_type.components();

  if(expr.operands().size()!=components.size())
  {
    error().source_location=expr.find_source_location();
    error() << "struct: wrong number of arguments" << eom;
    throw 0;
  }

  bvt bv;
  bv.resize(width);

  std::size_t offset=0, i=0;

  for(struct_typet::componentst::const_iterator
      it=components.begin();
      it!=components.end();
      it++)
  {
    const typet &subtype=it->type();
    const exprt &op=expr.operands()[i];

    if(!base_type_eq(subtype, op.type(), ns))
    {
      error().source_location=expr.find_source_location();
      error() << "struct: component type does not match: "
              << subtype.pretty() << " vs. "
              << op.type().pretty() << eom;
      throw 0;
    }

    std::size_t subtype_width=boolbv_width(subtype);

    if(subtype_width!=0)
    {
      const bvt &op_bv=convert_bv(op);

      assert(offset<width);
      assert(op_bv.size()==subtype_width);
      assert(offset+op_bv.size()<=width);

      for(std::size_t j=0; j<op_bv.size(); j++)
        bv[offset+j]=op_bv[j];

      offset+=op_bv.size();
    }

    i++;
  }

  assert(offset==width);

  return bv;
}
예제 #12
0
void boolbvt::convert_index(
  const exprt &array,
  const mp_integer &index,
  bvt &bv)
{
  const array_typet &array_type=
    to_array_type(ns.follow(array.type()));

  unsigned width=boolbv_width(array_type.subtype());

  if(width==0)
    return conversion_failed(array, bv);

  bv.resize(width);
  
  const bvt &tmp=convert_bv(array); // recursive call

  mp_integer offset=index*width;

  if(offset>=0 &&
     offset+width<=mp_integer(tmp.size()))
  {
    // in bounds
    for(unsigned i=0; i<width; i++)
      bv[i]=tmp[integer2long(offset+i)];
  }
  else
  {
    // out of bounds
    for(unsigned i=0; i<width; i++)
      bv[i]=prop.new_variable();
  }
}
예제 #13
0
void boolbvt::convert_cond(const exprt &expr, bvt &bv)
{
  const exprt::operandst &operands=expr.operands();

  unsigned width=boolbv_width(expr.type());
  
  if(width==0)
    return conversion_failed(expr, bv);

  bv.resize(width);

  // make it free variables
  Forall_literals(it, bv)
    *it=prop.new_variable();

  if(operands.size()<2)
    throw "cond takes at least two operands";

  if((operands.size()%2)!=0)
    throw "number of cond operands must be even";

  if(prop.has_set_to())
  {
    bool condition=true;
    literalt previous_cond=const_literal(false);
    literalt cond_literal=const_literal(false);

    forall_operands(it, expr)
    {
      if(condition)
      {
        cond_literal=convert(*it);
        cond_literal=prop.land(prop.lnot(previous_cond), cond_literal);

        previous_cond=prop.lor(previous_cond, cond_literal);
      }
      else
      {
        const bvt &op=convert_bv(*it);

        if(bv.size()!=op.size())
        {
          std::cerr << "result size: " << bv.size()
                    << std::endl
                    << "operand: " << op.size() << std::endl
                    << it->pretty()
                    << std::endl;

          throw "size of value operand does not match";
        }

        literalt value_literal=bv_utils.equal(bv, op);

        prop.l_set_to_true(prop.limplies(cond_literal, value_literal));
      }

      condition=!condition;
    }
  }
예제 #14
0
bvt boolbvt::convert_if(const if_exprt &expr)
{
  std::size_t width=boolbv_width(expr.type());

  if(width==0)
    return bvt(); // An empty bit-vector if.

  literalt cond=convert(expr.cond());

  const bvt &op1_bv=convert_bv(expr.true_case());
  const bvt &op2_bv=convert_bv(expr.false_case());

  if(op1_bv.size()!=width || op2_bv.size()!=width)
    throw "operand size mismatch for if "+expr.pretty();

  return bv_utils.select(cond, op1_bv, op2_bv);
}
예제 #15
0
literalt boolbvt::convert_equality(const equal_exprt &expr)
{
  if(!base_type_eq(expr.lhs().type(), expr.rhs().type(), ns))
  {
    std::cout << "######### lhs: " << expr.lhs().pretty() << '\n';
    std::cout << "######### rhs: " << expr.rhs().pretty() << '\n';
    throw "equality without matching types";
  }

  // see if it is an unbounded array
  if(is_unbounded_array(expr.lhs().type()))
  {
    // flatten byte_update/byte_extract operators if needed

    if(has_byte_operator(expr))
    {
      exprt tmp=flatten_byte_operators(expr, ns);
      return record_array_equality(to_equal_expr(tmp));
    }

    return record_array_equality(expr);
  }

  const bvt &bv0=convert_bv(expr.lhs());
  const bvt &bv1=convert_bv(expr.rhs());

  if(bv0.size()!=bv1.size())
  {
    std::cerr << "lhs: " << expr.lhs().pretty() << '\n';
    std::cerr << "lhs size: " << bv0.size() << '\n';
    std::cerr << "rhs: " << expr.rhs().pretty() << '\n';
    std::cerr << "rhs size: " << bv1.size() << '\n';
    throw "unexpected size mismatch on equality";
  }

  if(bv0.empty())
  {
    // An empty bit-vector comparison. It's not clear
    // what this is meant to say.
    return prop.new_variable();
  }

  return bv_utils.equal(bv0, bv1);
}
예제 #16
0
파일: boolbv_with.cpp 프로젝트: lihaol/cbmc
void boolbvt::convert_with_struct(
  const struct_typet &type,
  const exprt &op1,
  const exprt &op2,
  const bvt &prev_bv,
  bvt &next_bv)
{
  next_bv=prev_bv;

  const bvt &op2_bv=convert_bv(op2);

  const irep_idt &component_name=op1.get(ID_component_name);
  const struct_typet::componentst &components=
    type.components();

  std::size_t offset=0;

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

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

    std::size_t sub_width=boolbv_width(subtype);

    if(it->get_name()==component_name)
    {
      if(!base_type_eq(subtype, op2.type(), ns))
      {
        error().source_location=type.source_location();
        error() << "with/struct: component `" << component_name
                << "' type does not match: "
                << subtype.pretty() << " vs. "
                << op2.type().pretty() << eom;
        throw 0;
      }

      if(sub_width!=op2_bv.size())
      {
        error().source_location=type.source_location();
        error() << "convert_with_struct: unexpected operand op2 width"
                << eom;
        throw 0;
      }

      for(std::size_t i=0; i<sub_width; i++)
        next_bv[offset+i]=op2_bv[i];

      break; // done
    }

    offset+=sub_width;
  }
}
예제 #17
0
void boolbvt::convert_shift(const exprt &expr, bvt &bv)
{
  if(expr.type().id()!=ID_unsignedbv &&
     expr.type().id()!=ID_signedbv)
    return conversion_failed(expr, bv);

  unsigned width=boolbv_width(expr.type());
  
  if(width==0)
    return conversion_failed(expr, bv);

  if(width==0)
    throw "zero length bit vector type: "+expr.type().to_string();

  if(expr.operands().size()!=2)
    throw "shifting takes two operands";

  bvt op, dist;

  convert_bv(expr.op0(), op);
  convert_bv(expr.op1(), dist);

  if(op.size()!=width)
    throw "convert_shift: unexpected operand width";

  bv_utilst::shiftt shift;

  if(expr.id()==ID_shl)
    shift=bv_utilst::LEFT;
  else if(expr.id()==ID_ashr)
    shift=bv_utilst::ARIGHT;
  else if(expr.id()==ID_lshr)
    shift=bv_utilst::LRIGHT;
  else
    throw "unexpected operand";

  bv=bv_utils.shift(op, shift, dist);
}
예제 #18
0
bvt boolbvt::convert_bv_typecast(const typecast_exprt &expr)
{
  const typet &expr_type=ns.follow(expr.type());
  const exprt &op=expr.op();
  const typet &op_type=ns.follow(op.type());
  const bvt &op_bv=convert_bv(op);  

  bvt bv;

  if(type_conversion(op_type, op_bv, expr_type, bv))
    return conversion_failed(expr);

  return bv;
}
예제 #19
0
bvt boolbvt::convert_array_of(const array_of_exprt &expr)
{
  if(expr.type().id()!=ID_array)
    throw "array_of must be array-typed";

  const array_typet &array_type=to_array_type(expr.type());

  if(is_unbounded_array(array_type))
    return conversion_failed(expr);

  std::size_t width=boolbv_width(array_type);

  if(width==0)
  {
    // A zero-length array is acceptable;
    // an element with unknown size is not.
    if(boolbv_width(array_type.subtype())==0)
      return conversion_failed(expr);
    else
      return bvt();
  }

  const exprt &array_size=array_type.size();

  mp_integer size;

  if(to_integer(array_size, size))
    return conversion_failed(expr);

  const bvt &tmp=convert_bv(expr.op0());

  bvt bv;
  bv.resize(width);

  if(size*tmp.size()!=width)
    throw "convert_array_of: unexpected operand width";

  std::size_t offset=0;

  for(mp_integer i=0; i<size; i=i+1)
  {
    for(std::size_t j=0; j<tmp.size(); j++, offset++)
      bv[offset]=tmp[j];
  }

  assert(offset==bv.size());

  return bv;
}
예제 #20
0
void boolbvt::convert_shift(const exprt &expr, bvt &bv)
{
  if(expr.type().id()!=ID_unsignedbv &&
     expr.type().id()!=ID_signedbv &&
     expr.type().id()!=ID_floatbv &&
     expr.type().id()!=ID_pointer &&
     expr.type().id()!=ID_bv)
    return conversion_failed(expr, bv);

  unsigned width=boolbv_width(expr.type());
  
  if(width==0)
    return conversion_failed(expr, bv);

  if(expr.operands().size()!=2)
    throw "shifting takes two operands";

  const bvt &op=convert_bv(expr.op0());
  const bvt &dist=convert_bv(expr.op1());

  if(op.size()!=width)
    throw "convert_shift: unexpected operand width";

  bv_utilst::shiftt shift;

  if(expr.id()==ID_shl)
    shift=bv_utilst::LEFT;
  else if(expr.id()==ID_ashr)
    shift=bv_utilst::ARIGHT;
  else if(expr.id()==ID_lshr)
    shift=bv_utilst::LRIGHT;
  else
    throw "unexpected operand";

  bv=bv_utils.shift(op, shift, dist);
}
예제 #21
0
파일: boolbv_with.cpp 프로젝트: lihaol/cbmc
bvt boolbvt::convert_with(const exprt &expr)
{
  if(expr.operands().size()<3)
  {
    error().source_location=expr.find_source_location();
    error() << "with takes at least three operands" << eom;
    throw 0;
  }

  if((expr.operands().size()%2)!=1)
  {
    error().source_location=expr.find_source_location();
    error() << "with takes an odd number of operands" << eom;
    throw 0;
  }

  bvt bv=convert_bv(expr.op0());

  std::size_t width=boolbv_width(expr.type());

  if(width==0)
    return conversion_failed(expr);

  if(bv.size()!=width)
  {
    error().source_location=expr.find_source_location();
    error() << "unexpected operand 0 width" << eom;
    throw 0;
  }

  bvt prev_bv;
  prev_bv.resize(width);

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

  for(std::size_t op_no=1; op_no<ops.size(); op_no+=2)
  {
    bv.swap(prev_bv);

    convert_with(expr.op0().type(),
                 ops[op_no],
                 ops[op_no+1],
                 prev_bv,
                 bv);
  }

  return bv;
}
예제 #22
0
void bv_refinementt::freeze_lazy_constraints()
{
  if(!lazy_arrays) return;

  for(std::list<lazy_constraintt>::iterator 
	l_it = lazy_array_constraints.begin();
      l_it != lazy_array_constraints.end(); ++l_it)
  {
    std::set<symbol_exprt> symbols;
    find_symbols(l_it->lazy,symbols);
    for(std::set<symbol_exprt>::const_iterator it = symbols.begin();
	it != symbols.end(); ++it)
    {
      bvt bv = convert_bv(l_it->lazy);
      forall_literals(b_it, bv) 
	if(!b_it->is_constant()) prop.set_frozen(*b_it);
    }
  }
}
예제 #23
0
bvt boolbvt::convert_union(const union_exprt &expr)
{
  std::size_t width=boolbv_width(expr.type());

  if(width==0)
    return conversion_failed(expr);

  const bvt &op_bv=convert_bv(expr.op());

  if(width<op_bv.size())
    throw "union: unexpected operand op width";

  bvt bv;
  bv.resize(width);

  if(config.ansi_c.endianness==configt::ansi_ct::endiannesst::IS_LITTLE_ENDIAN)
  {
    for(std::size_t i=0; i<op_bv.size(); i++)
      bv[i]=op_bv[i];

    // pad with nondets
    for(std::size_t i=op_bv.size(); i<bv.size(); i++)
      bv[i]=prop.new_variable();
  }
  else
  {
    assert(
      config.ansi_c.endianness==configt::ansi_ct::endiannesst::IS_BIG_ENDIAN);

    endianness_mapt map_u(expr.type(), false, ns);
    endianness_mapt map_op(expr.op0().type(), false, ns);

    for(std::size_t i=0; i<op_bv.size(); i++)
      bv[map_u.map_bit(i)]=op_bv[map_op.map_bit(i)];

    // pad with nondets
    for(std::size_t i=op_bv.size(); i<bv.size(); i++)
      bv[map_u.map_bit(i)]=prop.new_variable();
  }

  return bv;
}
예제 #24
0
void boolbvt::convert_update(const exprt &expr, bvt &bv)
{
  const exprt::operandst &ops=expr.operands();

  if(ops.size()!=3)
    throw "update takes at three operands";

  std::size_t width=boolbv_width(expr.type());

  if(width==0)
    return conversion_failed(expr, bv);

  bv=convert_bv(ops[0]);

  if(bv.size()!=width)
    throw "update: unexpected operand 0 width";

  // start the recursion
  convert_update_rec(
    expr.op1().operands(), 0, expr.type(), 0, expr.op2(), bv);
}
예제 #25
0
literalt boolbvt::convert_onehot(const unary_exprt &expr)
{
  bvt op=convert_bv(expr.op());

  literalt one_seen=const_literal(false);
  literalt more_than_one_seen=const_literal(false);

  for(bvt::const_iterator it=op.begin(); it!=op.end(); it++)
  {
    more_than_one_seen=
      prop.lor(more_than_one_seen, prop.land(*it, one_seen));
    one_seen=prop.lor(*it, one_seen);
  }

  if(expr.id()==ID_onehot)
    return prop.land(one_seen, !more_than_one_seen);
  else if(expr.id()==ID_onehot0)
    return !more_than_one_seen;
  else
    throw "unexpected onehot expression";
}
예제 #26
0
literalt boolbvt::convert_typecast(const typecast_exprt &expr)
{
  assert(expr.operands().size()==1);
  
  if(expr.op0().type().id()==ID_range)
  {
    mp_integer from=string2integer(expr.op0().type().get_string(ID_from));
    mp_integer to=string2integer(expr.op0().type().get_string(ID_to));

    if(from==1 && to==1)
      return const_literal(true);
    else if(from==0 && to==0)
      return const_literal(false);
  }

  const bvt &bv=convert_bv(expr.op0());
  
  if(!bv.empty())
    return prop.lor(bv);

  return SUB::convert_rest(expr);
}
예제 #27
0
bv_refinementt::approximationt &
bv_refinementt::add_approximation(
  const exprt &expr, bvt &bv)
{
  approximations.push_back(approximationt(approximations.size()));
  approximationt &a=approximations.back(); // stable!

  unsigned width=boolbv_width(expr.type());
  assert(width!=0);

  a.expr=expr;
  a.result_bv=prop.new_variables(width);
  a.no_operands=expr.operands().size();
  set_frozen(a.result_bv);

  if(a.no_operands==1)
  {
    a.op0_bv=convert_bv(expr.op0());
    set_frozen(a.op0_bv);
  }
  else if(a.no_operands==2)
  {
    a.op0_bv=convert_bv(expr.op0());
    a.op1_bv=convert_bv(expr.op1());
    set_frozen(a.op0_bv);
    set_frozen(a.op1_bv);
  }
  else if(a.no_operands==3)
  {
    a.op0_bv=convert_bv(expr.op0());
    a.op1_bv=convert_bv(expr.op1());
    a.op2_bv=convert_bv(expr.op2());
    set_frozen(a.op0_bv);
    set_frozen(a.op1_bv);
    set_frozen(a.op2_bv);
  }
  else
    assert(false);
    
  bv=a.result_bv;

  initialize(a);
  
  return a;
}
예제 #28
0
bvt boolbvt::convert_abs(const exprt &expr)
{
    std::size_t width=boolbv_width(expr.type());

    if(width==0)
        return conversion_failed(expr);

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

    if(operands.size()!=1)
        throw "abs takes one operand";

    const exprt &op0=expr.op0();

    const bvt &op_bv=convert_bv(op0);

    if(op0.type()!=expr.type())
        return conversion_failed(expr);

    bvtypet bvtype=get_bvtype(expr.type());

    if(bvtype==IS_FIXED ||
            bvtype==IS_SIGNED ||
            bvtype==IS_UNSIGNED)
    {
        return bv_utils.absolute_value(op_bv);
    }
    else if(bvtype==IS_FLOAT)
    {
        float_utilst float_utils(prop);
        float_utils.spec=to_floatbv_type(expr.type());
        return float_utils.abs(op_bv);
    }

    return conversion_failed(expr);
}
예제 #29
0
void boolbvt::convert_union(const exprt &expr, bvt &bv)
{
  unsigned width=boolbv_width(expr.type());

  if(width==0)
    return conversion_failed(expr, bv);

  if(expr.operands().size()!=1)
    throw "union expects one argument";

  const bvt &op_bv=convert_bv(expr.op0());

  if(width<op_bv.size())
    throw "union: unexpected operand op width";

  bv.resize(width);
  
  for(unsigned i=0; i<op_bv.size(); i++)
    bv[i]=op_bv[i];

  // pad with nondets
  for(unsigned i=op_bv.size(); i<bv.size(); i++)
    bv[i]=prop.new_variable();
}
예제 #30
0
literalt boolbvt::convert_overflow(const exprt &expr)
{
  const exprt::operandst &operands=expr.operands();

  if(expr.id()==ID_overflow_plus ||
     expr.id()==ID_overflow_minus)
  {
    if(operands.size()!=2)
      throw "operator "+expr.id_string()+" takes two operands";

    const bvt &bv0=convert_bv(operands[0]);
    const bvt &bv1=convert_bv(operands[1]);

    if(bv0.size()!=bv1.size())
      return SUB::convert_rest(expr);

    bv_utilst::representationt rep=
      expr.op0().type().id()==ID_signedbv?bv_utilst::SIGNED:
                                          bv_utilst::UNSIGNED;

    return expr.id()==ID_overflow_minus?
      bv_utils.overflow_sub(bv0, bv1, rep):
      bv_utils.overflow_add(bv0, bv1, rep);
  }
  else if(expr.id()==ID_overflow_mult)
  {
    if(operands.size()!=2)
      throw "operator "+expr.id_string()+" takes two operands";

    if(operands[0].type().id()!=ID_unsignedbv &&
       operands[0].type().id()!=ID_signedbv)
      return SUB::convert_rest(expr);

    bvt bv0=convert_bv(operands[0]);
    bvt bv1=convert_bv(operands[1]);

    if(bv0.size()!=bv1.size())
      throw "operand size mismatch on overflow-*";

    bv_utilst::representationt rep=
      operands[0].type().id()==ID_signedbv?bv_utilst::SIGNED:
                                           bv_utilst::UNSIGNED;

    if(operands[0].type()!=operands[1].type())
      throw "operand type mismatch on overflow-*";

    assert(bv0.size()==bv1.size());
    unsigned old_size=bv0.size();
    unsigned new_size=old_size*2;

    // sign/zero extension
    bv0=bv_utils.extension(bv0, new_size, rep);
    bv1=bv_utils.extension(bv1, new_size, rep);

    bvt result=bv_utils.multiplier(bv0, bv1, rep);

    if(rep==bv_utilst::UNSIGNED)
    {
      bvt bv_overflow;
      bv_overflow.reserve(old_size);

      // get top result bits
      for(unsigned i=old_size; i<result.size(); i++)
        bv_overflow.push_back(result[i]);

      return prop.lor(bv_overflow);
    }
    else
    {
      bvt bv_overflow;
      bv_overflow.reserve(old_size);

      // get top result bits, plus one more
      assert(old_size!=0);
      for(unsigned i=old_size-1; i<result.size(); i++)
        bv_overflow.push_back(result[i]);

      // these need to be either all 1's or all 0's
      literalt all_one=prop.land(bv_overflow);
      literalt all_zero=prop.lnot(prop.lor(bv_overflow));
      return prop.lnot(prop.lor(all_one, all_zero));
    }
  }
  else if(expr.id()==ID_overflow_unary_minus)
  {
    if(operands.size()!=1)
      throw "operator "+expr.id_string()+" takes one operand";

    const bvt &bv=convert_bv(operands[0]);
      
    return bv_utils.overflow_negate(bv);
  }
  else if(has_prefix(expr.id_string(), "overflow-typecast-"))
  {
    unsigned bits=atoi(expr.id().c_str()+18);

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

    if(operands.size()!=1)
      throw "operator "+expr.id_string()+" takes one operand";
      
    const exprt &op=operands[0];

    const bvt &bv=convert_bv(op);

    if(bits>=bv.size() || bits==0)
      throw "overflow-typecast got wrong number of bits";
      
    // signed or unsigned?
    if(op.type().id()==ID_signedbv)
    {
      bvt tmp_bv;
      for(unsigned i=bits; i<bv.size(); i++)
        tmp_bv.push_back(prop.lxor(bv[bits-1], bv[i]));

      return prop.lor(tmp_bv);
    }
    else
    {
      bvt tmp_bv;
      for(unsigned i=bits; i<bv.size(); i++)
        tmp_bv.push_back(bv[i]);

      return prop.lor(tmp_bv);
    }
  }

  return SUB::convert_rest(expr);
}