literalt smt1_propt::lxor(const bvt &bv)
{
  if(bv.size()==0) return const_literal(false);
  if(bv.size()==1) return bv[0];

  out << std::endl;

  literalt l=new_variable();

  out << ":assumption ; lxor" << std::endl;
  out << " (iff " << smt1_literal(l) << " (xor";

  forall_literals(it, bv)
    out << " " << smt1_literal(*it);

  out << "))" << std::endl;

  return l;
}
Exemple #2
0
bvt bv_utilst::extension(
  const bvt &bv,
  std::size_t new_size,
  representationt rep)
{
  std::size_t old_size=bv.size();
  bvt result=bv;
  result.resize(new_size);

  assert(old_size!=0);

  literalt extend_with=
    (rep==SIGNED && !bv.empty())?bv[old_size-1]:
    const_literal(false);

  for(std::size_t i=old_size; i<new_size; i++)
    result[i]=extend_with;

  return result;
}
Exemple #3
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);
}
Exemple #4
0
bool z3_propt::process_clause(const bvt &bv, bvt &dest)
{
  dest.clear();

  // empty clause! this is UNSAT
  if(bv.empty()) return false;

  std::set<literalt> s;

  dest.reserve(bv.size());

  for(bvt::const_iterator it=bv.begin();
      it!=bv.end();
      it++)
  {
    literalt l=*it;

    // we never use index 0
    assert(l.var_no()!=0);

    if(l.is_true())
      return true; // clause satisfied

    if(l.is_false())
      continue;

    if(l.var_no()>=_no_variables)
      std::cout << "l.var_no()=" << l.var_no() << " _no_variables=" << _no_variables << std::endl;
    assert(l.var_no()<_no_variables);

    // prevent duplicate literals
    if(s.insert(l).second)
      dest.push_back(l);

    if(s.find(lnot(l))!=s.end())
      return true; // clause satisfied
  }

  return false;
}
void smt1_propt::lcnf(const bvt &bv)
{
  out << std::endl;
  out << ":assumption ; lcnf" << std::endl;
  out << " ";

  if(bv.empty())
    out << "false ; the empty clause";
  else if(bv.size()==1)
    out << smt1_literal(bv.front());
  else
  {
    out << "(or";
    
    for(bvt::const_iterator it=bv.begin(); it!=bv.end(); it++)
      out << " " << smt1_literal(*it);

    out << ")";
  }

  out << std::endl;
}
Exemple #6
0
static void write_dimacs_clause(
  const bvt &clause,
  std::ostream &out,
  bool break_lines)
{
  // The DIMACS CNF format allows line breaks in clauses:
  // "Each clauses is terminated by the value 0. Unlike many formats
  // that represent the end of a clause by a new-line character,
  // this format allows clauses to be on multiple lines."
  // Some historic solvers (zchaff e.g.) have silently swallowed
  // literals in clauses that exceed some fixed buffer size.
  
  // However, the SAT competition format does not allow line
  // breaks in clauses, so we offer both options. 

  for(size_t j=0; j<clause.size(); j++)
  {
    out << clause[j].dimacs() << " ";
    // newline to avoid overflow in sat checkers
    if((j&15)==0 && j!=0 && break_lines) out << "\n";
  }

  out << "0" << "\n";
}
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();
}
Exemple #8
0
literalt bv_utilst::overflow_sub(
  const bvt &op0, const bvt &op1, representationt rep)
{
  if(rep==SIGNED)
  {
    // We special-case x-INT_MIN, which is >=0 if
    // x is negative, always representable, and
    // thus not an overflow.
    literalt op1_is_int_min=is_int_min(op1);
    literalt op0_is_negative=op0[op0.size()-1];

    return
      prop.lselect(op1_is_int_min,
        !op0_is_negative,
        overflow_add(op0, negate(op1), SIGNED));
  }
  else if(rep==UNSIGNED)
  {
    // overflow is simply _negated_ carry-out
    return !carry_out(op0, inverted(op1), const_literal(true));
  }
  else
    assert(false);
}
Exemple #9
0
mp_integer boolbvt::get_value(
  const bvt &bv,
  unsigned offset,
  unsigned width)
{
  mp_integer value=0;
  mp_integer weight=1;

  for(unsigned bit_nr=offset; bit_nr<offset+width; bit_nr++)
  {
    assert(bit_nr<bv.size());
    switch(prop.l_get(bv[bit_nr]).get_value())
    {
     case tvt::TV_FALSE:   break;
     case tvt::TV_TRUE:    value+=weight; break;
     case tvt::TV_UNKNOWN: break;
     default: assert(false);
    }

    weight*=2;
  }

  return value;
}
Exemple #10
0
void boolbvt::convert_add_sub(const exprt &expr, bvt &bv)
{
  const typet &type=ns.follow(expr.type());

  if(type.id()!=ID_unsignedbv &&
     type.id()!=ID_signedbv &&
     type.id()!=ID_fixedbv &&
     type.id()!=ID_floatbv &&
     type.id()!=ID_range &&
     type.id()!=ID_vector)
    return conversion_failed(expr, bv);

  unsigned width=boolbv_width(type);
  
  if(width==0)
    return conversion_failed(expr, bv);
    
  const exprt::operandst &operands=expr.operands();

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

  const exprt &op0=expr.op0();

  if(op0.type()!=type)
  {
    std::cerr << expr.pretty() << std::endl;
    throw "add/sub with mixed types";
  }

  convert_bv(op0, bv);

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

  bool subtract=(expr.id()==ID_minus ||
                 expr.id()=="no-overflow-minus");
                 
  bool no_overflow=(expr.id()=="no-overflow-plus" ||
                    expr.id()=="no-overflow-minus");

  typet arithmetic_type=
    (type.id()==ID_vector)?ns.follow(type.subtype()):type;

  bv_utilst::representationt rep=
    (arithmetic_type.id()==ID_signedbv ||
     arithmetic_type.id()==ID_fixedbv)?bv_utilst::SIGNED:
                                       bv_utilst::UNSIGNED;

  for(exprt::operandst::const_iterator
      it=operands.begin()+1;
      it!=operands.end(); it++)
  {
    if(it->type()!=type)
    {
      std::cerr << expr.pretty() << std::endl;
      throw "add/sub with mixed types";
    }

    bvt op;
    convert_bv(*it, op);

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

    if(type.id()==ID_vector)
    {
      const typet &subtype=ns.follow(type.subtype());
    
      unsigned sub_width=boolbv_width(subtype);

      if(sub_width==0 || width%sub_width!=0)
        throw "convert_add_sub: unexpected vector operand width";

      unsigned size=width/sub_width;
      bv.resize(width);

      for(unsigned i=0; i<size; i++)
      {
        bvt tmp_op;
        tmp_op.resize(sub_width);

        for(unsigned j=0; j<tmp_op.size(); j++)
        {
          assert(i*sub_width+j<op.size());
          tmp_op[j]=op[i*sub_width+j];
        }
        
        bvt tmp_result;
        tmp_result.resize(sub_width);

        for(unsigned j=0; j<tmp_result.size(); j++)
        {
          assert(i*sub_width+j<bv.size());
          tmp_result[j]=bv[i*sub_width+j];
        }
        
        if(type.subtype().id()==ID_floatbv)
        {
          #ifdef HAVE_FLOATBV
          float_utilst float_utils(prop);
          float_utils.spec=to_floatbv_type(subtype);
          tmp_result=float_utils.add_sub(tmp_result, tmp_op, subtract);
          #else
          return conversion_failed(expr, bv);
          #endif
        }
        else
          tmp_result=bv_utils.add_sub(tmp_result, tmp_op, subtract);
      
        assert(tmp_result.size()==sub_width);
        
        for(unsigned j=0; j<tmp_result.size(); j++)
        {
          assert(i*sub_width+j<bv.size());
          bv[i*sub_width+j]=tmp_result[j];
        }
      }
    }
    else if(type.id()==ID_floatbv)
    {
      #ifdef HAVE_FLOATBV
      float_utilst float_utils(prop);
      float_utils.spec=to_floatbv_type(arithmetic_type);
      bv=float_utils.add_sub(bv, op, subtract);
      #else
      return conversion_failed(expr, bv);
      #endif
    }
    else if(no_overflow)
      bv=bv_utils.add_sub_no_overflow(bv, op, subtract, rep);
    else
      bv=bv_utils.add_sub(bv, op, subtract);
  }
}
bool boolbvt::type_conversion(
  const typet &src_type, const bvt &src,
  const typet &dest_type, bvt &dest)
{
  bvtypet dest_bvtype=get_bvtype(dest_type);
  bvtypet src_bvtype=get_bvtype(src_type);
  
  if(src_bvtype==IS_C_BIT_FIELD)
    return type_conversion(
      c_bit_field_replacement_type(to_c_bit_field_type(src_type), ns), src, dest_type, dest);

  if(dest_bvtype==IS_C_BIT_FIELD)
    return type_conversion(
      src_type, src, c_bit_field_replacement_type(to_c_bit_field_type(dest_type), ns), dest);

  std::size_t src_width=src.size();
  std::size_t dest_width=boolbv_width(dest_type);
  
  if(dest_width==0 || src_width==0)
    return true;
  
  dest.clear();
  dest.reserve(dest_width);

  if(dest_type.id()==ID_complex)
  {
    if(src_type==dest_type.subtype())
    {
      forall_literals(it, src)
      dest.push_back(*it);

      // pad with zeros
      for(std::size_t i=src.size(); i<dest_width; i++)
        dest.push_back(const_literal(false));

      return false;
    }
    else if(src_type.id()==ID_complex)
    {
      // recursively do both halfs
      bvt lower, upper, lower_res, upper_res;
      lower.assign(src.begin(), src.begin()+src.size()/2);
      upper.assign(src.begin()+src.size()/2, src.end());
      type_conversion(ns.follow(src_type.subtype()), lower, ns.follow(dest_type.subtype()), lower_res);
      type_conversion(ns.follow(src_type.subtype()), upper, ns.follow(dest_type.subtype()), upper_res);
      assert(lower_res.size()+upper_res.size()==dest_width);
      dest=lower_res;
      dest.insert(dest.end(), upper_res.begin(), upper_res.end());
      return false;
    }
  }
  
  if(src_type.id()==ID_complex)
  {
    assert(dest_type.id()!=ID_complex);
    if(dest_type.id()==ID_signedbv ||
       dest_type.id()==ID_unsignedbv ||
       dest_type.id()==ID_floatbv ||
       dest_type.id()==ID_fixedbv ||
       dest_type.id()==ID_c_enum ||
       dest_type.id()==ID_c_enum_tag ||
       dest_type.id()==ID_bool)
    {
      // A cast from complex x to real T
      // is (T) __real__ x.
      bvt tmp_src(src);
      tmp_src.resize(src.size()/2); // cut off imag part
      return type_conversion(src_type.subtype(), tmp_src, dest_type, dest);
    }
  }
  
  switch(dest_bvtype)
  {
  case IS_RANGE:
    if(src_bvtype==IS_UNSIGNED ||
       src_bvtype==IS_SIGNED ||
       src_bvtype==IS_C_BOOL)
    {
      mp_integer dest_from=to_range_type(dest_type).get_from();

      if(dest_from==0)
      {
        // do zero extension
        dest.resize(dest_width);
        for(std::size_t i=0; i<dest.size(); i++)
          dest[i]=(i<src.size()?src[i]:const_literal(false));

        return false;
      }
    }
    else if(src_bvtype==IS_RANGE) // range to range
    {
      mp_integer src_from=to_range_type(src_type).get_from();
      mp_integer dest_from=to_range_type(dest_type).get_from();

      if(dest_from==src_from)
      {
        // do zero extension, if needed
        dest=bv_utils.zero_extension(src, dest_width);
        return false;
      }
      else
      {
        // need to do arithmetic: add src_from-dest_from
        mp_integer offset=src_from-dest_from;
        dest=
          bv_utils.add(
            bv_utils.zero_extension(src, dest_width),
            bv_utils.build_constant(offset, dest_width));
      }

      return false;
    }
    break;
    
  case IS_FLOAT: // to float
    {
      float_utilst float_utils(prop);
      
      switch(src_bvtype)
      {
      case IS_FLOAT: // float to float
        // we don't have a rounding mode here,
        // which is why we refuse.
        break;

      case IS_SIGNED: // signed to float
      case IS_C_ENUM:
        float_utils.spec=to_floatbv_type(dest_type);
        dest=float_utils.from_signed_integer(src);
        return false;

      case IS_UNSIGNED: // unsigned to float
      case IS_C_BOOL: // _Bool to float
        float_utils.spec=to_floatbv_type(dest_type);
        dest=float_utils.from_unsigned_integer(src);
        return false;

      case IS_BV:
        assert(src_width==dest_width);
        dest=src;
        return false;

      default:
        if(src_type.id()==ID_bool)
        {
          // bool to float
          
          // build a one
          ieee_floatt f;
          f.spec=to_floatbv_type(dest_type);
          f.from_integer(1);
          
          dest=convert_bv(f.to_expr());

          assert(src_width==1);
          
          Forall_literals(it, dest)
            *it=prop.land(*it, src[0]);
            
          return false;
        }
      }
    }
    break;

  case IS_FIXED:
    if(src_bvtype==IS_FIXED)
    {
      // fixed to fixed
      
      std::size_t dest_fraction_bits=to_fixedbv_type(dest_type).get_fraction_bits(),
                  dest_int_bits=dest_width-dest_fraction_bits;
      std::size_t op_fraction_bits=to_fixedbv_type(src_type).get_fraction_bits(),
                  op_int_bits=src_width-op_fraction_bits;
      
      dest.resize(dest_width);
      
      // i == position after dot
      // i == 0: first position after dot

      for(std::size_t i=0; i<dest_fraction_bits; i++)
      {
        // position in bv
        std::size_t p=dest_fraction_bits-i-1;
      
        if(i<op_fraction_bits)
          dest[p]=src[op_fraction_bits-i-1];
        else 
          dest[p]=const_literal(false); // zero padding
      }

      for(std::size_t i=0; i<dest_int_bits; i++)
      {
        // position in bv
        std::size_t p=dest_fraction_bits+i;
        assert(p<dest_width);
      
        if(i<op_int_bits)
          dest[p]=src[i+op_fraction_bits];
        else 
          dest[p]=src[src_width-1]; // sign extension
      }

      return false;
    }
    else if(src_bvtype==IS_BV)
    {
      assert(src_width==dest_width);
      dest=src;
      return false;
    }
    else if(src_bvtype==IS_UNSIGNED ||
            src_bvtype==IS_SIGNED ||
            src_bvtype==IS_C_BOOL ||
            src_bvtype==IS_C_ENUM)
    {
      // integer to fixed

      std::size_t dest_fraction_bits=
        to_fixedbv_type(dest_type).get_fraction_bits();

      for(std::size_t i=0; i<dest_fraction_bits; i++)
        dest.push_back(const_literal(false)); // zero padding

      for(std::size_t i=0; i<dest_width-dest_fraction_bits; i++)
      {
        literalt l;
      
        if(i<src_width)
          l=src[i];
        else
        {
          if(src_bvtype==IS_SIGNED || src_bvtype==IS_C_ENUM)
            l=src[src_width-1]; // sign extension
          else
            l=const_literal(false); // zero extension
        }
        
        dest.push_back(l);
      }

      return false;
    }
    else if(src_type.id()==ID_bool)
    {
      // bool to fixed
      std::size_t fraction_bits=
        to_fixedbv_type(dest_type).get_fraction_bits();

      assert(src_width==1);

      for(std::size_t i=0; i<dest_width; i++)
      {
        if(i==fraction_bits)
          dest.push_back(src[0]);
        else
          dest.push_back(const_literal(false));
      }

      return false;
    }
    break;
  
  case IS_UNSIGNED:
  case IS_SIGNED:
  case IS_C_ENUM:
    switch(src_bvtype)
    {
    case IS_FLOAT: // float to integer
      // we don't have a rounding mode here,
      // which is why we refuse.
      break;
     
    case IS_FIXED: // fixed to integer
      {
        std::size_t op_fraction_bits=
          to_fixedbv_type(src_type).get_fraction_bits();

        for(std::size_t i=0; i<dest_width; i++)
        {
          if(i<src_width-op_fraction_bits)
            dest.push_back(src[i+op_fraction_bits]);
          else
          {
            if(dest_bvtype==IS_SIGNED)
              dest.push_back(src[src_width-1]); // sign extension
            else
              dest.push_back(const_literal(false)); // zero extension
          }
        }
        
        // we might need to round up in case of negative numbers
        // e.g., (int)(-1.00001)==1
        
        bvt fraction_bits_bv=src;
        fraction_bits_bv.resize(op_fraction_bits);
        literalt round_up=
          prop.land(prop.lor(fraction_bits_bv), src.back());

        dest=bv_utils.incrementer(dest, round_up);

        return false;
      }

    case IS_UNSIGNED: // integer to integer
    case IS_SIGNED:
    case IS_C_ENUM:
    case IS_C_BOOL:
      {
        // We do sign extension for any source type
        // that is signed, independently of the
        // destination type.
        // E.g., ((short)(ulong)(short)-1)==-1
        bool sign_extension=
          src_bvtype==IS_SIGNED || src_bvtype==IS_C_ENUM;

        for(std::size_t i=0; i<dest_width; i++)
        {
          if(i<src_width)
            dest.push_back(src[i]);
          else if(sign_extension)
            dest.push_back(src[src_width-1]); // sign extension
          else
            dest.push_back(const_literal(false));
        }

        return false;
      }
      
    case IS_VERILOG_UNSIGNED: // verilog_unsignedbv to signed/unsigned/enum
      {
        for(std::size_t i=0; i<dest_width; i++)
        {
          std::size_t src_index=i*2; // we take every second bit

          if(src_index<src_width)
            dest.push_back(src[src_index]);
          else // always zero-extend
            dest.push_back(const_literal(false));
        }

        return false;
      }
      break;
      
    case IS_VERILOG_SIGNED: // verilog_signedbv to signed/unsigned/enum
      {
        for(std::size_t i=0; i<dest_width; i++)
        {
          std::size_t src_index=i*2; // we take every second bit

          if(src_index<src_width)
            dest.push_back(src[src_index]);
          else // always sign-extend
            dest.push_back(src.back());
        }

        return false;
      }
      break;
      
    default:
      if(src_type.id()==ID_bool)
      {
        // bool to integer

        assert(src_width==1);

        for(std::size_t i=0; i<dest_width; i++)
        {
          if(i==0)
            dest.push_back(src[0]);
          else
            dest.push_back(const_literal(false));
        }

        return false;
      }
    }
    break;
    
  case IS_VERILOG_UNSIGNED:
    if(src_bvtype==IS_UNSIGNED ||
       src_bvtype==IS_C_BOOL ||
       src_type.id()==ID_bool)
    {
      for(std::size_t i=0, j=0; i<dest_width; i+=2, j++)
      {
        if(j<src_width)
          dest.push_back(src[j]);
        else
          dest.push_back(const_literal(false));

        dest.push_back(const_literal(false));
      }

      return false;
    }
    else if(src_bvtype==IS_SIGNED)
    {
      for(std::size_t i=0, j=0; i<dest_width; i+=2, j++)
      {
        if(j<src_width)
          dest.push_back(src[j]);
        else
          dest.push_back(src.back());

        dest.push_back(const_literal(false));
      }

      return false;
    }
    else if(src_bvtype==IS_VERILOG_UNSIGNED)
    {
      // verilog_unsignedbv to verilog_unsignedbv
      dest=src;

      if(dest_width<src_width)
        dest.resize(dest_width);
      else
      {
        dest=src;
        while(dest.size()<dest_width)
        {
          dest.push_back(const_literal(false));
          dest.push_back(const_literal(false));
        }
      }
      return false;
    }
    break;

  case IS_BV:
    assert(src_width==dest_width);
    dest=src;
    return false;
    
  case IS_C_BOOL:
    dest.resize(dest_width, const_literal(false));

    if(src_bvtype==IS_FLOAT)
    {
      float_utilst float_utils(prop);
      float_utils.spec=to_floatbv_type(src_type);
      dest[0]=!float_utils.is_zero(src);
    }
    else if(src_bvtype==IS_C_BOOL)
      dest[0]=src[0];
    else
      dest[0]=!bv_utils.is_zero(src);

    return false;
    
  default:
    if(dest_type.id()==ID_array)
    {
      if(src_width==dest_width)
      {
        dest=src;
        return false;
      }
    }
    else if(dest_type.id()==ID_struct)
    {
      const struct_typet &dest_struct =
        to_struct_type(dest_type);

      if(src_type.id()==ID_struct)
      {
        // we do subsets

        dest.resize(dest_width, const_literal(false));

        const struct_typet &op_struct =
          to_struct_type(src_type);

        const struct_typet::componentst &dest_comp=
          dest_struct.components();

        const struct_typet::componentst &op_comp=
          op_struct.components();

        // build offset maps
        offset_mapt op_offsets, dest_offsets;

        build_offset_map(op_struct, op_offsets);
        build_offset_map(dest_struct, dest_offsets);

        // build name map
        typedef std::map<irep_idt, unsigned> op_mapt;
        op_mapt op_map;

        for(std::size_t i=0; i<op_comp.size(); i++)
          op_map[op_comp[i].get_name()]=i;

        // now gather required fields
        for(std::size_t i=0;
            i<dest_comp.size();
            i++)
        {
          std::size_t offset=dest_offsets[i];
          std::size_t comp_width=boolbv_width(dest_comp[i].type());
          if(comp_width==0) continue;

          op_mapt::const_iterator it=
            op_map.find(dest_comp[i].get_name());

          if(it==op_map.end())
          {
            // not found

            // filling with free variables
            for(std::size_t j=0; j<comp_width; j++)
              dest[offset+j]=prop.new_variable();
          }
          else
          {
            // found
            if(dest_comp[i].type()!=dest_comp[it->second].type())
            {
              // filling with free variables
              for(std::size_t j=0; j<comp_width; j++)
                dest[offset+j]=prop.new_variable();
            }
            else
            {
              std::size_t op_offset=op_offsets[it->second];
              for(std::size_t j=0; j<comp_width; j++)
                dest[offset+j]=src[op_offset+j];
            }
          }
        }

        return false;
      }
    }

  }

  return true;
}
Exemple #12
0
void boolbvt::convert_unary_minus(const exprt &expr, bvt &bv)
{
  const typet &type=ns.follow(expr.type());

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

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

  if(operands.size()!=1)
    throw "unary minus takes one operand";
    
  const exprt &op0=expr.op0();

  const bvt &op_bv=convert_bv(op0);

  bvtypet bvtype=get_bvtype(type);
  bvtypet op_bvtype=get_bvtype(op0.type());
  unsigned op_width=op_bv.size();

  bool no_overflow=(expr.id()=="no-overflow-unary-minus");
  
  if(op_width==0 || op_width!=width)
    return conversion_failed(expr, bv);

  if(bvtype==IS_UNKNOWN &&
     (type.id()==ID_vector || type.id()==ID_complex))
  {
    const typet &subtype=ns.follow(type.subtype());
  
    unsigned sub_width=boolbv_width(subtype);

    if(sub_width==0 || width%sub_width!=0)
      throw "unary-: unexpected vector operand width";

    unsigned size=width/sub_width;
    bv.resize(width);

    for(unsigned i=0; i<size; i++)
    {
      bvt tmp_op;
      tmp_op.resize(sub_width);

      for(unsigned j=0; j<tmp_op.size(); j++)
      {
        assert(i*sub_width+j<op_bv.size());
        tmp_op[j]=op_bv[i*sub_width+j];
      }
      
      bvt tmp_result;
      
      if(type.subtype().id()==ID_floatbv)
      {
        float_utilst float_utils(prop);
        float_utils.spec=to_floatbv_type(subtype);
        tmp_result=float_utils.negate(tmp_op);
      }
      else
        tmp_result=bv_utils.negate(tmp_op);
    
      assert(tmp_result.size()==sub_width);
      
      for(unsigned j=0; j<tmp_result.size(); j++)
      {
        assert(i*sub_width+j<bv.size());
        bv[i*sub_width+j]=tmp_result[j];
      }
    }

    return;
  }
  else if(bvtype==IS_FIXED && op_bvtype==IS_FIXED)
  {
    if(no_overflow)
      bv=bv_utils.negate_no_overflow(op_bv);
    else
      bv=bv_utils.negate(op_bv);

    return;
  }
  else if(bvtype==IS_FLOAT && op_bvtype==IS_FLOAT)
  {
    assert(!no_overflow);
    float_utilst float_utils(prop);
    float_utils.spec=to_floatbv_type(expr.type());
    bv=float_utils.negate(op_bv);
    return;
  }
  else if((op_bvtype==IS_SIGNED || op_bvtype==IS_UNSIGNED) &&
          (bvtype==IS_SIGNED || bvtype==IS_UNSIGNED))
  {
    if(no_overflow)
      prop.l_set_to(bv_utils.overflow_negate(op_bv), false);

    if(no_overflow)
      bv=bv_utils.negate_no_overflow(op_bv);
    else
      bv=bv_utils.negate(op_bv);

    return;
  }

  conversion_failed(expr, bv);
}
void boolbvt::convert_constraint_select_one(const exprt &expr, bvt &bv)
{
  const exprt::operandst &operands=expr.operands();

  if(expr.id()!="constraint_select_one")
    throw "expected constraint_select_one expression";

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

  if(expr.type()!=expr.op0().type())
    throw "constraint_select_one expects matching types";
    
  if(prop.has_set_to())
  {
    std::vector<bvt> op_bv;
    op_bv.reserve(expr.operands().size());

    forall_operands(it, expr)
      op_bv.push_back(convert_bv(*it));

    bv=op_bv[0];

    // add constraints

    bvt equal_bv;
    equal_bv.resize(bv.size());

    bvt b;
    b.reserve(op_bv.size()-1);

    for(unsigned i=1; i<op_bv.size(); i++)
    {
      if(op_bv[i].size()!=bv.size())
        throw "constraint_select_one expects matching width";

      for(unsigned j=0; j<bv.size(); j++)
        equal_bv[j]=prop.lequal(bv[j], op_bv[i][j]);

      b.push_back(prop.land(equal_bv));
    }

    prop.l_set_to_true(prop.lor(b));
  }
  else
  {
    unsigned op_nr=0;
    forall_operands(it, expr)
    {
      const bvt &op_bv=convert_bv(*it);

      if(op_nr==0)
        bv=op_bv;
      else
      {
        if(op_bv.size()!=bv.size())
          return conversion_failed(expr, bv);

        for(unsigned i=0; i<op_bv.size(); i++)
          bv[i]=prop.lselect(prop.new_variable(), bv[i], op_bv[i]);
      }

      op_nr++;
    }
  }
}
void boolbvt::convert_case(const exprt &expr, bvt &bv)
{
  const std::vector<exprt> &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()<3)
    throw "case takes at least three operands";

  if((operands.size()%2)!=1)
    throw "number of case operands must be odd";

  enum { FIRST, COMPARE, VALUE } what=FIRST;
  bvt compare_bv;
  literalt previous_compare=const_literal(false);
  literalt compare_literal=const_literal(false);

  forall_operands(it, expr)
  {
    bvt op=convert_bv(*it);

    switch(what)
    {
    case FIRST:
      compare_bv.swap(op);
      what=COMPARE;
      break;

    case COMPARE:
      if(compare_bv.size()!=op.size())
      {
        std::cerr << "compare operand: " << compare_bv.size()
                  << std::endl
                  << "operand: " << op.size() << std::endl
                  << it->pretty()
                  << std::endl;

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

      compare_literal=bv_utils.equal(compare_bv, op);
      compare_literal=prop.land(prop.lnot(previous_compare),
                           compare_literal);

      previous_compare=prop.lor(previous_compare, compare_literal);

      what=VALUE;
      break;

    case VALUE: 
      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(compare_literal, value_literal));
      }

      what=COMPARE;
      break;

    default:
      assert(false);
    }
  }
