CBMC
boolbv_width.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
9 #include "boolbv_width.h"
10 
11 #include <algorithm>
12 
13 #include <util/arith_tools.h>
14 #include <util/c_types.h>
15 #include <util/invariant.h>
16 #include <util/namespace.h>
17 #include <util/std_types.h>
18 
20 {
21 }
22 
24 {
25  // check cache first
26 
27  std::pair<cachet::iterator, bool> cache_result =
28  cache.emplace(type, entryt{});
29 
30  auto &cache_entry = cache_result.first->second;
31 
32  if(!cache_result.second) // found!
33  return cache_entry;
34 
35  const irep_idt type_id=type.id();
36 
37  if(type_id==ID_struct)
38  {
39  const struct_typet::componentst &components=
40  to_struct_type(type).components();
41 
42  std::size_t offset=0;
43  defined_entryt entry{0};
44  entry.members.resize(components.size());
45 
46  for(std::size_t i=0; i<entry.members.size(); i++)
47  {
48  auto sub_width = get_width_opt(components[i].type());
49  if(!sub_width.has_value())
50  return cache_entry;
51  entry.members[i].offset=offset;
52  entry.members[i].width = *sub_width;
53  offset += *sub_width;
54  }
55 
56  entry.total_width=offset;
57 
58  cache_entry = std::move(entry);
59  }
60  else if(type_id==ID_union)
61  {
62  const union_typet::componentst &components=
63  to_union_type(type).components();
64 
65  defined_entryt entry{0};
66  entry.members.resize(components.size());
67 
68  std::size_t max_width=0;
69 
70  for(std::size_t i=0; i<entry.members.size(); i++)
71  {
72  auto sub_width = get_width_opt(components[i].type());
73  if(!sub_width.has_value())
74  return cache_entry;
75  entry.members[i].width = *sub_width;
76  max_width = std::max(max_width, *sub_width);
77  }
78 
79  entry.total_width=max_width;
80 
81  cache_entry = std::move(entry);
82  }
83  else if(type_id==ID_bool)
84  {
85  cache_entry = defined_entryt{1};
86  }
87  else if(type_id==ID_c_bool)
88  {
89  cache_entry = defined_entryt{to_c_bool_type(type).get_width()};
90  }
91  else if(type_id==ID_signedbv)
92  {
93  cache_entry = defined_entryt{to_signedbv_type(type).get_width()};
94  }
95  else if(type_id==ID_unsignedbv)
96  {
97  cache_entry = defined_entryt{to_unsignedbv_type(type).get_width()};
98  }
99  else if(type_id==ID_floatbv)
100  {
101  cache_entry = defined_entryt{to_floatbv_type(type).get_width()};
102  }
103  else if(type_id==ID_fixedbv)
104  {
105  cache_entry = defined_entryt{to_fixedbv_type(type).get_width()};
106  }
107  else if(type_id==ID_bv)
108  {
109  cache_entry = defined_entryt{to_bv_type(type).get_width()};
110  }
111  else if(type_id==ID_verilog_signedbv ||
112  type_id==ID_verilog_unsignedbv)
113  {
114  // we encode with two bits
115  std::size_t size = to_bitvector_type(type).get_width();
117  size > 0, "verilog bitvector width shall be greater than zero");
118  cache_entry = defined_entryt{size * 2};
119  }
120  else if(type_id==ID_range)
121  {
122  mp_integer from=string2integer(type.get_string(ID_from)),
123  to=string2integer(type.get_string(ID_to));
124 
125  mp_integer size=to-from+1;
126 
127  if(size < 0)
128  return cache_entry;
129  else if(size == 0)
130  cache_entry = defined_entryt{0};
131  else
132  cache_entry = defined_entryt{address_bits(size)};
133  }
134  else if(type_id==ID_array)
135  {
136  const array_typet &array_type=to_array_type(type);
137  auto sub_width = get_width_opt(array_type.element_type());
138  if(!sub_width.has_value())
139  return cache_entry;
140 
141  const auto array_size = numeric_cast<mp_integer>(array_type.size());
142 
143  if(!array_size.has_value() || *array_size < 0)
144  return cache_entry;
145 
146  mp_integer total = *array_size * *sub_width;
147  if(total > (1 << 30)) // realistic limit
148  throw analysis_exceptiont("array too large for flattening");
149  else
150  cache_entry = defined_entryt{numeric_cast_v<std::size_t>(total)};
151  }
152  else if(type_id==ID_complex)
153  {
154  auto sub_width = get_width_opt(to_complex_type(type).subtype());
155  if(!sub_width.has_value())
156  return cache_entry;
157  cache_entry =
158  defined_entryt{numeric_cast_v<std::size_t>(2 * mp_integer{*sub_width})};
159  }
160  else if(type_id==ID_code)
161  {
162  cache_entry = defined_entryt{0};
163  }
164  else if(type_id==ID_enumeration)
165  {
166  // get number of necessary bits
167  std::size_t size=to_enumeration_type(type).elements().size();
168  if(size == 0)
169  cache_entry = defined_entryt{0};
170  else
171  cache_entry = defined_entryt{address_bits(size)};
172  }
173  else if(type_id==ID_c_enum)
174  {
175  // these have a subtype
176  cache_entry = defined_entryt{
177  to_bitvector_type(to_c_enum_type(type).underlying_type()).get_width()};
178  CHECK_RETURN(cache_entry->total_width > 0);
179  }
180  else if(type_id==ID_pointer)
181  {
182  cache_entry =
183  defined_entryt{type_checked_cast<pointer_typet>(type).get_width()};
184  }
185  else if(type_id==ID_struct_tag)
186  {
187  cache_entry = get_entry(ns.follow_tag(to_struct_tag_type(type)));
188  }
189  else if(type_id==ID_union_tag)
190  {
191  cache_entry = get_entry(ns.follow_tag(to_union_tag_type(type)));
192  }
193  else if(type_id==ID_c_enum_tag)
194  {
195  cache_entry = get_entry(ns.follow_tag(to_c_enum_tag_type(type)));
196  }
197  else if(type_id==ID_c_bit_field)
198  {
199  cache_entry = defined_entryt{to_c_bit_field_type(type).get_width()};
200  }
201  else if(type_id==ID_string)
202  {
203  cache_entry = defined_entryt{32};
204  }
205  else if(type_id == ID_empty)
206  {
207  cache_entry = defined_entryt{0};
208  }
209  else
210  {
212  "boolbv_widtht::get_entry(" + id2string(type_id) + ")");
213  }
214 
215  return cache_entry;
216 }
217 
219  const struct_typet &type,
220  const irep_idt &member) const
221 {
222  const auto &entry_opt = get_entry(type);
223  CHECK_RETURN(entry_opt.has_value());
224  std::size_t component_number=type.component_number(member);
225  PRECONDITION(entry_opt->members.size() > component_number);
226 
227  return entry_opt->members[component_number];
228 }
std::size_t address_bits(const mp_integer &size)
ceil(log2(size))
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
const fixedbv_typet & to_fixedbv_type(const typet &type)
Cast a typet to a fixedbv_typet.
const unsignedbv_typet & to_unsignedbv_type(const typet &type)
Cast a typet to an unsignedbv_typet.
const bv_typet & to_bv_type(const typet &type)
Cast a typet to a bv_typet.
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition: c_types.h:335
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition: c_types.h:224
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
Definition: c_types.h:80
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition: c_types.h:184
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
Definition: c_types.h:377
const c_bool_typet & to_c_bool_type(const typet &type)
Cast a typet to a c_bool_typet.
Definition: c_types.h:128
Thrown when an unexpected error occurs during the analysis (e.g., when the SAT solver returns an erro...
Arrays with given size.
Definition: std_types.h:807
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:827
const exprt & size() const
Definition: std_types.h:840
std::size_t get_width() const
Definition: std_types.h:920
virtual std::optional< std::size_t > get_width_opt(const typet &type) const
Definition: boolbv_width.h:31
boolbv_widtht(const namespacet &_ns)
const namespacet & ns
Definition: boolbv_width.h:48
const entryt & get_entry(const typet &type) const
std::optional< defined_entryt > entryt
Definition: boolbv_width.h:59
const membert & get_member(const struct_typet &type, const irep_idt &member) const
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
const irept::subt & elements() const
Definition: std_types.h:540
const irep_idt & id() const
Definition: irep.h:384
const std::string & get_string(const irep_idt &name) const
Definition: irep.h:397
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
Structure type, corresponds to C style structs.
Definition: std_types.h:231
const componentst & components() const
Definition: std_types.h:147
std::size_t component_number(const irep_idt &component_name) const
Return the sequence number of the component with given name.
Definition: std_types.cpp:46
std::vector< componentt > componentst
Definition: std_types.h:140
The type of an expression, extends irept.
Definition: type.h:29
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
const mp_integer string2integer(const std::string &n, unsigned base)
Definition: mp_arith.cpp:54
BigInt mp_integer
Definition: smt_terms.h:17
#define UNIMPLEMENTED_FEATURE(FEATURE)
Definition: invariant.h:549
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:534
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
Pre-defined types.
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:888
const complex_typet & to_complex_type(const typet &type)
Cast a typet to a complex_typet.
Definition: std_types.h:1146
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:518
const enumeration_typet & to_enumeration_type(const typet &type)
Cast a typet to a enumeration_typet.
Definition: std_types.h:568
std::vector< membert > members
Definition: boolbv_width.h:57