Ejemplo n.º 1
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();
}
Ejemplo n.º 2
0
const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const
{
  // check cache first

  std::pair<cachet::iterator, bool> cache_result=
    cache.insert(std::pair<typet, entryt>(type, entryt()));
    
  entryt &entry=cache_result.first->second;

  if(!cache_result.second) // found!
    return entry;
    
  entry.total_width=0;
  
  const irep_idt type_id=type.id();

  if(type_id==ID_struct)
  {
    const struct_typet::componentst &components=
      to_struct_type(type).components();

    std::size_t offset=0;
    entry.members.resize(components.size());
  
    for(std::size_t i=0; i<entry.members.size(); i++)
    {
      std::size_t sub_width=operator()(components[i].type());
      entry.members[i].offset=offset;
      entry.members[i].width=sub_width;
      offset+=sub_width;
    }
    
    entry.total_width=offset;
  }
  else if(type_id==ID_union)
  {
    const union_typet::componentst &components=
      to_union_type(type).components();

    entry.members.resize(components.size());
    
    std::size_t max_width=0;
  
    for(std::size_t i=0; i<entry.members.size(); i++)
    {
      std::size_t sub_width=operator()(components[i].type());
      entry.members[i].width=sub_width;
      max_width=std::max(max_width, sub_width);
    }

    entry.total_width=max_width;
  }
  else if(type_id==ID_bool)
    entry.total_width=1;
  else if(type_id==ID_c_bool)
  {
    entry.total_width=to_c_bool_type(type).get_width();
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_signedbv)
  {
    entry.total_width=to_signedbv_type(type).get_width();
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_unsignedbv)
  {
    entry.total_width=to_unsignedbv_type(type).get_width();
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_floatbv)
  {
    entry.total_width=to_floatbv_type(type).get_width();
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_fixedbv)
  {
    entry.total_width=to_fixedbv_type(type).get_width();
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_bv)
  {
    entry.total_width=to_bv_type(type).get_width();
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_verilogbv)
  {
    // we encode with two bits
    entry.total_width=type.get_unsigned_int(ID_width)*2;
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_range)
  {
    mp_integer from=string2integer(type.get_string(ID_from)),
                 to=string2integer(type.get_string(ID_to));

    mp_integer size=to-from+1;

    if(size>=1)
    {
      entry.total_width=integer2unsigned(address_bits(size));
      assert(entry.total_width!=0);
    }
  }
  else if(type_id==ID_array)
  {
    const array_typet &array_type=to_array_type(type);
    std::size_t sub_width=operator()(array_type.subtype());

    mp_integer array_size;

    if(to_integer(array_type.size(), array_size))
    {
      // we can still use the theory of arrays for this
      entry.total_width=0;
    }
    else
    {
      mp_integer total=array_size*sub_width;
      if(total>(1<<30)) // realistic limit
        throw "array too large for flattening";

      entry.total_width=integer2unsigned(total);
    }
  }
  else if(type_id==ID_vector)
  {
    const vector_typet &vector_type=to_vector_type(type);
    std::size_t sub_width=operator()(vector_type.subtype());

    mp_integer vector_size;

    if(to_integer(vector_type.size(), vector_size))
    {
      // we can still use the theory of arrays for this
      entry.total_width=0;
    }
    else
    {
      mp_integer total=vector_size*sub_width;
      if(total>(1<<30)) // realistic limit
        throw "vector too large for flattening";

      entry.total_width=integer2unsigned(vector_size*sub_width);
    }
  }
  else if(type_id==ID_complex)
  {
    std::size_t sub_width=operator()(type.subtype());
    entry.total_width=integer2unsigned(2*sub_width);
  }
  else if(type_id==ID_code)
  {
  }
  else if(type_id==ID_enum)
  {
    // get number of necessary bits

    std::size_t size=type.find(ID_elements).get_sub().size();
    entry.total_width=integer2unsigned(address_bits(size));
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_c_enum)
  {
    // these have a subtype
    entry.total_width=type.subtype().get_unsigned_int(ID_width);
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_incomplete_c_enum)
  {
    // no width
  }
  else if(type_id==ID_pointer ||
          type_id==ID_reference)
  {
    entry.total_width=config.ansi_c.pointer_width;
  }
  else if(type_id==ID_symbol)
    entry=get_entry(ns.follow(type));
  else if(type_id==ID_struct_tag)
    entry=get_entry(ns.follow_tag(to_struct_tag_type(type)));
  else if(type_id==ID_union_tag)
    entry=get_entry(ns.follow_tag(to_union_tag_type(type)));
  else if(type_id==ID_c_enum_tag)
    entry=get_entry(ns.follow_tag(to_c_enum_tag_type(type)));
  else if(type_id==ID_c_bit_field)
  {
    entry.total_width=to_c_bit_field_type(type).get_width();
  }
  
  return entry;
}