Exemple #15
0
void boolbvt::convert_floatbv_op(const exprt &expr, bvt &bv)
{
  const exprt::operandst &operands=expr.operands();
  
  if(operands.size()!=3)
    throw "operator "+expr.id_string()+" takes three operands";

  const exprt &op0=expr.op0(); // first operand
  const exprt &op1=expr.op1(); // second operand
  const exprt &op2=expr.op2(); // rounding mode

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

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

  if(op0.type()!=type || op1.type()!=type)
  {
    std::cerr << expr.pretty() << std::endl;
    throw "float op with mixed types";
  }

  float_utilst float_utils(prop);
  
  float_utils.set_rounding_mode(bv2);

  if(type.id()==ID_floatbv)
  {
    float_utils.spec=to_floatbv_type(expr.type());

    if(expr.id()==ID_floatbv_plus)
      bv=float_utils.add_sub(bv0, bv1, false);
    else if(expr.id()==ID_floatbv_minus)
      bv=float_utils.add_sub(bv0, bv1, true);
    else if(expr.id()==ID_floatbv_mult)
      bv=float_utils.mul(bv0, bv1);
    else if(expr.id()==ID_floatbv_div)
      bv=float_utils.div(bv0, bv1);
    else if(expr.id()==ID_floatbv_rem)
      bv=float_utils.rem(bv0, bv1);
    else
      assert(false);
  }
  else if(type.id()==ID_vector || type.id()==ID_complex)
  {
    const typet &subtype=ns.follow(type.subtype());
    
    if(subtype.id()==ID_floatbv)
    {
      float_utils.spec=to_floatbv_type(subtype);

      std::size_t width=boolbv_width(type);
      std::size_t sub_width=boolbv_width(subtype);

      if(sub_width==0 || width%sub_width!=0)
        throw "convert_floatbv_op: unexpected vector operand width";

      std::size_t size=width/sub_width;
      bv.resize(width);

      for(std::size_t i=0; i<size; i++)
      {
        bvt tmp_bv0, tmp_bv1, tmp_bv;
        
        tmp_bv0.assign(bv0.begin()+i*sub_width, bv0.begin()+(i+1)*sub_width);
        tmp_bv1.assign(bv1.begin()+i*sub_width, bv1.begin()+(i+1)*sub_width);

        if(expr.id()==ID_floatbv_plus)
          tmp_bv=float_utils.add_sub(tmp_bv0, tmp_bv1, false);
        else if(expr.id()==ID_floatbv_minus)
          tmp_bv=float_utils.add_sub(tmp_bv0, tmp_bv1, true);
        else if(expr.id()==ID_floatbv_mult)
          tmp_bv=float_utils.mul(tmp_bv0, tmp_bv1);
        else if(expr.id()==ID_floatbv_div)
          tmp_bv=float_utils.div(tmp_bv0, tmp_bv1);
        else
          assert(false);

        assert(tmp_bv.size()==sub_width);
        assert(i*sub_width+sub_width-1<bv.size());
        std::copy(tmp_bv.begin(), tmp_bv.end(), bv.begin()+i*sub_width);
      }
    }
    else
      return conversion_failed(expr, bv);
  }
  else
    return conversion_failed(expr, bv);
}
Exemple #16
0
exprt boolbvt::bv_get_rec(
    const bvt &bv,
    const std::vector<bool> &unknown,
    std::size_t offset,
    const typet &type) const
{
    if(type.id()==ID_symbol)
        return bv_get_rec(bv, unknown, offset, ns.follow(type));

    std::size_t width=boolbv_width(type);

    assert(bv.size()==unknown.size());
    assert(bv.size()>=offset+width);

    if(type.id()==ID_bool)
    {
        if(!unknown[offset])
        {
            switch(prop.l_get(bv[offset]).get_value())
            {
            case tvt::tv_enumt::TV_FALSE:
                return false_exprt();
            case tvt::tv_enumt::TV_TRUE:
                return true_exprt();
            default:
                return false_exprt(); // default
            }
        }

        return nil_exprt();
    }

    bvtypet bvtype=get_bvtype(type);

    if(bvtype==IS_UNKNOWN)
    {
        if(type.id()==ID_array)
        {
            const typet &subtype=type.subtype();
            std::size_t sub_width=boolbv_width(subtype);

            if(sub_width!=0)
            {
                exprt::operandst op;
                op.reserve(width/sub_width);

                for(std::size_t new_offset=0;
                        new_offset<width;
                        new_offset+=sub_width)
                {
                    op.push_back(
                        bv_get_rec(bv, unknown, offset+new_offset, subtype));
                }

                exprt dest=exprt(ID_array, type);
                dest.operands().swap(op);
                return dest;
            }
        }
        else if(type.id()==ID_struct_tag)
        {
            return bv_get_rec(bv, unknown, offset, ns.follow_tag(to_struct_tag_type(type)));
        }
        else if(type.id()==ID_union_tag)
        {
            return bv_get_rec(bv, unknown, offset, ns.follow_tag(to_union_tag_type(type)));
        }
        else if(type.id()==ID_struct)
        {
            const struct_typet &struct_type=to_struct_type(type);
            const struct_typet::componentst &components=struct_type.components();
            std::size_t new_offset=0;
            exprt::operandst op;
            op.reserve(components.size());

            for(struct_typet::componentst::const_iterator
                    it=components.begin();
                    it!=components.end();
                    it++)
            {
                const typet &subtype=ns.follow(it->type());
                op.push_back(nil_exprt());

                std::size_t sub_width=boolbv_width(subtype);

                if(sub_width!=0)
                {
                    op.back()=bv_get_rec(bv, unknown, offset+new_offset, subtype);
                    new_offset+=sub_width;
                }
            }

            struct_exprt dest(type);
            dest.operands().swap(op);
            return dest;
        }
        else if(type.id()==ID_union)
        {
            const union_typet &union_type=to_union_type(type);
            const union_typet::componentst &components=union_type.components();

            assert(!components.empty());

            // Any idea that's better than just returning the first component?
            std::size_t component_nr=0;

            union_exprt value(union_type);

            value.set_component_name(
                components[component_nr].get_name());

            const typet &subtype=components[component_nr].type();

            value.op()=bv_get_rec(bv, unknown, offset, subtype);

            return value;
        }
        else if(type.id()==ID_vector)
        {
            const typet &subtype=ns.follow(type.subtype());
            std::size_t sub_width=boolbv_width(subtype);

            if(sub_width!=0 && width%sub_width==0)
            {
                std::size_t size=width/sub_width;
                exprt value(ID_vector, type);
                value.operands().resize(size);

                for(std::size_t i=0; i<size; i++)
                    value.operands()[i]=
                        bv_get_rec(bv, unknown, i*sub_width, subtype);

                return value;
            }
        }
        else if(type.id()==ID_complex)
        {
            const typet &subtype=ns.follow(type.subtype());
            std::size_t sub_width=boolbv_width(subtype);

            if(sub_width!=0 && width==sub_width*2)
            {
                exprt value(ID_complex, type);
                value.operands().resize(2);

                value.op0()=bv_get_rec(bv, unknown, 0*sub_width, subtype);
                value.op1()=bv_get_rec(bv, unknown, 1*sub_width, subtype);

                return value;
            }
        }
    }

    std::string value;

    for(std::size_t bit_nr=offset; bit_nr<offset+width; bit_nr++)
    {
        char ch;
        if(unknown[bit_nr])
            ch='0';
        else
            switch(prop.l_get(bv[bit_nr]).get_value())
            {
            case tvt::tv_enumt::TV_FALSE:
                ch='0';
                break;
            case tvt::tv_enumt::TV_TRUE:
                ch='1';
                break;
            case tvt::tv_enumt::TV_UNKNOWN:
                ch='0';
                break;
            default:
                assert(false);
            }

        value=ch+value;
    }

    switch(bvtype)
    {
    case IS_UNKNOWN:
        if(type.id()==ID_string)
        {
            mp_integer int_value=binary2integer(value, false);
            irep_idt s;
            if(int_value>=string_numbering.size())
                s=irep_idt();
            else
                s=string_numbering[int_value.to_long()];

            return constant_exprt(s, type);
        }
        break;

    case IS_RANGE:
    {
        mp_integer int_value=binary2integer(value, false);
        mp_integer from=string2integer(type.get_string(ID_from));

        constant_exprt value_expr(type);
        value_expr.set_value(integer2string(int_value+from));
        return value_expr;
    }
    break;

    default:
    case IS_C_ENUM:
        constant_exprt value_expr(type);
        value_expr.set_value(value);
        return value_expr;
    }

    return nil_exprt();
}
Exemple #17
0
void prop_convt::set_frozen(const bvt &bv)
{
  for(unsigned i=0; i<bv.size(); i++)
    if(!bv[i].is_constant())
      set_frozen(bv[i]);
}
Exemple #18
0
void boolbvt::convert_with_array(
  const array_typet &type,
  const exprt &op1,
  const exprt &op2,
  const bvt &prev_bv,
  bvt &next_bv)
{
  if(is_unbounded_array(type))
  {
    // can't do this
    error().source_location=type.source_location();
    error() << "convert_with_array called for unbounded array" << eom;
    throw 0;
  }

  const exprt &array_size=type.size();

  mp_integer size;

  if(to_integer(array_size, size))
  {
    error().source_location=type.source_location();
    error() << "convert_with_array expects constant array size" << eom;
    throw 0;
  }

  const bvt &op2_bv=convert_bv(op2);

  if(size*op2_bv.size()!=prev_bv.size())
  {
    error().source_location=type.source_location();
    error() << "convert_with_array: unexpected operand 2 width" << eom;
    throw 0;
  }

  // Is the index a constant?
  mp_integer op1_value;
  if(!to_integer(op1, op1_value))
  {
    // Yes, it is!
    next_bv=prev_bv;

    if(op1_value>=0 && op1_value<size) // bounds check
    {
      std::size_t offset=integer2unsigned(op1_value*op2_bv.size());

      for(std::size_t j=0; j<op2_bv.size(); j++)
        next_bv[offset+j]=op2_bv[j];
    }

    return;
  }

  typet counter_type=op1.type();

  for(mp_integer i=0; i<size; i=i+1)
  {
    exprt counter=from_integer(i, counter_type);

    literalt eq_lit=convert(equal_exprt(op1, counter));

    std::size_t offset=integer2unsigned(i*op2_bv.size());

    for(std::size_t j=0; j<op2_bv.size(); j++)
      next_bv[offset+j]=
        prop.lselect(eq_lit, op2_bv[j], prev_bv[offset+j]);
  }
}
Exemple #19
0
void float_utilst::normalization_shift(bvt &fraction, bvt &exponent)
{
  #if 0
  // this thing is quadratic!

  bvt new_fraction=prop.new_variables(fraction.size());
  bvt new_exponent=prop.new_variables(exponent.size());

  // i is the shift distance
  for(std::size_t i=0; i<fraction.size(); i++)
  {
    bvt equal;

    // the bits above need to be zero
    for(std::size_t j=0; j<i; j++)
      equal.push_back(
        !fraction[fraction.size()-1-j]);

    // this one needs to be one
    equal.push_back(fraction[fraction.size()-1-i]);

    // iff all of that holds, we shift here!
    literalt shift=prop.land(equal);

    // build shifted value
    bvt shifted_fraction=bv_utils.shift(fraction, bv_utilst::LEFT, i);
    bv_utils.cond_implies_equal(shift, shifted_fraction, new_fraction);

    // build new exponent
    bvt adjustment=bv_utils.build_constant(-i, exponent.size());
    bvt added_exponent=bv_utils.add(exponent, adjustment);
    bv_utils.cond_implies_equal(shift, added_exponent, new_exponent);
  }

  // Fraction all zero? It stays zero.
  // The exponent is undefined in that case.
  literalt fraction_all_zero=bv_utils.is_zero(fraction);
  bvt zero_fraction;
  zero_fraction.resize(fraction.size(), const_literal(false));
  bv_utils.cond_implies_equal(fraction_all_zero, zero_fraction, new_fraction);

  fraction=new_fraction;
  exponent=new_exponent;

  #else

  // n-log-n alignment shifter.
  // The worst-case shift is the number of fraction
  // bits minus one, in case the faction is one exactly.
  assert(!fraction.empty());
  unsigned depth=integer2unsigned(address_bits(fraction.size()-1));

  if(exponent.size()<depth)
    exponent=bv_utils.sign_extension(exponent, depth);

  bvt exponent_delta=bv_utils.zeros(exponent.size());

  for(int d=depth-1; d>=0; d--)
  {
    std::size_t distance=(1<<d);
    assert(fraction.size()>distance);

    // check if first 'distance'-many bits are zeros
    const bvt prefix=bv_utils.extract_msb(fraction, distance);
    literalt prefix_is_zero=bv_utils.is_zero(prefix);

    // If so, shift the zeros out left by 'distance'.
    // Otherwise, leave as is.
    const bvt shifted=
      bv_utils.shift(fraction, bv_utilst::LEFT, distance);

    fraction=
      bv_utils.select(prefix_is_zero, shifted, fraction);

    // add corresponding weight to exponent
    assert(d<(signed)exponent_delta.size());
    exponent_delta[d]=prefix_is_zero;
  }

  exponent=bv_utils.sub(exponent, exponent_delta);

  #endif
}
Exemple #20
0
bvt float_utilst::add_sub(
  const bvt &src1,
  const bvt &src2,
  bool subtract)
{
  unbiased_floatt unpacked1=unpack(src1);
  unbiased_floatt unpacked2=unpack(src2);

  // subtract?
  if(subtract)
    unpacked2.sign=!unpacked2.sign;

  // figure out which operand has the bigger exponent
  const bvt exponent_difference=subtract_exponents(unpacked1, unpacked2);
  literalt src2_bigger=exponent_difference.back();

  const bvt bigger_exponent=
    bv_utils.select(src2_bigger, unpacked2.exponent, unpacked1.exponent);

  // swap fractions as needed
  const bvt new_fraction1=
    bv_utils.select(src2_bigger, unpacked2.fraction, unpacked1.fraction);

  const bvt new_fraction2=
    bv_utils.select(src2_bigger, unpacked1.fraction, unpacked2.fraction);

  // compute distance
  const bvt distance=bv_utils.absolute_value(exponent_difference);

  // limit the distance: shifting more than f+3 bits is unnecessary
  const bvt limited_dist=limit_distance(distance, spec.f+3);

  // pad fractions with 2 zeros from below
  const bvt fraction1_padded=bv_utils.concatenate(bv_utils.zeros(3), new_fraction1);
  const bvt fraction2_padded=bv_utils.concatenate(bv_utils.zeros(3), new_fraction2);

  // shift new_fraction2
  literalt sticky_bit;
  const bvt fraction1_shifted=fraction1_padded;
  const bvt fraction2_shifted=sticky_right_shift(
    fraction2_padded, limited_dist, sticky_bit);

  // sticky bit: or of the bits lost by the right-shift
  bvt fraction2_stickied=fraction2_shifted;
  fraction2_stickied[0]=prop.lor(fraction2_shifted[0], sticky_bit);

  // need to have two extra fraction bits for addition and rounding
  const bvt fraction1_ext=bv_utils.zero_extension(fraction1_shifted, fraction1_shifted.size()+2);
  const bvt fraction2_ext=bv_utils.zero_extension(fraction2_stickied, fraction2_stickied.size()+2);

  unbiased_floatt result;

  // now add/sub them
  literalt subtract_lit=prop.lxor(unpacked1.sign, unpacked2.sign);
  result.fraction=
    bv_utils.add_sub(fraction1_ext, fraction2_ext, subtract_lit);

  // sign of result
  literalt fraction_sign=result.fraction.back();
  result.fraction=bv_utils.absolute_value(result.fraction);

  result.exponent=bigger_exponent;

  // adjust the exponent for the fact that we added two bits to the fraction
  result.exponent=
    bv_utils.add(bv_utils.sign_extension(result.exponent, result.exponent.size()+1),
      bv_utils.build_constant(2, result.exponent.size()+1));

  // NaN?
  result.NaN=prop.lor(
      prop.land(prop.land(unpacked1.infinity, unpacked2.infinity),
                prop.lxor(unpacked1.sign, unpacked2.sign)),
      prop.lor(unpacked1.NaN, unpacked2.NaN));

  // infinity?
  result.infinity=prop.land(
      !result.NaN,
      prop.lor(unpacked1.infinity, unpacked2.infinity));

  // zero?
  // Note that:
  //  1. The zero flag isn't used apart from in divide and
  //     is only set on unpack
  //  2. Subnormals mean that addition or subtraction can't round to 0,
  //     thus we can perform this test now
  //  3. The rules for sign are different for zero
  result.zero = prop.land(
      !prop.lor(result.infinity, result.NaN),
      !prop.lor(result.fraction));


  // sign
  literalt add_sub_sign=
    prop.lxor(prop.lselect(src2_bigger, unpacked2.sign, unpacked1.sign),
              fraction_sign);

  literalt infinity_sign=
    prop.lselect(unpacked1.infinity, unpacked1.sign, unpacked2.sign);

  #if 1
  literalt zero_sign=
    prop.lselect(rounding_mode_bits.round_to_minus_inf,
                 prop.lor(unpacked1.sign, unpacked2.sign),
                 prop.land(unpacked1.sign, unpacked2.sign));

  result.sign=prop.lselect(
    result.infinity,
    infinity_sign,
    prop.lselect(result.zero,
                 zero_sign,
                 add_sub_sign));
  #else
  result.sign=prop.lselect(
    result.infinity,
    infinity_sign,
    add_sub_sign);
  #endif

  #if 0
  result.sign=const_literal(false);
  result.fraction.resize(spec.f+1, const_literal(true));
  result.exponent.resize(spec.e, const_literal(false));
  result.NaN=const_literal(false);
  result.infinity=const_literal(false);
  //for(std::size_t i=0; i<result.fraction.size(); i++)
  //  result.fraction[i]=const_literal(true);

  for(std::size_t i=0; i<result.fraction.size(); i++)
    result.fraction[i]=new_fraction2[i];

  return pack(bias(result));
  #endif

  return rounder(result);
}
Exemple #21
0
bvt float_utilst::conversion(
  const bvt &src,
  const ieee_float_spect &dest_spec)
{
  assert(src.size()==spec.width());

  #if 1
  // Catch the special case in which we extend,
  // e.g. single to double.
  // In this case, rounding can be avoided,
  // but a denormal number may be come normal.
  // Be careful to exclude the difficult case
  // when denormalised numbers in the old format
  // can be converted to denormalised numbers in the
  // new format.  Note that this is rare and will only
  // happen with very non-standard formats.

  int sourceSmallestNormalExponent = -((1 << (spec.e - 1)) - 1);
  int sourceSmallestDenormalExponent =
    sourceSmallestNormalExponent - spec.f;

  // Using the fact that f doesn't include the hidden bit

  int destSmallestNormalExponent = -((1 << (dest_spec.e - 1)) - 1);

  if(dest_spec.e>=spec.e &&
     dest_spec.f>=spec.f &&
     !(sourceSmallestDenormalExponent < destSmallestNormalExponent))
  {
    unbiased_floatt unpacked_src=unpack(src);
    unbiased_floatt result;

    // the fraction gets zero-padded
    std::size_t padding=dest_spec.f-spec.f;
    result.fraction=
      bv_utils.concatenate(bv_utils.zeros(padding), unpacked_src.fraction);

    // the exponent gets sign-extended
    result.exponent=
      bv_utils.sign_extension(unpacked_src.exponent, dest_spec.e);

    // if the number was denormal and is normal in the new format,
    // normalise it!
    if(dest_spec.e > spec.e)
    {
      normalization_shift(result.fraction,result.exponent);
    }

    // the flags get copied
    result.sign=unpacked_src.sign;
    result.NaN=unpacked_src.NaN;
    result.infinity=unpacked_src.infinity;

    // no rounding needed!
    spec=dest_spec;
    return pack(bias(result));
  }
  else
  #endif
  {
    // we actually need to round
    unbiased_floatt result=unpack(src);
    spec=dest_spec;
    return rounder(result);
  }
}
Exemple #22
0
void float_utilst::denormalization_shift(bvt &fraction, bvt &exponent)
{
  mp_integer bias=spec.bias();

  // Is the exponent strictly less than -bias+1, i.e., exponent<-bias+1?
  // This is transformed to distance=(-bias+1)-exponent
  // i.e., distance>0
  // Note that 1-bias is the exponent represented by 0...01,
  // i.e. the exponent of the smallest normal number and thus the 'base'
  // exponent for subnormal numbers.

  assert(exponent.size()>=spec.e);

#if 1
  // Need to sign extend to avoid overflow.  Note that this is a
  // relatively rare problem as the value needs to be close to the top
  // of the exponent range and then range must not have been
  // previously extended as add, multiply, etc. do.  This is primarily
  // to handle casting down from larger ranges.
  exponent = bv_utils.sign_extension(exponent, exponent.size() + 1);
#endif

  bvt distance=bv_utils.sub(
    bv_utils.build_constant(-bias+1, exponent.size()), exponent);

  // use sign bit
  literalt denormal=prop.land(
    !distance.back(),
    !bv_utils.is_zero(distance));

#if 1
  // Care must be taken to not loose information required for the
  // guard and sticky bits.  +3 is for the hidden, guard and sticky bits.
  if (fraction.size() < (spec.f + 3))
  {
    // Add zeros at the LSB end for the guard bit to shift into
    fraction=
      bv_utils.concatenate(bv_utils.zeros((spec.f + 3) - fraction.size()),
                           fraction);
  }

  bvt denormalisedFraction = fraction;

  literalt sticky_bit = const_literal(false);
  denormalisedFraction =
    sticky_right_shift(fraction, distance, sticky_bit);
  denormalisedFraction[0] = prop.lor(denormalisedFraction[0], sticky_bit);

  fraction=
    bv_utils.select(
      denormal,
      denormalisedFraction,
      fraction);

#else
  fraction=
    bv_utils.select(
      denormal,
      bv_utils.shift(fraction, bv_utilst::LRIGHT, distance),
      fraction);
#endif

  exponent=
    bv_utils.select(denormal,
      bv_utils.build_constant(-bias, exponent.size()),
      exponent);
}
Exemple #23
0
void boolbvt::convert_update_rec(
  const exprt::operandst &designators,
  std::size_t d,
  const typet &type,
  std::size_t offset,
  const exprt &new_value,
  bvt &bv)
{
  if(type.id()==ID_symbol)
    convert_update_rec(
      designators, d, ns.follow(type), offset, new_value, bv);

  if(d>=designators.size())
  {
    // done
    bvt new_value_bv=convert_bv(new_value);
    std::size_t new_value_width=boolbv_width(type);
    
    if(new_value_width!=new_value_bv.size())
      throw "convert_update_rec: unexpected new_value size";

    // update
    for(std::size_t i=0; i<new_value_width; i++)
    {
      assert(offset+i<bv.size());
      bv[offset+i]=new_value_bv[i];
    }
    
    return;
  }

  const exprt &designator=designators[d];

  if(designator.id()==ID_index_designator)
  {
    if(type.id()!=ID_array)
      throw "update: index designator needs array";
      
    if(designator.operands().size()!=1)
      throw "update: index designator takes one operand";
      
    bvt index_bv=convert_bv(designator.op0());

    const array_typet &array_type=to_array_type(type);
    
    const typet &subtype=ns.follow(array_type.subtype());

    std::size_t element_size=boolbv_width(subtype);

    // iterate over array
    mp_integer size;
    if(to_integer(array_type.size(), size))
      throw "update: failed to get array size";
      
    bvt tmp_bv=bv;
    
    for(std::size_t i=0; i!=integer2long(size); ++i)
    {
      std::size_t new_offset=offset+i*element_size;
      
      convert_update_rec(
        designators, d+1, subtype, new_offset, new_value, tmp_bv);

      bvt const_bv=bv_utils.build_constant(i, index_bv.size());
      literalt equal=bv_utils.equal(const_bv, index_bv);

      for(std::size_t j=0; j<element_size; j++)
      {
        std::size_t idx=new_offset+j;
        assert(idx<bv.size());
        bv[idx]=prop.lselect(equal, tmp_bv[idx], bv[idx]);
      }
    }
  }
  else if(designator.id()==ID_member_designator)
  {
    const irep_idt &component_name=designator.get(ID_component_name);
  
    if(type.id()==ID_struct)
    {
      const struct_typet &struct_type=
        to_struct_type(type);

      std::size_t struct_offset=0;
      
      struct_typet::componentt component;
      component.make_nil();

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

      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)
        {
          component=*it;
          break; // done
        }

        struct_offset+=sub_width;
      }
        
      if(component.is_nil())
        throw "update: failed to find struct component";

      const typet &new_type=ns.follow(component.type());

      std::size_t new_offset=offset+struct_offset;

      // recursive call
      convert_update_rec(
        designators, d+1, new_type, new_offset, new_value, bv);
    }
    else if(type.id()==ID_union)
    {
      const union_typet &union_type=
        to_union_type(type);

      const union_typet::componentt &component=
        union_type.get_component(component_name);
        
      if(component.is_nil())
        throw "update: failed to find union component";

      // this only adjusts the type, the offset stays as-is

      const typet &new_type=ns.follow(component.type());

      // recursive call
      convert_update_rec(
        designators, d+1, new_type, offset, new_value, bv);
    }
    else
      throw "update: member designator needs struct or union";
  }
  else
    throw "update: unexpected designator";
}
Exemple #24
0
void bv_utilst::set_equal(const bvt &a, const bvt &b)
{
  assert(a.size()==b.size());
  for(std::size_t i=0; i<a.size(); i++)
    prop.set_equal(a[i], b[i]);
}
Exemple #25
0
exprt boolbvt::bv_get(const bvt &bv, const typet &type) const
{
    std::vector<bool> unknown;
    unknown.resize(bv.size(), false);
    return bv_get_rec(bv, unknown, 0, type);
}
Exemple #26
0
void boolbvt::convert_byte_update(
  const byte_update_exprt &expr,
  bvt &bv)
{
  if(expr.operands().size()!=3)
    throw "byte_update takes three operands";
    
  const exprt &op=expr.op0();
  const exprt &offset_expr=expr.offset();
  const exprt &value=expr.value();

  bool little_endian;
  
  if(expr.id()==ID_byte_update_little_endian)
    little_endian=true;
  else if(expr.id()==ID_byte_update_big_endian)
    little_endian=false;
  else
    assert(false);

  bv=convert_bv(op);
  
  const bvt &value_bv=convert_bv(value);
  std::size_t update_width=value_bv.size();
  std::size_t byte_width=8;
  
  if(update_width>bv.size())
    update_width=bv.size();

  // see if the byte number is constant

  mp_integer index;
  if(!to_integer(offset_expr, index))
  {
    // yes!
    mp_integer offset=index*8;
    
    if(offset+update_width>mp_integer(bv.size()) || offset<0)
    {
      // out of bounds
    }
    else
    {
      if(little_endian)
      {
        for(std::size_t i=0; i<update_width; i++)
          bv[integer2long(offset+i)]=value_bv[i];
      }
      else
      {
        endianness_mapt map_op(op.type(), false, ns);
        endianness_mapt map_value(value.type(), false, ns);
        
        std::size_t offset_i=integer2unsigned(offset);
        
        for(std::size_t i=0; i<update_width; i++)
          bv[map_op.map_bit(offset_i+i)]=value_bv[map_value.map_bit(i)];
      }
    }

    return;
  }

  // byte_update with variable index
  for(std::size_t offset=0; offset<bv.size(); offset+=byte_width)
  {
    // index condition
    equal_exprt equality;
    equality.lhs()=offset_expr;
    equality.rhs()=from_integer(offset/byte_width, offset_expr.type());
    literalt equal=convert(equality);
    
    endianness_mapt map_op(op.type(), little_endian, ns);
    endianness_mapt map_value(value.type(), little_endian, ns);

    for(std::size_t bit=0; bit<update_width; bit++)
      if(offset+bit<bv.size())
      {
        std::size_t bv_o=map_op.map_bit(offset+bit);
        std::size_t value_bv_o=map_value.map_bit(bit);
        
        bv[bv_o]=prop.lselect(equal, value_bv[value_bv_o], bv[bv_o]);
      }
  }
}
Exemple #27
0
void boolbvt::convert_mult(const exprt &expr, bvt &bv)
{
  unsigned width=boolbv_width(expr.type());
  
  if(width==0)
    return conversion_failed(expr, bv);

  bv.resize(width);

  const exprt::operandst &operands=expr.operands();
  if(operands.size()==0)
    throw "mult without operands";

  const exprt &op0=expr.op0();

  bool no_overflow=expr.id()=="no-overflow-mult";
  
  if(expr.type().id()==ID_fixedbv)
  {
    if(op0.type()!=expr.type())
      throw "multiplication with mixed types";
    
    bv=convert_bv(op0);

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

    unsigned fraction_bits=
      to_fixedbv_type(expr.type()).get_fraction_bits();
             
    // do a sign extension by fraction_bits bits
    bv=bv_utils.sign_extension(bv, bv.size()+fraction_bits);
      
    for(exprt::operandst::const_iterator it=operands.begin()+1;
        it!=operands.end(); it++)
    {
      if(it->type()!=expr.type())
        throw "multiplication with mixed types";

      bvt op=convert_bv(*it);

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

      op=bv_utils.sign_extension(op, bv.size());

      bv=bv_utils.signed_multiplier(bv, op);
    }
    
    // cut it down again
    bv.erase(bv.begin(), bv.begin()+fraction_bits);

    return;
  }
  else if(expr.type().id()==ID_floatbv)
  {
    if(op0.type()!=expr.type())
      throw "multiplication with mixed types";
    
    bv=convert_bv(op0);

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

    float_utilst float_utils(prop);
    float_utils.spec=to_floatbv_type(expr.type());

    for(exprt::operandst::const_iterator it=operands.begin()+1;
        it!=operands.end(); it++)
    {
      if(it->type()!=expr.type())
        throw "multiplication with mixed types";

      const bvt &op=convert_bv(*it);

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

      bv=float_utils.mul(bv, op);
    }
    
    return;
  }
  else if(expr.type().id()==ID_unsignedbv ||
          expr.type().id()==ID_signedbv)
  {
    if(op0.type()!=expr.type())
      throw "multiplication with mixed types";
      
    bv_utilst::representationt rep=
      expr.type().id()==ID_signedbv?bv_utilst::SIGNED:
                                    bv_utilst::UNSIGNED;
    
    bv=convert_bv(op0);

    if(bv.size()!=width)
      throw "convert_mult: unexpected operand width";
      
    for(exprt::operandst::const_iterator it=operands.begin()+1;
        it!=operands.end(); it++)
    {
      if(it->type()!=expr.type())
        throw "multiplication with mixed types";

      const bvt &op=convert_bv(*it);

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

      if(no_overflow)
        bv=bv_utils.multiplier_no_overflow(bv, op, rep);
      else
        bv=bv_utils.multiplier(bv, op, rep);
    }    

    return;
  }
  
  conversion_failed(expr, bv);
}
Exemple #28
0
void bv_refinementt::check_UNSAT(approximationt &a)
{
  // part of the conflict?
  if(!is_in_conflict(a)) return;

  status() << "Found assumption for `" << a.as_string()
           << "' in proof (state " << a.under_state << ")" << eom;

  assert(!a.under_assumptions.empty());

  a.under_assumptions.clear();

  if(a.expr.type().id()==ID_floatbv)
  {
    const floatbv_typet &floatbv_type=to_floatbv_type(a.expr.type());
    ieee_float_spect spec=floatbv_type;

    a.under_assumptions.reserve(a.op0_bv.size()+a.op1_bv.size());

    float_utilst float_utils(prop);
    float_utils.spec=spec;

    // the fraction without hidden bit
    const bvt fraction0=float_utils.get_fraction(a.op0_bv);
    const bvt fraction1=float_utils.get_fraction(a.op1_bv);
    
    if(a.under_state==0)
    {
      // we first set sign and exponent free,
      // but keep the fraction zero

      for(unsigned i=0; i<fraction0.size(); i++)
        a.add_under_assumption(prop.lnot(fraction0[i]));

      for(unsigned i=0; i<fraction1.size(); i++)
        a.add_under_assumption(prop.lnot(fraction1[i]));
    }
    else
    {
      // now fraction: make this grow quadratically
      unsigned x=a.under_state*a.under_state;
  
      if(x>=MAX_FLOAT_UNDERAPPROX && x>=a.result_bv.size())
      {
        // make it free altogether, this guarantees progress
      }
      else
      {
        // set x bits of both exponent and mantissa free
        // need to start with most-significant bits

        #if 0
        for(unsigned i=x; i<fraction0.size(); i++)
          a.add_under_assumption(prop.lnot(
            fraction0[fraction0.size()-i-1]));

        for(unsigned i=x; i<fraction1.size(); i++)
          a.add_under_assumption(prop.lnot(
            fraction1[fraction1.size()-i-1]));
        #endif
      }
    }
  }
  else
  {
    unsigned x=a.under_state+1;
  
    if(x>=MAX_INTEGER_UNDERAPPROX && x>=a.result_bv.size())
    {
      // make it free altogether, this guarantees progress
    }
    else
    {
      // set x least-significant bits free
      a.under_assumptions.reserve(a.op0_bv.size()+a.op1_bv.size());

      for(unsigned i=x; i<a.op0_bv.size(); i++)
        a.add_under_assumption(prop.lnot(a.op0_bv[i]));

      for(unsigned i=x; i<a.op1_bv.size(); i++)
        a.add_under_assumption(prop.lnot(a.op1_bv[i]));
    }
  }

  a.under_state++;
  progress=true;
}