CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
boolbv_typecast.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
10#include <util/c_types.h>
11#include <util/namespace.h>
12
14
15#include "boolbv.h"
16#include "boolbv_type.h"
18
20{
21 const exprt &op = expr.op();
22 const bvt &op_bv = convert_bv(op);
23
24 bvt bv;
25
26 if(type_conversion(op.type(), op_bv, expr.type(), bv))
27 return conversion_failed(expr);
28
29 return bv;
30}
31
33 const typet &src_type,
34 const bvt &src,
35 const typet &dest_type,
36 bvt &dest)
37{
40
42 return type_conversion(
44 src,
46 dest);
47
49 return type_conversion(
51 src,
53 dest);
54
55 std::size_t src_width = src.size();
56 std::size_t dest_width = boolbv_width(dest_type);
57
58 if(dest_width == 0 || src_width == 0)
59 return true;
60
61 dest.clear();
62 dest.reserve(dest_width);
63
64 if(dest_type.id() == ID_complex)
65 {
66 if(src_type == to_complex_type(dest_type).subtype())
67 {
68 dest.insert(dest.end(), src.begin(), src.end());
69
70 // pad with zeros
71 for(std::size_t i = src.size(); i < dest_width; i++)
72 dest.push_back(const_literal(false));
73
74 return false;
75 }
76 else if(src_type.id() == ID_complex)
77 {
78 // recursively do both halfs
79 bvt lower, upper, lower_res, upper_res;
80 lower.assign(src.begin(), src.begin() + src.size() / 2);
81 upper.assign(src.begin() + src.size() / 2, src.end());
83 to_complex_type(src_type).subtype(),
84 lower,
85 to_complex_type(dest_type).subtype(),
86 lower_res);
88 to_complex_type(src_type).subtype(),
89 upper,
90 to_complex_type(dest_type).subtype(),
91 upper_res);
93 lower_res.size() + upper_res.size() == dest_width,
94 "lower result bitvector size plus upper result bitvector size shall "
95 "equal the destination bitvector size");
96 dest = lower_res;
97 dest.insert(dest.end(), upper_res.begin(), upper_res.end());
98 return false;
99 }
100 }
101
102 if(src_type.id() == ID_complex)
103 {
104 INVARIANT(
105 dest_type.id() == ID_complex,
106 "destination type shall be of complex type when source type is of "
107 "complex type");
108 if(
109 dest_type.id() == ID_signedbv || dest_type.id() == ID_unsignedbv ||
110 dest_type.id() == ID_floatbv || dest_type.id() == ID_fixedbv ||
111 dest_type.id() == ID_c_enum || dest_type.id() == ID_c_enum_tag ||
112 dest_type.id() == ID_bool)
113 {
114 // A cast from complex x to real T
115 // is (T) __real__ x.
116 bvt tmp_src(src);
117 tmp_src.resize(src.size() / 2); // cut off imag part
118 return type_conversion(
119 to_complex_type(src_type).subtype(), tmp_src, dest_type, dest);
120 }
121 }
122
123 switch(dest_bvtype)
124 {
126 if(
129 {
131
132 if(dest_from == 0)
133 {
134 // do zero extension
135 dest.resize(dest_width);
136 for(std::size_t i = 0; i < dest.size(); i++)
137 dest[i] = (i < src.size() ? src[i] : const_literal(false));
138
139 return false;
140 }
141 }
142 else if(src_bvtype == bvtypet::IS_RANGE) // range to range
143 {
146
147 if(dest_from == src_from)
148 {
149 // do zero extension, if needed
151 return false;
152 }
153 else
154 {
155 // need to do arithmetic: add src_from-dest_from
156 mp_integer offset = src_from - dest_from;
157 dest = bv_utils.add(
160 }
161
162 return false;
163 }
164 break;
165
166 case bvtypet::IS_FLOAT: // to float
167 {
169
170 switch(src_bvtype)
171 {
172 case bvtypet::IS_FLOAT: // float to float
173 // we don't have a rounding mode here,
174 // which is why we refuse.
175 break;
176
177 case bvtypet::IS_SIGNED: // signed to float
180 dest = float_utils.from_signed_integer(src);
181 return false;
182
183 case bvtypet::IS_UNSIGNED: // unsigned to float
184 case bvtypet::IS_C_BOOL: // _Bool to float
186 dest = float_utils.from_unsigned_integer(src);
187 return false;
188
189 case bvtypet::IS_BV:
190 INVARIANT(src_width >= dest_width, "cannot extend bv-typed bitvector");
191 dest = src;
193 dest.resize(dest_width);
194 return false;
195
202 if(src_type.id() == ID_bool)
203 {
204 // bool to float
205
206 // build a one
208 dest = convert_bv(one.to_expr());
209
210 INVARIANT(
211 src_width == 1, "bitvector of type boolean shall have width one");
212
213 for(auto &literal : dest)
214 literal = prop.land(literal, src[0]);
215
216 return false;
217 }
218 }
219 }
220 break;
221
224 {
225 // fixed to fixed
226
227 std::size_t dest_fraction_bits =
228 to_fixedbv_type(dest_type).get_fraction_bits();
230 std::size_t op_fraction_bits =
231 to_fixedbv_type(src_type).get_fraction_bits();
232 std::size_t op_int_bits = src_width - op_fraction_bits;
233
234 dest.resize(dest_width);
235
236 // i == position after dot
237 // i == 0: first position after dot
238
239 for(std::size_t i = 0; i < dest_fraction_bits; i++)
240 {
241 // position in bv
242 std::size_t p = dest_fraction_bits - i - 1;
243
244 if(i < op_fraction_bits)
245 dest[p] = src[op_fraction_bits - i - 1];
246 else
247 dest[p] = const_literal(false); // zero padding
248 }
249
250 for(std::size_t i = 0; i < dest_int_bits; i++)
251 {
252 // position in bv
253 std::size_t p = dest_fraction_bits + i;
254 INVARIANT(p < dest_width, "bit index shall be within bounds");
255
256 if(i < op_int_bits)
257 dest[p] = src[i + op_fraction_bits];
258 else
259 dest[p] = src[src_width - 1]; // sign extension
260 }
261
262 return false;
263 }
264 else if(src_bvtype == bvtypet::IS_BV)
265 {
266 INVARIANT(src_width >= dest_width, "cannot extend bv-typed bitvector");
267 dest = src;
269 dest.resize(dest_width);
270 return false;
271 }
272 else if(
275 {
276 // integer to fixed
277
278 std::size_t dest_fraction_bits =
279 to_fixedbv_type(dest_type).get_fraction_bits();
280
281 for(std::size_t i = 0; i < dest_fraction_bits; i++)
282 dest.push_back(const_literal(false)); // zero padding
283
284 for(std::size_t i = 0; i < dest_width - dest_fraction_bits; i++)
285 {
286 literalt l;
287
288 if(i < src_width)
289 l = src[i];
290 else
291 {
292 if(
295 l = src[src_width - 1]; // sign extension
296 else
297 l = const_literal(false); // zero extension
298 }
299
300 dest.push_back(l);
301 }
302
303 return false;
304 }
305 else if(src_type.id() == ID_bool)
306 {
307 // bool to fixed
308 std::size_t fraction_bits =
309 to_fixedbv_type(dest_type).get_fraction_bits();
310
311 INVARIANT(
312 src_width == 1, "bitvector of type boolean shall have width one");
313
314 for(std::size_t i = 0; i < dest_width; i++)
315 {
316 if(i == fraction_bits)
317 dest.push_back(src[0]);
318 else
319 dest.push_back(const_literal(false));
320 }
321
322 return false;
323 }
324 break;
325
329 {
330 switch(src_bvtype)
331 {
332 case bvtypet::IS_FLOAT: // float to integer
333 // we don't have a rounding mode here,
334 // which is why we refuse.
335 break;
336
337 case bvtypet::IS_FIXED: // fixed to integer
338 {
339 std::size_t op_fraction_bits =
340 to_fixedbv_type(src_type).get_fraction_bits();
341
342 for(std::size_t i = 0; i < dest_width; i++)
343 {
345 dest.push_back(src[i + op_fraction_bits]);
346 else
347 {
349 dest.push_back(src[src_width - 1]); // sign extension
350 else
351 dest.push_back(const_literal(false)); // zero extension
352 }
353 }
354
355 // we might need to round up in case of negative numbers
356 // e.g., (int)(-1.00001)==1
357
358 bvt fraction_bits_bv = src;
361
362 dest = bv_utils.incrementer(dest, round_up);
363
364 return false;
365 }
366
367 case bvtypet::IS_UNSIGNED: // integer to integer
371 {
372 // We do sign extension for any source type
373 // that is signed, independently of the
374 // destination type.
375 // E.g., ((short)(ulong)(short)-1)==-1
376 bool sign_extension =
378
379 for(std::size_t i = 0; i < dest_width; i++)
380 {
381 if(i < src_width)
382 dest.push_back(src[i]);
383 else if(sign_extension)
384 dest.push_back(src[src_width - 1]); // sign extension
385 else
386 dest.push_back(const_literal(false));
387 }
388
389 return false;
390 }
391 // verilog_unsignedbv to signed/unsigned/enum
393 {
394 for(std::size_t i = 0; i < dest_width; i++)
395 {
396 std::size_t src_index = i * 2; // we take every second bit
397
398 if(src_index < src_width)
399 dest.push_back(src[src_index]);
400 else // always zero-extend
401 dest.push_back(const_literal(false));
402 }
403
404 return false;
405 }
406 break;
407
408 case bvtypet::IS_VERILOG_SIGNED: // verilog_signedbv to signed/unsigned/enum
409 {
410 for(std::size_t i = 0; i < dest_width; i++)
411 {
412 std::size_t src_index = i * 2; // we take every second bit
413
414 if(src_index < src_width)
415 dest.push_back(src[src_index]);
416 else // always sign-extend
417 dest.push_back(src.back());
418 }
419
420 return false;
421 }
422 break;
423
424 case bvtypet::IS_BV:
425 INVARIANT(src_width >= dest_width, "cannot extend bv-typed bitvector");
426 dest = src;
428 dest.resize(dest_width);
429 return false;
430
434 if(src_type.id() == ID_bool)
435 {
436 // bool to integer
437
438 INVARIANT(
439 src_width == 1, "bitvector of type boolean shall have width one");
440
441 for(std::size_t i = 0; i < dest_width; i++)
442 {
443 if(i == 0)
444 dest.push_back(src[0]);
445 else
446 dest.push_back(const_literal(false));
447 }
448
449 return false;
450 }
451 }
452 break;
453 }
454
456 if(
458 src_type.id() == ID_bool)
459 {
460 for(std::size_t i = 0, j = 0; i < dest_width; i += 2, j++)
461 {
462 if(j < src_width)
463 dest.push_back(src[j]);
464 else
465 dest.push_back(const_literal(false));
466
467 dest.push_back(const_literal(false));
468 }
469
470 return false;
471 }
473 {
474 for(std::size_t i = 0, j = 0; i < dest_width; i += 2, j++)
475 {
476 if(j < src_width)
477 dest.push_back(src[j]);
478 else
479 dest.push_back(src.back());
480
481 dest.push_back(const_literal(false));
482 }
483
484 return false;
485 }
487 {
488 // verilog_unsignedbv to verilog_unsignedbv
489 dest = src;
490
492 dest.resize(dest_width);
493 else
494 {
495 dest = src;
496 while(dest.size() < dest_width)
497 {
498 dest.push_back(const_literal(false));
499 dest.push_back(const_literal(false));
500 }
501 }
502 return false;
503 }
504 break;
505
506 case bvtypet::IS_BV:
507 INVARIANT(src_width >= dest_width, "cannot extend bv-typed bitvector");
508 dest = src;
510 dest.resize(dest_width);
511 return false;
512
514 dest.resize(dest_width, const_literal(false));
515
517 {
519 dest[0] = !float_utils.is_zero(src);
520 }
522 dest[0] = src[0];
523 else
524 dest[0] = !bv_utils.is_zero(src);
525
526 return false;
527
531 if(dest_type.id() == ID_array)
532 {
533 if(src_width == dest_width)
534 {
535 dest = src;
536 return false;
537 }
538 }
539 else if(dest_type.id() == ID_struct || dest_type.id() == ID_struct_tag)
540 {
543 ? ns.follow_tag(to_struct_tag_type(dest_type))
545
546 if(src_type.id() == ID_struct || src_type.id() == ID_struct_tag)
547 {
548 // we do subsets
549
550 dest.resize(dest_width, const_literal(false));
551
552 const struct_typet &op_struct =
553 src_type.id() == ID_struct_tag
554 ? ns.follow_tag(to_struct_tag_type(src_type))
556
557 const struct_typet::componentst &dest_comp = dest_struct.components();
558
559 const struct_typet::componentst &op_comp = op_struct.components();
560
561 // build offset maps
564
565 // build name map
566 typedef std::map<irep_idt, std::size_t> op_mapt;
568
569 for(std::size_t i = 0; i < op_comp.size(); i++)
570 op_map[op_comp[i].get_name()] = i;
571
572 // now gather required fields
573 for(std::size_t i = 0; i < dest_comp.size(); i++)
574 {
575 std::size_t offset = dest_offsets[i];
576 std::size_t comp_width = boolbv_width(dest_comp[i].type());
577 if(comp_width == 0)
578 continue;
579
580 op_mapt::const_iterator it = op_map.find(dest_comp[i].get_name());
581
582 if(it == op_map.end())
583 {
584 // not found
585
586 // filling with free variables
587 for(std::size_t j = 0; j < comp_width; j++)
588 dest[offset + j] = prop.new_variable();
589 }
590 else
591 {
592 // found
593 if(dest_comp[i].type() != dest_comp[it->second].type())
594 {
595 // filling with free variables
596 for(std::size_t j = 0; j < comp_width; j++)
597 dest[offset + j] = prop.new_variable();
598 }
599 else
600 {
601 std::size_t op_offset = op_offsets[it->second];
602 for(std::size_t j = 0; j < comp_width; j++)
603 dest[offset + j] = src[op_offset + j];
604 }
605 }
606 }
607
608 return false;
609 }
610 }
611 }
612
613 return true;
614}
615
618{
619 if(expr.op().type().id() == ID_range)
620 {
621 mp_integer from = string2integer(expr.op().type().get_string(ID_from));
622 mp_integer to = string2integer(expr.op().type().get_string(ID_to));
623
624 if(from == 1 && to == 1)
625 return const_literal(true);
626 else if(from == 0 && to == 0)
627 return const_literal(false);
628 }
629
630 const bvt &bv = convert_bv(expr.op());
631
632 if(!bv.empty())
633 return prop.lor(bv);
634
635 return SUB::convert_rest(expr);
636}
Pre-defined bitvector types.
const fixedbv_typet & to_fixedbv_type(const typet &type)
Cast a typet to a fixedbv_typet.
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
bvtypet get_bvtype(const typet &type)
bvtypet
Definition boolbv_type.h:17
@ IS_VERILOG_UNSIGNED
@ IS_VERILOG_SIGNED
@ IS_C_BIT_FIELD
typet c_bit_field_replacement_type(const c_bit_field_typet &src, const namespacet &ns)
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
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
const namespacet & ns
Definition arrays.h:56
virtual const bvt & convert_bv(const exprt &expr, const std::optional< std::size_t > expected_width={})
Convert expression to vector of literalts, using an internal cache to speed up conversion if availabl...
Definition boolbv.cpp:39
offset_mapt build_offset_map(const struct_typet &src)
Definition boolbv.cpp:586
virtual literalt convert_typecast(const typecast_exprt &expr)
conversion from bitvector types to boolean
bv_utilst bv_utils
Definition boolbv.h:118
bvt conversion_failed(const exprt &expr)
Print that the expression of x has failed conversion, then return a vector of x's width.
Definition boolbv.cpp:94
virtual std::size_t boolbv_width(const typet &type) const
Definition boolbv.h:103
virtual bvt convert_bv_typecast(const typecast_exprt &expr)
bool type_conversion(const typet &src_type, const bvt &src, const typet &dest_type, bvt &dest)
std::vector< std::size_t > offset_mapt
Definition boolbv.h:279
bvt add(const bvt &op0, const bvt &op1)
Definition bv_utils.h:66
static bvt zero_extension(const bvt &bv, std::size_t new_size)
Definition bv_utils.h:187
static bvt build_constant(const mp_integer &i, std::size_t width)
Definition bv_utils.cpp:14
literalt is_zero(const bvt &op)
Definition bv_utils.h:143
bvt incrementer(const bvt &op, literalt carry_in)
Definition bv_utils.cpp:629
Base class for all expressions.
Definition expr.h:56
typet & type()
Return the type of the expression.
Definition expr.h:84
static ieee_float_valuet one(const floatbv_typet &)
virtual literalt convert_rest(const exprt &expr)
virtual literalt land(literalt a, literalt b)=0
virtual literalt new_variable()=0
virtual literalt lor(literalt a, literalt b)=0
Structure type, corresponds to C style structs.
Definition std_types.h:231
std::vector< componentt > componentst
Definition std_types.h:140
Semantic type conversion.
Definition std_expr.h:2073
The type of an expression, extends irept.
Definition type.h:29
const exprt & op() const
Definition std_expr.h:391
std::vector< literalt > bvt
Definition literal.h:201
literalt const_literal(bool value)
Definition literal.h:188
const mp_integer string2integer(const std::string &n, unsigned base)
Definition mp_arith.cpp:54
BigInt mp_integer
Definition smt_terms.h:17
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
const range_typet & to_range_type(const typet &type)
Cast a typet to a range_typet.
Definition std_types.h:1040
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:308
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 complex_typet & to_complex_type(const typet &type)
Cast a typet to a complex_typet.
Definition std_types.h:1158