コード例 #1
0
ファイル: cvc_prop.cpp プロジェクト: sarnold/cbmc
void cvc_propt::lcnf(const bvt &bv)
{
  if(bv.empty()) return;
  bvt new_bv;

  std::set<literalt> s;

  new_bv.reserve(bv.size());

  for(bvt::const_iterator it=bv.begin(); it!=bv.end(); it++)
  {
    if(s.insert(*it).second)
      new_bv.push_back(*it);

    if(s.find(lnot(*it))!=s.end())
      return; // clause satisfied

    assert(it->var_no()<_no_variables);
  }

  assert(!new_bv.empty());

  out << "%% lcnf" << std::endl;
  out << "ASSERT ";

  for(bvt::const_iterator it=new_bv.begin(); it!=new_bv.end(); it++)
  {
    if(it!=new_bv.begin()) out << " OR ";
    out << cvc_literal(*it);
  }

  out << ";" << std::endl << std::endl;
}
コード例 #2
0
void boolbv_mapt::get_literals(
  const irep_idt &identifier,
  const typet &type,
  const unsigned width,
  bvt &literals)
{
  map_entryt &map_entry=get_map_entry(identifier, type);

  assert(literals.size()==width);
  Forall_literals(it, literals)
  {
    literalt &l=*it;
    const unsigned bit=it-literals.begin();

    assert(bit<map_entry.literal_map.size());
    map_bitt &mb=map_entry.literal_map[bit];

    if(mb.is_set)
    {
      l=mb.l;
      continue;
    }

    l=prop.new_variable();

    mb.is_set=true;
    mb.l=l;

    #ifdef DEBUG
    std::cout << "NEW: " << identifier << ":" << bit
              << "=" << l << std::endl;
    #endif
  }
コード例 #3
0
ファイル: dplib_prop.cpp プロジェクト: danpoe/cbmc
void dplib_propt::lcnf(const bvt &bv)
{
  if(bv.empty())
    return;
  bvt new_bv;

  std::set<literalt> s;

  new_bv.reserve(bv.size());

  for(bvt::const_iterator it=bv.begin(); it!=bv.end(); it++)
  {
    if(s.insert(*it).second)
      new_bv.push_back(*it);

    if(s.find(!*it)!=s.end())
      return; // clause satisfied

    assert(it->var_no()<=_no_variables);
  }

  assert(!new_bv.empty());

  out << "// lcnf\n";
  out << "AXIOM ";

  for(bvt::const_iterator it=new_bv.begin(); it!=new_bv.end(); it++)
  {
    if(it!=new_bv.begin())
      out << " | ";
    out << dplib_literal(*it);
  }

  out << ";\n\n";
}
コード例 #4
0
ファイル: z3_prop.cpp プロジェクト: smaorus/rvt
void z3_propt::eliminate_duplicates(const bvt &bv, bvt &dest)
{
  std::set<literalt> s;

  dest.reserve(bv.size());

  for(bvt::const_iterator it=bv.begin(); it!=bv.end(); it++)
  {
    if(s.insert(*it).second)
      dest.push_back(*it);
  }
}
コード例 #5
0
ファイル: cvc_prop.cpp プロジェクト: sarnold/cbmc
literalt cvc_propt::lor(const bvt &bv)
{
  out << "%% lor" << std::endl;

  literalt literal=def_cvc_literal();

  forall_literals(it, bv)
  {
    if(it!=bv.begin()) out << " OR ";
    out << cvc_literal(*it);
  }
  
  out << ";" << std::endl << std::endl;

  return literal;  
}
コード例 #6
0
ファイル: dplib_prop.cpp プロジェクト: danpoe/cbmc
literalt dplib_propt::lor(const bvt &bv)
{
  out << "// lor\n";

  literalt literal=def_dplib_literal();

  forall_literals(it, bv)
  {
    if(it!=bv.begin())
      out << " | ";
    out << dplib_literal(*it);
  }

  out << "\n\n";

  return literal;
}
コード例 #7
0
ファイル: z3_prop.cpp プロジェクト: smaorus/rvt
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;
}
コード例 #8
0
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;
}
コード例 #9
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);
}
コード例 #10
0
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;
}
コード例 #11
0
ファイル: boolbv_floatbv_op.cpp プロジェクト: Dthird/CBMC
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);
}