cprover
Loading...
Searching...
No Matches
convert_expr_to_smt.cpp
Go to the documentation of this file.
1// Author: Diffblue Ltd.
2#include <util/arith_tools.h>
5#include <util/c_types.h>
6#include <util/config.h>
7#include <util/expr.h>
8#include <util/expr_cast.h>
9#include <util/floatbv_expr.h>
11#include <util/pointer_expr.h>
13#include <util/range.h>
14#include <util/std_expr.h>
16
22
23#include <algorithm>
24#include <functional>
25#include <numeric>
26#include <stack>
27
37using sub_expression_mapt = std::unordered_map<exprt, smt_termt, irep_hash>;
38
51template <typename factoryt>
53 const multi_ary_exprt &expr,
54 const sub_expression_mapt &converted,
55 const factoryt &factory)
56{
57 PRECONDITION(expr.operands().size() >= 2);
58 const auto operand_terms =
59 make_range(expr.operands()).map([&](const exprt &expr) {
60 return converted.at(expr);
61 });
62 return std::accumulate(
63 ++operand_terms.begin(),
64 operand_terms.end(),
65 *operand_terms.begin(),
66 factory);
67}
68
73template <typename target_typet>
74static bool operands_are_of_type(const exprt &expr)
75{
76 return std::all_of(
77 expr.operands().cbegin(), expr.operands().cend(), [](const exprt &operand) {
78 return can_cast_type<target_typet>(operand.type());
79 });
80}
81
83{
84 return smt_bool_sortt{};
85}
86
91
98
100{
101 // Convert floating-point to bitvector for bit-blasting
102 return smt_bit_vector_sortt{type.get_width()};
103}
104
106{
107 if(const auto bool_type = type_try_dynamic_cast<bool_typet>(type))
108 {
109 return convert_type_to_smt_sort(*bool_type);
110 }
111 if(const auto bitvector_type = type_try_dynamic_cast<bitvector_typet>(type))
112 {
113 if(const auto floatbv_type = type_try_dynamic_cast<floatbv_typet>(type))
114 {
115 return convert_type_to_smt_sort(*floatbv_type);
116 }
117 return convert_type_to_smt_sort(*bitvector_type);
118 }
119 if(const auto array_type = type_try_dynamic_cast<array_typet>(type))
120 {
121 return convert_type_to_smt_sort(*array_type);
122 }
123 // Note: the SMT-LIB theory-of-strings types (String/RegLan) and the
124 // cprover_string_*/cprover_regex_* built-ins are intentionally not supported
125 // by this incremental back-end; they are lowered only by the non-incremental
126 // smt2_convt (see src/solvers/smt2/smt2_conv.cpp). Such inputs reach the
127 // UNIMPLEMENTED_FEATURE below.
128 UNIMPLEMENTED_FEATURE("Generation of SMT formula for type: " + type.pretty());
129}
130
132{
134 symbol_expr.identifier(), convert_type_to_smt_sort(symbol_expr.type())};
135}
136
138 const nondet_symbol_exprt &nondet_symbol,
139 const sub_expression_mapt &converted)
140{
141 // A nondet_symbol is a reference to an unconstrained function. This function
142 // will already have been added as a dependency.
144 nondet_symbol.get_identifier(),
145 convert_type_to_smt_sort(nondet_symbol.type())};
146}
147
149static smt_termt make_not_zero(const smt_termt &input, const typet &source_type)
150{
151 if(input.get_sort().cast<smt_bool_sortt>())
152 return input;
153 if(const auto bit_vector_sort = input.get_sort().cast<smt_bit_vector_sortt>())
154 {
156 input, smt_bit_vector_constant_termt{0, *bit_vector_sort});
157 }
159}
160
163 const smt_termt &from_term,
164 const typet &from_type,
165 const bitvector_typet &to_type)
166{
167 const std::size_t c_bool_width = to_type.get_width();
169 make_not_zero(from_term, from_type),
170 smt_bit_vector_constant_termt{1, c_bool_width},
171 smt_bit_vector_constant_termt{0, c_bool_width});
172}
173
174static std::function<std::function<smt_termt(smt_termt)>(std::size_t)>
187
189 const smt_termt &from_term,
191 const bitvector_typet &to_type)
192{
194 {
196 "Generation of SMT formula for type cast to fixed-point bitvector "
197 "type: " +
198 to_type.pretty());
199 }
200 // After float lowering, floatbv types are treated as bitvectors.
201 // Same-width casts (e.g., from float_bvt::pack) are handled below.
202 const std::size_t from_width = from_type.get_width();
203 const std::size_t to_width = to_type.get_width();
204 if(to_width == from_width)
205 return from_term;
206 if(to_width < from_width)
207 return smt_bit_vector_theoryt::extract(to_width - 1, 0)(from_term);
208 const std::size_t extension_size = to_width - from_width;
209 return extension_for_type(from_type)(extension_size)(from_term);
210}
211
214{
218 std::optional<smt_termt> result;
219
227
228 void visit(const smt_bool_sortt &) override
229 {
231 from_term, from_type, c_bool_typet{to_type.get_width()});
232 }
233
234 void visit(const smt_bit_vector_sortt &) override
235 {
236 if(const auto bitvector = type_try_dynamic_cast<bitvector_typet>(from_type))
238 else
240 "Generation of SMT formula for type cast to bit vector from type: " +
241 from_type.pretty());
242 }
243
244 void visit(const smt_array_sortt &) override
245 {
247 "Generation of SMT formula for type cast to bit vector from type: " +
248 from_type.pretty());
249 }
250};
251
253 const smt_termt &from_term,
254 const typet &from_type,
255 const bitvector_typet &to_type)
256{
258 from_term, from_type, to_type};
259 from_term.get_sort().accept(converter);
260 POSTCONDITION(converter.result);
261 return *converter.result;
262}
263
265 const typecast_exprt &cast,
266 const sub_expression_mapt &converted)
267{
268 const auto &from_term = converted.at(cast.op());
269 const typet &from_type = cast.op().type();
270 const typet &to_type = cast.type();
272 return make_not_zero(from_term, cast.op().type());
273 if(const auto c_bool_type = type_try_dynamic_cast<c_bool_typet>(to_type))
274 return convert_c_bool_cast(from_term, from_type, *c_bool_type);
275 if(const auto bit_vector = type_try_dynamic_cast<bitvector_typet>(to_type))
276 return convert_bit_vector_cast(from_term, from_type, *bit_vector);
278 "Generation of SMT formula for type cast expression: " + cast.pretty());
279}
280
282 const floatbv_typecast_exprt &float_cast,
283 const sub_expression_mapt &converted)
284{
285 // Floating-point operations should be lowered to bitvector operations
286 // before reaching this point. If we get here, it means the lowering failed.
288 "Floating point type cast expression should have been lowered to "
289 "bitvector operations: " +
290 float_cast.pretty());
291}
292
294 const struct_exprt &struct_construction,
295 const sub_expression_mapt &converted)
296{
298 "Generation of SMT formula for struct construction expression: " +
299 struct_construction.pretty());
300}
301
303 const union_exprt &union_construction,
304 const sub_expression_mapt &converted)
305{
307 "Generation of SMT formula for union construction expression: " +
308 union_construction.pretty());
309}
310
312{
314 std::optional<smt_termt> result;
315
317 : member_input{input}
318 {
319 }
320
321 void visit(const smt_bool_sortt &) override
322 {
324 }
325
326 void visit(const smt_bit_vector_sortt &bit_vector_sort) override
327 {
328 const auto &width = bit_vector_sort.bit_width();
329 // We get the value using a non-signed interpretation, as smt bit vector
330 // terms do not carry signedness.
331 const auto value = bvrep2integer(member_input.get_value(), width, false);
332 result = smt_bit_vector_constant_termt{value, bit_vector_sort};
333 }
334
335 void visit(const smt_array_sortt &array_sort) override
336 {
338 "Conversion of array SMT literal " + array_sort.pretty());
339 }
340};
341
342static smt_termt convert_expr_to_smt(const constant_exprt &constant_literal)
343{
344 if(constant_literal.is_null_pointer())
345 {
346 const size_t bit_width =
347 type_checked_cast<pointer_typet>(constant_literal.type()).get_width();
348 // An address of 0 encodes an object identifier of 0 for the NULL object
349 // and an offset of 0 into the object.
350 const auto address = 0;
351 return smt_bit_vector_constant_termt{address, bit_width};
352 }
353 if(constant_literal.type() == integer_typet{})
354 {
355 // This is converting integer constants into bit vectors for use with
356 // bit vector based smt logics. As bit vector widths are not specified for
357 // non bit vector types, this chooses a width based on the minimum needed
358 // to hold the integer constant value.
359 const auto value = numeric_cast_v<mp_integer>(constant_literal);
360 return smt_bit_vector_constant_termt{value, address_bits(value + 1)};
361 }
362 const auto sort = convert_type_to_smt_sort(constant_literal.type());
363 sort_based_literal_convertert converter(constant_literal);
364 sort.accept(converter);
365 return *converter.result;
366}
367
369 const concatenation_exprt &concatenation,
370 const sub_expression_mapt &converted)
371{
373 {
375 concatenation, converted, smt_bit_vector_theoryt::concat);
376 }
378 "Generation of SMT formula for concatenation expression: " +
379 concatenation.pretty());
380}
381
383 const bitand_exprt &bitwise_and_expr,
384 const sub_expression_mapt &converted)
385{
386 if(operands_are_of_type<bitvector_typet>(bitwise_and_expr))
387 {
389 bitwise_and_expr, converted, smt_bit_vector_theoryt::make_and);
390 }
391 else
392 {
394 "Generation of SMT formula for bitwise and expression: " +
395 bitwise_and_expr.pretty());
396 }
397}
398
400 const bitor_exprt &bitwise_or_expr,
401 const sub_expression_mapt &converted)
402{
403 if(operands_are_of_type<bitvector_typet>(bitwise_or_expr))
404 {
406 bitwise_or_expr, converted, smt_bit_vector_theoryt::make_or);
407 }
408 else
409 {
411 "Generation of SMT formula for bitwise or expression: " +
412 bitwise_or_expr.pretty());
413 }
414}
415
418 const sub_expression_mapt &converted)
419{
421 {
424 }
425 else
426 {
428 "Generation of SMT formula for bitwise xor expression: " +
429 bitwise_xor.pretty());
430 }
431}
432
434 const bitnot_exprt &bitwise_not,
435 const sub_expression_mapt &converted)
436{
437 if(can_cast_type<bitvector_typet>(bitwise_not.op().type()))
438 {
439 return smt_bit_vector_theoryt::make_not(converted.at(bitwise_not.op()));
440 }
441 else
442 {
444 "Generation of SMT formula for bitnot_exprt: " + bitwise_not.pretty());
445 }
446}
447
449 const unary_minus_exprt &unary_minus,
450 const sub_expression_mapt &converted)
451{
453 {
454 return smt_bit_vector_theoryt::negate(converted.at(unary_minus.op()));
455 }
456 else
457 {
459 "Generation of SMT formula for unary minus expression: " +
460 unary_minus.pretty());
461 }
462}
463
465 const unary_plus_exprt &unary_plus,
466 const sub_expression_mapt &converted)
467{
469 "Generation of SMT formula for unary plus expression: " +
470 unary_plus.pretty());
471}
472
474 const sign_exprt &is_negative,
475 const sub_expression_mapt &converted)
476{
478 "Generation of SMT formula for \"is negative\" expression: " +
479 is_negative.pretty());
480}
481
483 const if_exprt &if_expression,
484 const sub_expression_mapt &converted)
485{
487 converted.at(if_expression.cond()),
488 converted.at(if_expression.true_case()),
489 converted.at(if_expression.false_case()));
490}
491
493 const and_exprt &and_expression,
494 const sub_expression_mapt &converted)
495{
497 and_expression, converted, smt_core_theoryt::make_and);
498}
499
501 const or_exprt &or_expression,
502 const sub_expression_mapt &converted)
503{
505 or_expression, converted, smt_core_theoryt::make_or);
506}
507
509 const xor_exprt &xor_expression,
510 const sub_expression_mapt &converted)
511{
513 xor_expression, converted, smt_core_theoryt::make_xor);
514}
515
517 const implies_exprt &implies,
518 const sub_expression_mapt &converted)
519{
521 converted.at(implies.op0()), converted.at(implies.op1()));
522}
523
525 const not_exprt &logical_not,
526 const sub_expression_mapt &converted)
527{
528 return smt_core_theoryt::make_not(converted.at(logical_not.op()));
529}
530
532 const equal_exprt &equal,
533 const sub_expression_mapt &converted)
534{
536 converted.at(equal.op0()), converted.at(equal.op1()));
537}
538
540 const notequal_exprt &not_equal,
541 const sub_expression_mapt &converted)
542{
544 converted.at(not_equal.op0()), converted.at(not_equal.op1()));
545}
546
548 const ieee_float_equal_exprt &float_equal,
549 const sub_expression_mapt &converted)
550{
552 "Floating point equality expression should have been lowered to "
553 "bitvector operations: " +
554 float_equal.pretty());
555}
556
558 const ieee_float_notequal_exprt &float_not_equal,
559 const sub_expression_mapt &converted)
560{
562 "Floating point not equal expression should have been lowered to "
563 "bitvector operations: " +
564 float_not_equal.pretty());
565}
566
567template <typename unsigned_factory_typet, typename signed_factory_typet>
569 const binary_relation_exprt &binary_relation,
570 const unsigned_factory_typet &unsigned_factory,
571 const signed_factory_typet &signed_factory,
572 const sub_expression_mapt &converted)
573{
574 PRECONDITION(binary_relation.lhs().type() == binary_relation.rhs().type());
575 const auto &lhs = converted.at(binary_relation.lhs());
576 const auto &rhs = converted.at(binary_relation.rhs());
577 const typet operand_type = binary_relation.lhs().type();
578 if(can_cast_type<pointer_typet>(operand_type))
579 {
580 // The code here is operating under the assumption that the comparison
581 // operands have types for which the comparison makes sense.
582
583 // We already know this is the case given that we have followed
584 // the if statement branch, but including the same check here
585 // for consistency (it's cheap).
586 const auto lhs_type_is_pointer =
587 can_cast_type<pointer_typet>(binary_relation.lhs().type());
588 const auto rhs_type_is_pointer =
589 can_cast_type<pointer_typet>(binary_relation.rhs().type());
590 INVARIANT(
591 lhs_type_is_pointer && rhs_type_is_pointer,
592 "pointer comparison requires that both operand types are pointers.");
593 return unsigned_factory(lhs, rhs);
594 }
595 else if(lhs.get_sort().cast<smt_bit_vector_sortt>())
596 {
597 if(can_cast_type<unsignedbv_typet>(operand_type))
598 return unsigned_factory(lhs, rhs);
599 if(can_cast_type<signedbv_typet>(operand_type))
600 return signed_factory(lhs, rhs);
601 }
602
604 "Generation of SMT formula for relational expression: " +
605 binary_relation.pretty());
606}
607
608static std::optional<smt_termt> try_relational_conversion(
609 const exprt &expr,
610 const sub_expression_mapt &converted)
611{
613 {
618 converted);
619 }
620 if(
621 const auto greater_than_or_equal =
623 {
625 *greater_than_or_equal,
628 converted);
629 }
631 {
633 *less_than,
636 converted);
637 }
638 if(
639 const auto less_than_or_equal =
641 {
643 *less_than_or_equal,
646 converted);
647 }
648 return {};
649}
650
652 const plus_exprt &plus,
653 const sub_expression_mapt &converted,
654 const type_size_mapt &pointer_sizes)
655{
656 if(std::all_of(
657 plus.operands().cbegin(), plus.operands().cend(), [](exprt operand) {
658 return can_cast_type<integer_bitvector_typet>(operand.type());
659 }))
660 {
662 plus, converted, smt_bit_vector_theoryt::add);
663 }
664 else if(can_cast_type<pointer_typet>(plus.type()))
665 {
666 INVARIANT(
667 plus.operands().size() == 2,
668 "We are only handling a binary version of plus when it has a pointer "
669 "operand");
670
671 exprt pointer;
672 exprt scalar;
673 for(auto &operand : plus.operands())
674 {
676 {
677 pointer = operand;
678 }
679 else
680 {
681 scalar = operand;
682 }
683 }
684
685 // We need to ensure that we follow this code path only if the expression
686 // our assumptions about the structure of the addition expression hold.
687 INVARIANT(
689 "An addition expression with both operands being pointers when they are "
690 "not dereferenced is malformed");
691
694 const auto base_type = pointer_type.base_type();
695 const auto pointer_size = pointer_sizes.at(base_type);
696
698 converted.at(pointer),
699 smt_bit_vector_theoryt::multiply(converted.at(scalar), pointer_size));
700 }
701 else
702 {
704 "Generation of SMT formula for plus expression: " + plus.pretty());
705 }
706}
707
709 const minus_exprt &minus,
710 const sub_expression_mapt &converted,
711 const type_size_mapt &pointer_sizes)
712{
713 const bool both_operands_bitvector =
716
717 const bool lhs_is_pointer = can_cast_type<pointer_typet>(minus.lhs().type());
718 const bool rhs_is_pointer = can_cast_type<pointer_typet>(minus.rhs().type());
719
720 const bool both_operands_pointers = lhs_is_pointer && rhs_is_pointer;
721
722 // We don't really handle this - we just compute this to fall
723 // into an if-else branch that gives proper error handling information.
724 const bool one_operand_pointer = lhs_is_pointer || rhs_is_pointer;
725
726 if(both_operands_bitvector)
727 {
729 converted.at(minus.lhs()), converted.at(minus.rhs()));
730 }
731 else if(both_operands_pointers)
732 {
733 const auto lhs_base_type = to_pointer_type(minus.lhs().type()).base_type();
734 const auto rhs_base_type = to_pointer_type(minus.rhs().type()).base_type();
735 INVARIANT(
736 lhs_base_type == rhs_base_type,
737 "only pointers of the same object type can be subtracted.");
740 converted.at(minus.lhs()), converted.at(minus.rhs())),
741 pointer_sizes.at(lhs_base_type));
742 }
743 else if(one_operand_pointer)
744 {
745 // It's semantically void to have an expression `3 - a` where `a`
746 // is a pointer.
747 INVARIANT(
748 lhs_is_pointer,
749 "minus expressions of pointer and integer expect lhs to be the pointer");
750 const auto lhs_base_type = to_pointer_type(minus.lhs().type()).base_type();
751
753 converted.at(minus.lhs()),
755 converted.at(minus.rhs()), pointer_sizes.at(lhs_base_type)));
756 }
757 else
758 {
760 "Generation of SMT formula for minus expression: " + minus.pretty());
761 }
762}
763
765 const div_exprt &divide,
766 const sub_expression_mapt &converted)
767{
768 const smt_termt &lhs = converted.at(divide.lhs());
769 const smt_termt &rhs = converted.at(divide.rhs());
770
771 const bool both_operands_bitvector =
774
775 const bool both_operands_unsigned =
778
779 if(both_operands_bitvector)
780 {
781 if(both_operands_unsigned)
782 {
784 }
785 else
786 {
788 }
789 }
790 else
791 {
793 "Generation of SMT formula for divide expression: " + divide.pretty());
794 }
795}
796
798 const ieee_float_op_exprt &float_operation,
799 const sub_expression_mapt &converted)
800{
801 // This case includes the floating point plus, minus, division and
802 // multiplication operations.
804 "Floating point operation expression should have been lowered to "
805 "bitvector operations: " +
806 float_operation.pretty());
807}
808
810 const mod_exprt &truncation_modulo,
811 const sub_expression_mapt &converted)
812{
813 const smt_termt &lhs = converted.at(truncation_modulo.lhs());
814 const smt_termt &rhs = converted.at(truncation_modulo.rhs());
815
816 const bool both_operands_bitvector =
817 can_cast_type<integer_bitvector_typet>(truncation_modulo.lhs().type()) &&
818 can_cast_type<integer_bitvector_typet>(truncation_modulo.rhs().type());
819
820 const bool both_operands_unsigned =
821 can_cast_type<unsignedbv_typet>(truncation_modulo.lhs().type()) &&
822 can_cast_type<unsignedbv_typet>(truncation_modulo.rhs().type());
823
824 if(both_operands_bitvector)
825 {
826 if(both_operands_unsigned)
827 {
829 }
830 else
831 {
833 }
834 }
835 else
836 {
838 "Generation of SMT formula for remainder (modulus) expression: " +
839 truncation_modulo.pretty());
840 }
841}
842
844 const euclidean_mod_exprt &euclidean_modulo,
845 const sub_expression_mapt &converted)
846{
848 "Generation of SMT formula for euclidean modulo expression: " +
849 euclidean_modulo.pretty());
850}
851
853 const mult_exprt &multiply,
854 const sub_expression_mapt &converted)
855{
856 if(std::all_of(
857 multiply.operands().cbegin(),
858 multiply.operands().cend(),
859 [](exprt operand) {
860 return can_cast_type<integer_bitvector_typet>(operand.type());
861 }))
862 {
864 multiply, converted, smt_bit_vector_theoryt::multiply);
865 }
866 else
867 {
869 "Generation of SMT formula for multiply expression: " +
870 multiply.pretty());
871 }
872}
873
882 const address_of_exprt &address_of,
883 const sub_expression_mapt &converted,
884 const smt_object_mapt &object_map)
885{
886 const auto type = type_try_dynamic_cast<pointer_typet>(address_of.type());
887 INVARIANT(
888 type, "Result of the address_of operator should have pointer type.");
889 const auto base = find_object_base_expression(address_of);
890 const auto object = object_map.find(base);
891 INVARIANT(
892 object != object_map.end(),
893 "Objects should be tracked before converting their address to SMT terms");
894 const std::size_t object_id = object->second.unique_id;
895 const std::size_t object_bits = config.bv_encoding.object_bits;
896 const std::size_t max_objects = std::size_t(1) << object_bits;
897 if(object_id >= max_objects)
898 {
900 "too many addressed objects: maximum number of objects is set to 2^n=" +
901 std::to_string(max_objects) + " (with n=" + std::to_string(object_bits) +
902 "); " +
903 "use the `--object-bits n` option to increase the maximum number"};
904 }
905 const smt_termt object_bit_vector =
906 smt_bit_vector_constant_termt{object_id, object_bits};
907 INVARIANT(
908 type->get_width() > object_bits,
909 "Pointer should be wider than object_bits in order to allow for offset "
910 "encoding.");
911 const size_t offset_bits = type->get_width() - object_bits;
913 {
914 const smt_bit_vector_constant_termt offset{0, offset_bits};
915 return smt_bit_vector_theoryt::concat(object_bit_vector, offset);
916 }
918 "Generation of SMT formula for address of expression: " +
919 address_of.pretty());
920}
921
923 const array_of_exprt &array_of,
924 const sub_expression_mapt &converted)
925{
926 // This function is unreachable as the `array_of_exprt` nodes are already
927 // fully converted by the incremental decision procedure functions
928 // (smt2_incremental_decision_proceduret::define_array_function).
930}
931
933 const array_comprehension_exprt &array_comprehension,
934 const sub_expression_mapt &converted)
935{
937 "Generation of SMT formula for array comprehension expression: " +
938 array_comprehension.pretty());
939}
940
942 const index_exprt &index_of,
943 const sub_expression_mapt &converted)
944{
945 const smt_termt &array = converted.at(index_of.array());
946 const smt_termt &index = converted.at(index_of.index());
947 return smt_array_theoryt::select(array, index);
948}
949
950template <typename factoryt, typename shiftt>
952 const factoryt &factory,
953 const shiftt &shift,
954 const sub_expression_mapt &converted)
955{
956 const smt_termt &first_operand = converted.at(shift.op0());
957 const smt_termt &second_operand = converted.at(shift.op1());
958 const auto first_bit_vector_sort =
959 first_operand.get_sort().cast<smt_bit_vector_sortt>();
960 const auto second_bit_vector_sort =
961 second_operand.get_sort().cast<smt_bit_vector_sortt>();
962 INVARIANT(
963 first_bit_vector_sort && second_bit_vector_sort,
964 "Shift expressions are expected to have bit vector operands.");
965 INVARIANT(
966 shift.type() == shift.op0().type(),
967 "Shift expression type must be equals to first operand type.");
968 const std::size_t first_width = first_bit_vector_sort->bit_width();
969 const std::size_t second_width = second_bit_vector_sort->bit_width();
970 if(first_width > second_width)
971 {
972 return factory(
973 first_operand,
974 extension_for_type(shift.op1().type())(first_width - second_width)(
975 second_operand));
976 }
977 else if(first_width < second_width)
978 {
979 const auto result = factory(
980 extension_for_type(shift.op0().type())(second_width - first_width)(
981 first_operand),
982 second_operand);
983 return smt_bit_vector_theoryt::extract(first_width - 1, 0)(result);
984 }
985 else
986 {
987 return factory(first_operand, second_operand);
988 }
989}
990
992 const shift_exprt &shift,
993 const sub_expression_mapt &converted)
994{
995 // TODO: Dispatch for rotation expressions. A `shift_exprt` can be a rotation.
996 if(const auto left_shift = expr_try_dynamic_cast<shl_exprt>(shift))
997 {
999 smt_bit_vector_theoryt::shift_left, *left_shift, converted);
1000 }
1001 if(const auto right_logical_shift = expr_try_dynamic_cast<lshr_exprt>(shift))
1002 {
1003 return convert_to_smt_shift(
1005 *right_logical_shift,
1006 converted);
1007 }
1008 if(const auto right_arith_shift = expr_try_dynamic_cast<ashr_exprt>(shift))
1009 {
1010 return convert_to_smt_shift(
1012 *right_arith_shift,
1013 converted);
1014 }
1016 "Generation of SMT formula for shift expression: " + shift.pretty());
1017}
1018
1020 const with_exprt &with,
1021 const sub_expression_mapt &converted)
1022{
1023 smt_termt array = converted.at(with.old());
1024 const smt_termt &index_term = converted.at(with.where());
1025 const smt_termt &value_term = converted.at(with.new_value());
1026 array = smt_array_theoryt::store(array, index_term, value_term);
1027 return array;
1028}
1029
1031 const with_exprt &with,
1032 const sub_expression_mapt &converted)
1033{
1035 return convert_array_update_to_smt(with, converted);
1036 // 'with' expression is also used to update struct fields, but for now we do
1037 // not support them, so we fail.
1039 "Generation of SMT formula for with expression: " + with.pretty());
1040}
1041
1043 const update_exprt &update,
1044 const sub_expression_mapt &converted)
1045{
1047 "Generation of SMT formula for update expression: " + update.pretty());
1048}
1049
1051 const member_exprt &member_extraction,
1052 const sub_expression_mapt &converted)
1053{
1055 "Generation of SMT formula for member extraction expression: " +
1056 member_extraction.pretty());
1057}
1058
1060 const is_dynamic_object_exprt &is_dynamic_object,
1061 const sub_expression_mapt &converted,
1062 const smt_is_dynamic_objectt::make_applicationt &apply_is_dynamic_object)
1063{
1064 const smt_termt &pointer = converted.at(is_dynamic_object.address());
1065 const auto pointer_sort = pointer.get_sort().cast<smt_bit_vector_sortt>();
1066 INVARIANT(
1067 pointer_sort, "Pointers should be encoded as bit vector sorted terms.");
1068 const std::size_t pointer_width = pointer_sort->bit_width();
1069 return apply_is_dynamic_object(
1070 std::vector<smt_termt>{smt_bit_vector_theoryt::extract(
1071 pointer_width - 1,
1072 pointer_width - config.bv_encoding.object_bits)(pointer)});
1073}
1074
1076 const is_invalid_pointer_exprt &is_invalid_pointer,
1077 const smt_object_mapt &object_map,
1078 const sub_expression_mapt &converted)
1079{
1080 const exprt &pointer_expr(to_unary_expr(is_invalid_pointer).op());
1083 INVARIANT(pointer_type, "Pointer object should have a bitvector-based type.");
1084 const std::size_t object_bits = config.bv_encoding.object_bits;
1085 const std::size_t width = pointer_type->get_width();
1086 INVARIANT(
1087 width >= object_bits,
1088 "Width should be at least as big as the number of object bits.");
1089
1090 const auto extract_op = smt_bit_vector_theoryt::extract(
1091 width - 1, width - object_bits)(converted.at(pointer_expr));
1092
1093 const auto &invalid_pointer = object_map.at(make_invalid_pointer_expr());
1094
1095 const smt_termt invalid_pointer_address = smt_bit_vector_constant_termt(
1096 invalid_pointer.unique_id, config.bv_encoding.object_bits);
1097
1098 return smt_core_theoryt::equal(invalid_pointer_address, extract_op);
1099}
1100
1102 const string_constantt &string_constant,
1103 const sub_expression_mapt &converted)
1104{
1106 "Generation of SMT formula for string constant expression: " +
1107 string_constant.pretty());
1108}
1109
1111 const extractbit_exprt &extract_bit,
1112 const sub_expression_mapt &converted)
1113{
1115 "Generation of SMT formula for extract bit expression: " +
1116 extract_bit.pretty());
1117}
1118
1120 const extractbits_exprt &extract_bits,
1121 const sub_expression_mapt &converted)
1122{
1123 const smt_termt &from = converted.at(extract_bits.src());
1124 const auto bit_vector_sort =
1126 INVARIANT(
1127 bit_vector_sort, "Extract can only be applied to bit vector terms.");
1128 const auto index_value = numeric_cast<std::size_t>(extract_bits.index());
1129 if(index_value)
1131 *index_value + bit_vector_sort->bit_width() - 1, *index_value)(from);
1133 "Generation of SMT formula for extract bits expression: " +
1134 extract_bits.pretty());
1135}
1136
1138 const replication_exprt &replication,
1139 const sub_expression_mapt &converted)
1140{
1142 "Generation of SMT formula for bit vector replication expression: " +
1143 replication.pretty());
1144}
1145
1147 const byte_extract_exprt &byte_extraction,
1148 const sub_expression_mapt &converted)
1149{
1151 "Generation of SMT formula for byte extract expression: " +
1152 byte_extraction.pretty());
1153}
1154
1156 const byte_update_exprt &byte_update,
1157 const sub_expression_mapt &converted)
1158{
1160 "Generation of SMT formula for byte update expression: " +
1161 byte_update.pretty());
1162}
1163
1165 const abs_exprt &absolute_value_of,
1166 const sub_expression_mapt &converted)
1167{
1169 "Generation of SMT formula for absolute value of expression: " +
1170 absolute_value_of.pretty());
1171}
1172
1174 const isnan_exprt &is_nan_expr,
1175 const sub_expression_mapt &converted)
1176{
1178 "Is not a number expression should have been lowered to "
1179 "bitvector operations: " +
1180 is_nan_expr.pretty());
1181}
1182
1184 const isfinite_exprt &is_finite_expr,
1185 const sub_expression_mapt &converted)
1186{
1188 "Is finite expression should have been lowered to "
1189 "bitvector operations: " +
1190 is_finite_expr.pretty());
1191}
1192
1194 const isinf_exprt &is_infinite_expr,
1195 const sub_expression_mapt &converted)
1196{
1198 "Is infinite expression should have been lowered to "
1199 "bitvector operations: " +
1200 is_infinite_expr.pretty());
1201}
1202
1204 const isnormal_exprt &is_normal_expr,
1205 const sub_expression_mapt &converted)
1206{
1208 "Is normal expression should have been lowered to "
1209 "bitvector operations: " +
1210 is_normal_expr.pretty());
1211}
1212
1217{
1218 const auto bit_vector_sort = input.get_sort().cast<smt_bit_vector_sortt>();
1219 INVARIANT(
1220 bit_vector_sort,
1221 "Most significant bit can only be extracted from bit vector terms.");
1222 const size_t most_significant_bit_index = bit_vector_sort->bit_width() - 1;
1223 const auto extract_most_significant_bit = smt_bit_vector_theoryt::extract(
1224 most_significant_bit_index, most_significant_bit_index);
1226 extract_most_significant_bit(input), smt_bit_vector_constant_termt{1, 1});
1227}
1228
1230 const plus_overflow_exprt &plus_overflow,
1231 const sub_expression_mapt &converted)
1232{
1233 const smt_termt &left = converted.at(plus_overflow.lhs());
1234 const smt_termt &right = converted.at(plus_overflow.rhs());
1236 {
1237 const auto add_carry_bit = smt_bit_vector_theoryt::zero_extend(1);
1239 smt_bit_vector_theoryt::add(add_carry_bit(left), add_carry_bit(right)));
1240 }
1241 if(operands_are_of_type<signedbv_typet>(plus_overflow))
1242 {
1243 // Overflow has occurred if the operands have the same sign and adding them
1244 // gives a result of the opposite sign.
1245 const smt_termt msb_left = most_significant_bit_is_set(left);
1246 const smt_termt msb_right = most_significant_bit_is_set(right);
1248 smt_core_theoryt::equal(msb_left, msb_right),
1250 msb_left,
1252 }
1254 "Generation of SMT formula for plus overflow expression: " +
1255 plus_overflow.pretty());
1256}
1257
1259 const minus_overflow_exprt &minus_overflow,
1260 const sub_expression_mapt &converted)
1261{
1262 const smt_termt &left = converted.at(minus_overflow.lhs());
1263 const smt_termt &right = converted.at(minus_overflow.rhs());
1264 if(operands_are_of_type<unsignedbv_typet>(minus_overflow))
1265 {
1267 }
1268 if(operands_are_of_type<signedbv_typet>(minus_overflow))
1269 {
1270 // Overflow has occurred if the operands have the opposing signs and
1271 // subtracting them gives a result having the same signedness as the
1272 // right-hand operand. For example the following would be overflow for cases
1273 // for 8 bit wide bit vectors -
1274 // -128 - 1 == 127
1275 // 127 - (-1) == -128
1276 const smt_termt msb_left = most_significant_bit_is_set(left);
1277 const smt_termt msb_right = most_significant_bit_is_set(right);
1279 smt_core_theoryt::distinct(msb_left, msb_right),
1281 msb_right,
1283 smt_bit_vector_theoryt::subtract(left, right))));
1284 }
1286 "Generation of SMT formula for minus overflow expression: " +
1287 minus_overflow.pretty());
1288}
1289
1291 const mult_overflow_exprt &mult_overflow,
1292 const sub_expression_mapt &converted)
1293{
1294 PRECONDITION(mult_overflow.lhs().type() == mult_overflow.rhs().type());
1295 const auto &operand_type = mult_overflow.lhs().type();
1296 const smt_termt &left = converted.at(mult_overflow.lhs());
1297 const smt_termt &right = converted.at(mult_overflow.rhs());
1298 if(
1299 const auto unsigned_type =
1301 {
1302 const std::size_t width = unsigned_type->get_width();
1303 const auto extend = smt_bit_vector_theoryt::zero_extend(width);
1305 smt_bit_vector_theoryt::multiply(extend(left), extend(right)),
1306 smt_bit_vector_constant_termt{power(2, width), width * 2});
1307 }
1308 if(
1309 const auto signed_type =
1311 {
1312 const smt_termt msb_left = most_significant_bit_is_set(left);
1313 const smt_termt msb_right = most_significant_bit_is_set(right);
1314 const std::size_t width = signed_type->get_width();
1315 const auto extend = smt_bit_vector_theoryt::sign_extend(width);
1316 const auto multiplication =
1317 smt_bit_vector_theoryt::multiply(extend(left), extend(right));
1319 multiplication,
1320 smt_bit_vector_constant_termt{power(2, width - 1), width * 2});
1321 const auto too_small = smt_bit_vector_theoryt::signed_less_than(
1322 multiplication,
1324 smt_bit_vector_constant_termt{power(2, width - 1), width * 2}));
1326 smt_core_theoryt::equal(msb_left, msb_right), too_large, too_small);
1327 }
1329 "Generation of SMT formula for multiply overflow expression: " +
1330 mult_overflow.pretty());
1331}
1332
1335 const sub_expression_mapt &converted)
1336{
1337 const auto type =
1339 INVARIANT(type, "Pointer object should have a bitvector-based type.");
1340 const auto converted_expr = converted.at(pointer_object.pointer());
1341 const std::size_t width = type->get_width();
1342 const std::size_t object_bits = config.bv_encoding.object_bits;
1343 INVARIANT(
1344 width >= object_bits,
1345 "Width should be at least as big as the number of object bits.");
1346 const std::size_t ext = width - object_bits;
1347 const auto extract_op = smt_bit_vector_theoryt::extract(
1348 width - 1, width - object_bits)(converted_expr);
1349 if(ext > 0)
1350 {
1351 return smt_bit_vector_theoryt::zero_extend(ext)(extract_op);
1352 }
1353 return extract_op;
1354}
1355
1358 const sub_expression_mapt &converted)
1359{
1360 const auto type =
1362 INVARIANT(type, "Pointer offset should have a bitvector-based type.");
1363 const auto converted_expr = converted.at(pointer_offset.pointer());
1364 const std::size_t width = type->get_width();
1365 std::size_t offset_bits = width - config.bv_encoding.object_bits;
1366 if(offset_bits > width)
1367 offset_bits = width;
1368 const auto extract_op =
1369 smt_bit_vector_theoryt::extract(offset_bits - 1, 0)(converted_expr);
1370 if(width > offset_bits)
1371 {
1372 return smt_bit_vector_theoryt::sign_extend(width - offset_bits)(extract_op);
1373 }
1374 return extract_op;
1375}
1376
1378 const shl_overflow_exprt &shl_overflow,
1379 const sub_expression_mapt &converted)
1380{
1382 "Generation of SMT formula for shift left overflow expression: " +
1383 shl_overflow.pretty());
1384}
1385
1387 const array_exprt &array_construction,
1388 const sub_expression_mapt &converted)
1389{
1390 // This function is unreachable as the `array_exprt` nodes are already fully
1391 // converted by the incremental decision procedure functions
1392 // (smt2_incremental_decision_proceduret::define_array_function).
1394}
1395
1397 const literal_exprt &literal,
1398 const sub_expression_mapt &converted)
1399{
1401 "Generation of SMT formula for literal expression: " + literal.pretty());
1402}
1403
1405 const forall_exprt &for_all,
1406 const sub_expression_mapt &converted)
1407{
1409 "Generation of SMT formula for for all expression: " + for_all.pretty());
1410}
1411
1413 const exists_exprt &exists,
1414 const sub_expression_mapt &converted)
1415{
1417 "Generation of SMT formula for exists expression: " + exists.pretty());
1418}
1419
1421 const vector_exprt &vector,
1422 const sub_expression_mapt &converted)
1423{
1425 "Generation of SMT formula for vector expression: " + vector.pretty());
1426}
1427
1430 const sub_expression_mapt &converted,
1431 const smt_object_sizet::make_applicationt &call_object_size)
1432{
1433 const smt_termt &pointer = converted.at(object_size.pointer());
1434 const auto pointer_sort = pointer.get_sort().cast<smt_bit_vector_sortt>();
1435 INVARIANT(
1436 pointer_sort, "Pointers should be encoded as bit vector sorted terms.");
1437 const std::size_t pointer_width = pointer_sort->bit_width();
1438 return call_object_size(
1439 std::vector<smt_termt>{smt_bit_vector_theoryt::extract(
1440 pointer_width - 1,
1441 pointer_width - config.bv_encoding.object_bits)(pointer)});
1442}
1443
1444static smt_termt
1446{
1448 "Generation of SMT formula for let expression: " + let.pretty());
1449}
1450
1452 const bswap_exprt &byte_swap,
1453 const sub_expression_mapt &converted)
1454{
1456 "Generation of SMT formula for byte swap expression: " +
1457 byte_swap.pretty());
1458}
1459
1461 const popcount_exprt &population_count,
1462 const sub_expression_mapt &converted)
1463{
1465 "Generation of SMT formula for population count expression: " +
1466 population_count.pretty());
1467}
1468
1470 const count_leading_zeros_exprt &count_leading_zeros,
1471 const sub_expression_mapt &converted)
1472{
1474 "Generation of SMT formula for count leading zeros expression: " +
1475 count_leading_zeros.pretty());
1476}
1477
1479 const count_trailing_zeros_exprt &count_trailing_zeros,
1480 const sub_expression_mapt &converted)
1481{
1483 "Generation of SMT formula for count trailing zeros expression: " +
1484 count_trailing_zeros.pretty());
1485}
1486
1488 const zero_extend_exprt &zero_extend,
1489 const sub_expression_mapt &converted)
1490{
1492 "zero_extend expression should have been lowered by the decision "
1493 "procedure before conversion to smt terms");
1494}
1495
1497 const prophecy_r_or_w_ok_exprt &prophecy_r_or_w_ok,
1498 const sub_expression_mapt &converted)
1499{
1501 "prophecy_r_or_w_ok expression should have been lowered by the decision "
1502 "procedure before conversion to smt terms");
1503}
1504
1506 const prophecy_pointer_in_range_exprt &prophecy_pointer_in_range,
1507 const sub_expression_mapt &converted)
1508{
1510 "prophecy_pointer_in_range expression should have been lowered by the "
1511 "decision procedure before conversion to smt terms");
1512}
1513
1515 const exprt &expr,
1516 const sub_expression_mapt &converted,
1517 const smt_object_mapt &object_map,
1518 const type_size_mapt &pointer_sizes,
1519 const smt_object_sizet::make_applicationt &call_object_size,
1520 const smt_is_dynamic_objectt::make_applicationt &apply_is_dynamic_object)
1521{
1522 if(const auto symbol = expr_try_dynamic_cast<symbol_exprt>(expr))
1523 {
1524 return convert_expr_to_smt(*symbol);
1525 }
1526 if(const auto nondet = expr_try_dynamic_cast<nondet_symbol_exprt>(expr))
1527 {
1528 return convert_expr_to_smt(*nondet, converted);
1529 }
1530 if(const auto cast = expr_try_dynamic_cast<typecast_exprt>(expr))
1531 {
1532 return convert_expr_to_smt(*cast, converted);
1533 }
1534 if(
1535 const auto float_cast = expr_try_dynamic_cast<floatbv_typecast_exprt>(expr))
1536 {
1537 return convert_expr_to_smt(*float_cast, converted);
1538 }
1539 if(const auto struct_construction = expr_try_dynamic_cast<struct_exprt>(expr))
1540 {
1541 return convert_expr_to_smt(*struct_construction, converted);
1542 }
1543 if(const auto union_construction = expr_try_dynamic_cast<union_exprt>(expr))
1544 {
1545 return convert_expr_to_smt(*union_construction, converted);
1546 }
1547 if(const auto constant_literal = expr_try_dynamic_cast<constant_exprt>(expr))
1548 {
1549 return convert_expr_to_smt(*constant_literal);
1550 }
1551 if(
1552 const auto concatenation = expr_try_dynamic_cast<concatenation_exprt>(expr))
1553 {
1554 return convert_expr_to_smt(*concatenation, converted);
1555 }
1556 if(const auto bitwise_and_expr = expr_try_dynamic_cast<bitand_exprt>(expr))
1557 {
1558 return convert_expr_to_smt(*bitwise_and_expr, converted);
1559 }
1560 if(const auto bitwise_or_expr = expr_try_dynamic_cast<bitor_exprt>(expr))
1561 {
1562 return convert_expr_to_smt(*bitwise_or_expr, converted);
1563 }
1565 {
1566 return convert_expr_to_smt(*bitwise_xor, converted);
1567 }
1568 if(const auto bitwise_not = expr_try_dynamic_cast<bitnot_exprt>(expr))
1569 {
1570 return convert_expr_to_smt(*bitwise_not, converted);
1571 }
1572 if(const auto unary_minus = expr_try_dynamic_cast<unary_minus_exprt>(expr))
1573 {
1574 return convert_expr_to_smt(*unary_minus, converted);
1575 }
1576 if(const auto unary_plus = expr_try_dynamic_cast<unary_plus_exprt>(expr))
1577 {
1578 return convert_expr_to_smt(*unary_plus, converted);
1579 }
1580 if(const auto is_negative = expr_try_dynamic_cast<sign_exprt>(expr))
1581 {
1582 return convert_expr_to_smt(*is_negative, converted);
1583 }
1584 if(const auto if_expression = expr_try_dynamic_cast<if_exprt>(expr))
1585 {
1586 return convert_expr_to_smt(*if_expression, converted);
1587 }
1588 if(const auto and_expression = expr_try_dynamic_cast<and_exprt>(expr))
1589 {
1590 return convert_expr_to_smt(*and_expression, converted);
1591 }
1592 if(const auto or_expression = expr_try_dynamic_cast<or_exprt>(expr))
1593 {
1594 return convert_expr_to_smt(*or_expression, converted);
1595 }
1596 if(const auto xor_expression = expr_try_dynamic_cast<xor_exprt>(expr))
1597 {
1598 return convert_expr_to_smt(*xor_expression, converted);
1599 }
1600 if(const auto implies = expr_try_dynamic_cast<implies_exprt>(expr))
1601 {
1602 return convert_expr_to_smt(*implies, converted);
1603 }
1604 if(const auto logical_not = expr_try_dynamic_cast<not_exprt>(expr))
1605 {
1606 return convert_expr_to_smt(*logical_not, converted);
1607 }
1608 if(const auto equal = expr_try_dynamic_cast<equal_exprt>(expr))
1609 {
1610 return convert_expr_to_smt(*equal, converted);
1611 }
1612 if(const auto not_equal = expr_try_dynamic_cast<notequal_exprt>(expr))
1613 {
1614 return convert_expr_to_smt(*not_equal, converted);
1615 }
1616 if(
1617 const auto float_equal =
1619 {
1620 return convert_expr_to_smt(*float_equal, converted);
1621 }
1622 if(
1623 const auto float_not_equal =
1625 {
1626 return convert_expr_to_smt(*float_not_equal, converted);
1627 }
1628 if(
1629 const auto converted_relational =
1630 try_relational_conversion(expr, converted))
1631 {
1632 return *converted_relational;
1633 }
1634 if(const auto plus = expr_try_dynamic_cast<plus_exprt>(expr))
1635 {
1636 return convert_expr_to_smt(*plus, converted, pointer_sizes);
1637 }
1638 if(const auto minus = expr_try_dynamic_cast<minus_exprt>(expr))
1639 {
1640 return convert_expr_to_smt(*minus, converted, pointer_sizes);
1641 }
1642 if(const auto divide = expr_try_dynamic_cast<div_exprt>(expr))
1643 {
1644 return convert_expr_to_smt(*divide, converted);
1645 }
1646 if(
1647 const auto float_operation =
1649 {
1650 return convert_expr_to_smt(*float_operation, converted);
1651 }
1652 if(const auto truncation_modulo = expr_try_dynamic_cast<mod_exprt>(expr))
1653 {
1654 return convert_expr_to_smt(*truncation_modulo, converted);
1655 }
1656 if(
1657 const auto euclidean_modulo =
1659 {
1660 return convert_expr_to_smt(*euclidean_modulo, converted);
1661 }
1662 if(const auto multiply = expr_try_dynamic_cast<mult_exprt>(expr))
1663 {
1664 return convert_expr_to_smt(*multiply, converted);
1665 }
1666 if(const auto address_of = expr_try_dynamic_cast<address_of_exprt>(expr))
1667 {
1668 return convert_expr_to_smt(*address_of, converted, object_map);
1669 }
1670 if(const auto array_of = expr_try_dynamic_cast<array_of_exprt>(expr))
1671 {
1672 return convert_expr_to_smt(*array_of, converted);
1673 }
1674 if(
1675 const auto array_comprehension =
1677 {
1678 return convert_expr_to_smt(*array_comprehension, converted);
1679 }
1680 if(const auto index = expr_try_dynamic_cast<index_exprt>(expr))
1681 {
1682 return convert_expr_to_smt(*index, converted);
1683 }
1684 if(const auto shift = expr_try_dynamic_cast<shift_exprt>(expr))
1685 {
1686 return convert_expr_to_smt(*shift, converted);
1687 }
1688 if(const auto with = expr_try_dynamic_cast<with_exprt>(expr))
1689 {
1690 return convert_expr_to_smt(*with, converted);
1691 }
1692 if(const auto update = expr_try_dynamic_cast<update_exprt>(expr))
1693 {
1694 return convert_expr_to_smt(*update, converted);
1695 }
1696 if(const auto member_extraction = expr_try_dynamic_cast<member_exprt>(expr))
1697 {
1698 return convert_expr_to_smt(*member_extraction, converted);
1699 }
1700 else if(
1701 const auto pointer_offset =
1703 {
1704 return convert_expr_to_smt(*pointer_offset, converted);
1705 }
1706 else if(
1707 const auto pointer_object =
1709 {
1710 return convert_expr_to_smt(*pointer_object, converted);
1711 }
1712 if(
1713 const auto is_dynamic_object =
1715 {
1716 return convert_expr_to_smt(
1717 *is_dynamic_object, converted, apply_is_dynamic_object);
1718 }
1719 if(
1720 const auto is_invalid_pointer =
1722 {
1723 return convert_expr_to_smt(*is_invalid_pointer, object_map, converted);
1724 }
1725 if(const auto string_constant = expr_try_dynamic_cast<string_constantt>(expr))
1726 {
1727 return convert_expr_to_smt(*string_constant, converted);
1728 }
1729 if(const auto extract_bit = expr_try_dynamic_cast<extractbit_exprt>(expr))
1730 {
1731 return convert_expr_to_smt(*extract_bit, converted);
1732 }
1733 if(const auto extract_bits = expr_try_dynamic_cast<extractbits_exprt>(expr))
1734 {
1735 return convert_expr_to_smt(*extract_bits, converted);
1736 }
1737 if(const auto replication = expr_try_dynamic_cast<replication_exprt>(expr))
1738 {
1739 return convert_expr_to_smt(*replication, converted);
1740 }
1741 if(
1742 const auto byte_extraction =
1744 {
1745 return convert_expr_to_smt(*byte_extraction, converted);
1746 }
1747 if(const auto byte_update = expr_try_dynamic_cast<byte_update_exprt>(expr))
1748 {
1749 return convert_expr_to_smt(*byte_update, converted);
1750 }
1751 if(const auto absolute_value_of = expr_try_dynamic_cast<abs_exprt>(expr))
1752 {
1753 return convert_expr_to_smt(*absolute_value_of, converted);
1754 }
1755 if(const auto is_nan_expr = expr_try_dynamic_cast<isnan_exprt>(expr))
1756 {
1757 return convert_expr_to_smt(*is_nan_expr, converted);
1758 }
1759 if(const auto is_finite_expr = expr_try_dynamic_cast<isfinite_exprt>(expr))
1760 {
1761 return convert_expr_to_smt(*is_finite_expr, converted);
1762 }
1763 if(const auto is_infinite_expr = expr_try_dynamic_cast<isinf_exprt>(expr))
1764 {
1765 return convert_expr_to_smt(*is_infinite_expr, converted);
1766 }
1767 if(const auto is_normal_expr = expr_try_dynamic_cast<isnormal_exprt>(expr))
1768 {
1769 return convert_expr_to_smt(*is_normal_expr, converted);
1770 }
1771 if(
1772 const auto plus_overflow = expr_try_dynamic_cast<plus_overflow_exprt>(expr))
1773 {
1774 return convert_expr_to_smt(*plus_overflow, converted);
1775 }
1776 if(
1777 const auto minus_overflow =
1779 {
1780 return convert_expr_to_smt(*minus_overflow, converted);
1781 }
1782 if(
1783 const auto mult_overflow = expr_try_dynamic_cast<mult_overflow_exprt>(expr))
1784 {
1785 return convert_expr_to_smt(*mult_overflow, converted);
1786 }
1787 if(const auto shl_overflow = expr_try_dynamic_cast<shl_overflow_exprt>(expr))
1788 {
1789 return convert_expr_to_smt(*shl_overflow, converted);
1790 }
1791 if(const auto array_construction = expr_try_dynamic_cast<array_exprt>(expr))
1792 {
1793 return convert_expr_to_smt(*array_construction, converted);
1794 }
1795 if(const auto literal = expr_try_dynamic_cast<literal_exprt>(expr))
1796 {
1797 return convert_expr_to_smt(*literal, converted);
1798 }
1799 if(const auto for_all = expr_try_dynamic_cast<forall_exprt>(expr))
1800 {
1801 return convert_expr_to_smt(*for_all, converted);
1802 }
1803 if(const auto exists = expr_try_dynamic_cast<exists_exprt>(expr))
1804 {
1805 return convert_expr_to_smt(*exists, converted);
1806 }
1807 if(const auto vector = expr_try_dynamic_cast<vector_exprt>(expr))
1808 {
1809 return convert_expr_to_smt(*vector, converted);
1810 }
1812 {
1813 return convert_expr_to_smt(*object_size, converted, call_object_size);
1814 }
1815 if(const auto let = expr_try_dynamic_cast<let_exprt>(expr))
1816 {
1817 return convert_expr_to_smt(*let, converted);
1818 }
1819 INVARIANT(
1820 expr.id() != ID_constraint_select_one,
1821 "constraint_select_one is not expected in smt conversion: " +
1822 expr.pretty());
1823 if(const auto byte_swap = expr_try_dynamic_cast<bswap_exprt>(expr))
1824 {
1825 return convert_expr_to_smt(*byte_swap, converted);
1826 }
1827 if(const auto population_count = expr_try_dynamic_cast<popcount_exprt>(expr))
1828 {
1829 return convert_expr_to_smt(*population_count, converted);
1830 }
1831 if(
1832 const auto count_leading_zeros =
1834 {
1835 return convert_expr_to_smt(*count_leading_zeros, converted);
1836 }
1837 if(
1838 const auto count_trailing_zeros =
1840 {
1841 return convert_expr_to_smt(*count_trailing_zeros, converted);
1842 }
1843 if(const auto zero_extend = expr_try_dynamic_cast<zero_extend_exprt>(expr))
1844 {
1845 return convert_expr_to_smt(*zero_extend, converted);
1846 }
1847 if(
1848 const auto prophecy_r_or_w_ok =
1850 {
1851 return convert_expr_to_smt(*prophecy_r_or_w_ok, converted);
1852 }
1853 if(
1854 const auto prophecy_pointer_in_range =
1856 {
1857 return convert_expr_to_smt(*prophecy_pointer_in_range, converted);
1858 }
1859
1861 "Generation of SMT formula for unknown kind of expression: " +
1862 expr.pretty());
1863}
1864
1865#ifndef CPROVER_INVARIANT_DO_NOT_CHECK
1866template <typename functiont>
1879
1880template <typename functiont>
1882{
1883 return at_scope_exitt<functiont>(exit_function);
1884}
1885#endif
1886
1888{
1889 expr.visit_pre([](exprt &expr) {
1890 const auto address_of_expr = expr_try_dynamic_cast<address_of_exprt>(expr);
1891 if(!address_of_expr)
1892 return;
1893 const auto array_index_expr =
1894 expr_try_dynamic_cast<index_exprt>(address_of_expr->object());
1895 if(!array_index_expr)
1896 return;
1897 expr = plus_exprt{
1899 array_index_expr->array(),
1900 type_checked_cast<pointer_typet>(address_of_expr->type())},
1901 array_index_expr->index()};
1902 });
1903 return expr;
1904}
1905
1910 const exprt &_expr,
1911 std::function<bool(const exprt &)> filter,
1912 std::function<void(const exprt &)> visitor)
1913{
1914 struct stack_entryt
1915 {
1916 const exprt *e;
1917 bool operands_pushed;
1918 explicit stack_entryt(const exprt *_e) : e(_e), operands_pushed(false)
1919 {
1920 }
1921 };
1922
1923 std::stack<stack_entryt> stack;
1924
1925 stack.emplace(&_expr);
1926
1927 while(!stack.empty())
1928 {
1929 auto &top = stack.top();
1930 if(top.operands_pushed)
1931 {
1932 visitor(*top.e);
1933 stack.pop();
1934 }
1935 else
1936 {
1937 // do modification of 'top' before pushing in case 'top' isn't stable
1938 top.operands_pushed = true;
1939 if(filter(*top.e))
1940 for(auto &op : top.e->operands())
1941 stack.emplace(&op);
1942 }
1943 }
1944}
1945
1947 const exprt &expr,
1948 const smt_object_mapt &object_map,
1949 const type_size_mapt &pointer_sizes,
1951 const smt_is_dynamic_objectt::make_applicationt &is_dynamic_object)
1952{
1953#ifndef CPROVER_INVARIANT_DO_NOT_CHECK
1954 static bool in_conversion = false;
1955 INVARIANT(
1956 !in_conversion,
1957 "Conversion of expr to smt should be non-recursive. "
1958 "Re-entrance found in conversion of " +
1959 expr.pretty(1, 0));
1960 in_conversion = true;
1961 const auto end_conversion = at_scope_exit([&]() { in_conversion = false; });
1962#endif
1963 sub_expression_mapt sub_expression_map;
1964 const auto lowered_expr = lower_address_of_array_index(expr);
1966 lowered_expr,
1967 [](const exprt &expr) {
1968 // Code values inside "address of" expressions do not need to be converted
1969 // as the "address of" conversion only depends on the object identifier.
1970 // Avoiding the conversion side steps a need to convert arbitrary code to
1971 // SMT terms.
1972 const auto address_of = expr_try_dynamic_cast<address_of_exprt>(expr);
1973 if(!address_of)
1974 return true;
1975 return !can_cast_type<code_typet>(address_of->object().type());
1976 },
1977 [&](const exprt &expr) {
1978 const auto find_result = sub_expression_map.find(expr);
1979 if(find_result != sub_expression_map.cend())
1980 return;
1982 expr,
1983 sub_expression_map,
1984 object_map,
1985 pointer_sizes,
1987 is_dynamic_object);
1988 sub_expression_map.emplace_hint(find_result, expr, std::move(term));
1989 });
1990 return std::move(sub_expression_map.at(lowered_expr));
1991}
configt config
Definition config.cpp:25
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
std::size_t address_bits(const mp_integer &size)
ceil(log2(size))
mp_integer power(const mp_integer &base, const mp_integer &exponent)
A multi-precision implementation of the power operator.
Target numeric_cast_v(const mp_integer &arg)
Convert an mp_integer to integral type Target An invariant will fail if the conversion is not possibl...
std::optional< Target > numeric_cast(const exprt &arg)
Converts an expression to any integral type.
API to expression classes for bitvectors.
bool can_cast_type< integer_bitvector_typet >(const typet &type)
Check whether a reference to a typet is an integer_bitvector_typet.
bool can_cast_type< unsignedbv_typet >(const typet &type)
Check whether a reference to a typet is a unsignedbv_typet.
Expression classes for byte-level operators.
pointer_typet pointer_type(const typet &subtype)
Definition c_types.cpp:235
typet c_bool_type()
Definition c_types.cpp:100
Absolute value.
Definition std_expr.h:440
Operator to return the address of an object.
Thrown when an unexpected error occurs during the analysis (e.g., when the SAT solver returns an erro...
Boolean AND All operands must be boolean, and the result is always boolean.
Definition std_expr.h:2043
Expression to define a mapping from an argument (index) to elements.
Definition std_expr.h:3467
Array constructor from list of elements.
Definition std_expr.h:1570
Array constructor from single element.
Definition std_expr.h:1512
Arrays with given size.
Definition std_types.h:806
typet index_type() const
The type of the index expressions into any instance of this type.
Definition std_types.cpp:34
const typet & element_type() const
The type of the elements of the array.
Definition std_types.h:826
exprt & lhs()
Definition std_expr.h:679
exprt & rhs()
Definition std_expr.h:689
exprt & op0()
Definition expr.h:134
exprt & op1()
Definition expr.h:137
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition std_expr.h:784
Bit-wise AND Any number of operands that is greater or equal one.
Bit-wise negation of bit-vectors.
Bit-wise OR Any number of operands that is greater or equal one.
Base class of fixed-width bit-vector types.
std::size_t get_width() const
Bit-wise XOR Any number of operands that is greater or equal one.
The Boolean type.
Definition std_types.h:35
The byte swap expression.
Expression of type type extracted from some object op starting at position offset (given in number of...
Expression corresponding to op() where the bytes starting at position offset (given in number of byte...
The C/C++ Booleans.
Definition c_types.h:97
Concatenation of bit-vector operands.
A constant literal expression.
Definition std_expr.h:3007
bool is_null_pointer() const
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
Definition std_expr.cpp:170
The count leading zeros (counting the number of zero bits starting from the most-significant bit) exp...
The count trailing zeros (counting the number of zero bits starting from the least-significant bit) e...
Division.
Definition std_expr.h:1152
Equality.
Definition std_expr.h:1339
Boute's Euclidean definition of Modulo – to match SMT-LIB2.
Definition std_expr.h:1277
An exists expression.
Base class for all expressions.
Definition expr.h:57
void visit_pre(std::function< void(exprt &)>)
Definition expr.cpp:148
typet & type()
Return the type of the expression.
Definition expr.h:85
operandst & operands()
Definition expr.h:95
Extracts a single bit of a bit-vector operand.
Extracts a sub-range of a bit-vector operand.
Semantic type conversion from/to floating-point formats.
Fixed-width bit-vector with IEEE floating-point interpretation.
A forall expression.
IEEE-floating-point equality.
IEEE floating-point disequality.
IEEE floating-point operations These have two data operands (op0 and op1) and one rounding mode (op2)...
The trinary if-then-else operator.
Definition std_expr.h:2426
exprt & cond()
Definition std_expr.h:2443
exprt & false_case()
Definition std_expr.h:2463
exprt & true_case()
Definition std_expr.h:2453
Boolean implication.
Definition std_expr.h:2154
Array index operator.
Definition std_expr.h:1431
exprt & index()
Definition std_expr.h:1471
exprt & array()
Definition std_expr.h:1461
Unbounded, signed integers (mathematical integers, not bitvectors).
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition irep.cpp:482
const irep_idt & id() const
Definition irep.h:388
Evaluates to true if the operand is a pointer to a dynamic object.
Evaluates to true if the operand is finite.
Evaluates to true if the operand is infinite.
Evaluates to true if the operand is NaN.
Evaluates to true if the operand is a normal number.
A let expression.
Definition std_expr.h:3259
Extract member of struct or union.
Definition std_expr.h:2866
Binary minus.
Definition std_expr.h:1065
Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
Definition std_expr.h:1216
Binary multiplication Associativity is not specified.
Definition std_expr.h:1104
A base class for multi-ary expressions Associativity is not specified.
Definition std_expr.h:908
Expression to hold a nondeterministic choice.
Definition std_expr.h:295
const irep_idt & get_identifier() const
Definition std_expr.h:323
Boolean negation.
Definition std_expr.h:2388
Disequality.
Definition std_expr.h:1393
Expression for finding the size (in bytes) of the object a pointer points to.
Boolean OR All operands must be boolean, and the result is always boolean.
Definition std_expr.h:2193
The plus expression Associativity is not specified.
Definition std_expr.h:1006
A numerical identifier for the object a pointer points to.
The offset (in bytes) of a pointer relative to the object.
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
const typet & base_type() const
The type of the data what we point to.
The popcount (counting the number of bits set to 1) expression.
pointer_in_range (see pointer_in_range_exprt) with prophecy expressions to encode whether a pointer r...
A base class for a predicate that indicates that an address range is ok to read or write or both.
Bit-vector replication.
A base class for shift and rotate operators.
Sign of an expression Predicate is true if _op is negative, false otherwise.
Definition std_expr.h:612
static const smt_function_application_termt::factoryt< storet > store
static const smt_function_application_termt::factoryt< selectt > select
std::size_t bit_width() const
Definition smt_sorts.cpp:62
static const smt_function_application_termt::factoryt< ort > make_or
static const smt_function_application_termt::factoryt< unsigned_less_than_or_equalt > unsigned_less_than_or_equal
static const smt_function_application_termt::factoryt< signed_less_than_or_equalt > signed_less_than_or_equal
static const smt_function_application_termt::factoryt< addt > add
static const smt_function_application_termt::factoryt< arithmetic_shift_rightt > arithmetic_shift_right
static const smt_function_application_termt::factoryt< signed_greater_than_or_equalt > signed_greater_than_or_equal
static const smt_function_application_termt::factoryt< unsigned_greater_thant > unsigned_greater_than
static const smt_function_application_termt::factoryt< unsigned_remaindert > unsigned_remainder
static const smt_function_application_termt::factoryt< unsigned_greater_than_or_equalt > unsigned_greater_than_or_equal
static const smt_function_application_termt::factoryt< xort > make_xor
static const smt_function_application_termt::factoryt< nott > make_not
static const smt_function_application_termt::factoryt< shift_leftt > shift_left
static const smt_function_application_termt::factoryt< multiplyt > multiply
static smt_function_application_termt::factoryt< sign_extendt > sign_extend(std::size_t i)
static const smt_function_application_termt::factoryt< signed_less_thant > signed_less_than
static smt_function_application_termt::factoryt< zero_extendt > zero_extend(std::size_t i)
static smt_function_application_termt::factoryt< extractt > extract(std::size_t i, std::size_t j)
Makes a factory for extract function applications.
static const smt_function_application_termt::factoryt< signed_greater_thant > signed_greater_than
static const smt_function_application_termt::factoryt< logical_shift_rightt > logical_shift_right
static const smt_function_application_termt::factoryt< negatet > negate
Arithmetic negation in two's complement.
static const smt_function_application_termt::factoryt< concatt > concat
static const smt_function_application_termt::factoryt< unsigned_dividet > unsigned_divide
static const smt_function_application_termt::factoryt< unsigned_less_thant > unsigned_less_than
static const smt_function_application_termt::factoryt< signed_dividet > signed_divide
static const smt_function_application_termt::factoryt< signed_remaindert > signed_remainder
static const smt_function_application_termt::factoryt< subtractt > subtract
static const smt_function_application_termt::factoryt< andt > make_and
static const smt_function_application_termt::factoryt< distinctt > distinct
Makes applications of the function which returns true iff its two arguments are not identical.
static const smt_function_application_termt::factoryt< if_then_elset > if_then_else
static const smt_function_application_termt::factoryt< impliest > implies
static const smt_function_application_termt::factoryt< ort > make_or
static const smt_function_application_termt::factoryt< equalt > equal
static const smt_function_application_termt::factoryt< andt > make_and
static const smt_function_application_termt::factoryt< xort > make_xor
static const smt_function_application_termt::factoryt< nott > make_not
Stores identifiers in unescaped and unquoted form.
Definition smt_terms.h:93
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition irep.cpp:482
const sub_classt * cast() const &
void accept(smt_sort_const_downcast_visitort &) const
Definition smt_sorts.cpp:97
const smt_sortt & get_sort() const
Definition smt_terms.cpp:36
Struct constructor from list of elements.
Definition std_expr.h:1820
Expression to hold a symbol (variable).
Definition std_expr.h:132
void identifier(const irep_idt &identifier)
Definition std_expr.h:160
Semantic type conversion.
Definition std_expr.h:1995
The type of an expression, extends irept.
Definition type.h:29
const exprt & op() const
Definition std_expr.h:394
The unary minus expression.
Definition std_expr.h:477
The unary plus expression.
Definition std_expr.h:519
Union constructor from single element.
Definition std_expr.h:1724
Operator to update elements in structs and arrays.
Definition std_expr.h:2679
Vector constructor from list of elements.
Definition std_expr.h:1686
Operator to update elements in structs and arrays.
Definition std_expr.h:2520
exprt & new_value()
Definition std_expr.h:2550
exprt & where()
Definition std_expr.h:2540
exprt & old()
Definition std_expr.h:2530
Boolean XOR All operands must be boolean, and the result is always boolean.
Definition std_expr.h:2300
zero extension The operand is converted to the given type by either a) truncating if the new type is ...
void filtered_visit_post(const exprt &_expr, std::function< bool(const exprt &)> filter, std::function< void(const exprt &)> visitor)
Post order traversal where the children of a node are only visited if applying the filter function to...
exprt lower_address_of_array_index(exprt expr)
Lower the address_of(array[idx]) sub expressions in expr to idx + address_of(array),...
static smt_termt convert_bit_vector_cast(const smt_termt &from_term, const typet &from_type, const bitvector_typet &to_type)
static std::optional< smt_termt > try_relational_conversion(const exprt &expr, const sub_expression_mapt &converted)
static smt_termt most_significant_bit_is_set(const smt_termt &input)
Constructs a term which is true if the most significant bit of input is set.
static smt_termt convert_array_update_to_smt(const with_exprt &with, const sub_expression_mapt &converted)
static smt_termt make_bitvector_resize_cast(const smt_termt &from_term, const bitvector_typet &from_type, const bitvector_typet &to_type)
static std::function< std::function< smt_termt(smt_termt)>(std::size_t)> extension_for_type(const typet &type)
static smt_termt convert_multiary_operator_to_terms(const multi_ary_exprt &expr, const sub_expression_mapt &converted, const factoryt &factory)
Converts operator expressions with 2 or more operands to terms expressed as binary operator applicati...
std::unordered_map< exprt, smt_termt, irep_hash > sub_expression_mapt
Post order visitation is used in order to construct the the smt terms bottom upwards without using re...
static smt_termt make_not_zero(const smt_termt &input, const typet &source_type)
Makes a term which is true if input is not 0 / false.
static smt_termt convert_relational_to_smt(const binary_relation_exprt &binary_relation, const unsigned_factory_typet &unsigned_factory, const signed_factory_typet &signed_factory, const sub_expression_mapt &converted)
static smt_termt dispatch_expr_to_smt_conversion(const exprt &expr, const sub_expression_mapt &converted, const smt_object_mapt &object_map, const type_size_mapt &pointer_sizes, const smt_object_sizet::make_applicationt &call_object_size, const smt_is_dynamic_objectt::make_applicationt &apply_is_dynamic_object)
static smt_termt convert_to_smt_shift(const factoryt &factory, const shiftt &shift, const sub_expression_mapt &converted)
static smt_sortt convert_type_to_smt_sort(const bool_typet &type)
static smt_termt convert_c_bool_cast(const smt_termt &from_term, const typet &from_type, const bitvector_typet &to_type)
Returns a cast to C bool expressed in smt terms.
at_scope_exitt< functiont > at_scope_exit(functiont exit_function)
static bool operands_are_of_type(const exprt &expr)
Ensures that all operands of the argument expression have related types.
static smt_termt convert_expr_to_smt(const symbol_exprt &symbol_expr)
Templated functions to cast to specific exprt-derived classes.
auto type_checked_cast(TType &base) -> typename detail::expr_dynamic_cast_return_typet< T, TType >::type
Cast a reference to a generic typet to a specific derived class and checks that the type could be con...
Definition expr_cast.h:242
auto type_try_dynamic_cast(TType &base) -> typename detail::expr_try_dynamic_cast_return_typet< T, TType >::type
Try to cast a reference to a generic typet to a specific derived class.
Definition expr_cast.h:135
bool can_cast_type(const typet &base)
Check whether a reference to a generic typet is of a specific derived class.
auto expr_try_dynamic_cast(TExpr &base) -> typename detail::expr_try_dynamic_cast_return_typet< T, TExpr >::type
Try to cast a reference to a generic exprt to a specific derived class.
Definition expr_cast.h:81
API to expression classes for floating-point arithmetic.
std::string from_type(const namespacet &ns, const irep_idt &identifier, const typet &type)
API to expression classes for 'mathematical' expressions.
mini_bddt exists(const mini_bddt &u, const unsigned var)
Definition miniBDD.cpp:556
mp_integer bitwise_xor(const mp_integer &a, const mp_integer &b)
bitwise 'xor' of two nonnegative integers
Definition mp_arith.cpp:239
exprt make_invalid_pointer_expr()
Create the invalid pointer constant.
exprt find_object_base_expression(const address_of_exprt &address_of)
The model of addresses we use consists of a unique object identifier and an offset.
std::unordered_map< exprt, decision_procedure_objectt, irep_hash > smt_object_mapt
Mapping from an object's base expression to the set of information about it which we track.
API to expression classes for Pointers.
bool can_cast_type< pointer_typet >(const typet &type)
Check whether a reference to a typet is a pointer_typet.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
exprt pointer_offset(const exprt &pointer)
exprt object_size(const exprt &pointer)
exprt pointer_object(const exprt &p)
Various predicates over pointers in programs.
Ranges: pair of begin and end iterators, which can be initialized from containers,...
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition range.h:522
#define UNIMPLEMENTED_FEATURE(FEATURE)
Definition invariant.h:549
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
#define UNHANDLED_CASE
Definition invariant.h:559
#define POSTCONDITION(CONDITION)
Definition invariant.h:479
#define UNREACHABLE_BECAUSE(REASON)
Definition invariant.h:526
API to expression classes.
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:424
bool can_cast_type< code_typet >(const typet &type)
Check whether a reference to a typet is a code_typet.
Definition std_types.h:774
binary_relation_exprt less_than(exprt lhs, exprt rhs)
Definition string_expr.h:49
binary_relation_exprt greater_than(exprt lhs, exprt rhs)
Definition string_expr.h:26
at_scope_exitt(functiont exit_function)
smt_function_application_termt::factoryt< smt_command_functiont > make_applicationt
Function which makes applications of the smt function.
smt_function_application_termt::factoryt< smt_command_functiont > make_applicationt
Function which makes applications of the smt function.
void visit(const smt_array_sortt &) override
sort_based_cast_to_bit_vector_convertert(const smt_termt &from_term, const typet &from_type, const bitvector_typet &to_type)
void visit(const smt_bool_sortt &) override
void visit(const smt_bit_vector_sortt &) override
void visit(const smt_array_sortt &array_sort) override
void visit(const smt_bit_vector_sortt &bit_vector_sort) override
std::optional< smt_termt > result
void visit(const smt_bool_sortt &) override
sort_based_literal_convertert(const constant_exprt &input)
std::unordered_map< typet, smt_termt, irep_hash > type_size_mapt