CBMC
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 {
110 }
112 {
114 {
116 }
118 }
120 {
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
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(),
146}
147
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 {
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),
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 {
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
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
295 const sub_expression_mapt &converted)
296{
298 "Generation of SMT formula for struct construction expression: " +
299 struct_construction.pretty());
300}
301
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
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);
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
343{
344 if(constant_literal.is_null_pointer())
345 {
346 const size_t bit_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.
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());
364 sort.accept(converter);
365 return *converter.result;
366}
367
370 const sub_expression_mapt &converted)
371{
373 {
376 }
378 "Generation of SMT formula for concatenation expression: " +
379 concatenation.pretty());
380}
381
384 const sub_expression_mapt &converted)
385{
387 {
390 }
391 else
392 {
394 "Generation of SMT formula for bitwise and expression: " +
395 bitwise_and_expr.pretty());
396 }
397}
398
401 const sub_expression_mapt &converted)
402{
404 {
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{
452 if(can_cast_type<integer_bitvector_typet>(unary_minus.op().type()))
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
499
507
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
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
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>
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();
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 =
588 const auto rhs_type_is_pointer =
590 INVARIANT(
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 {
598 return unsigned_factory(lhs, rhs);
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,
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;
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),
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,
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
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.
725
727 {
729 converted.at(minus.lhs()), converted.at(minus.rhs()));
730 }
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(
737 "only pointers of the same object type can be subtracted.");
740 converted.at(minus.lhs()), converted.at(minus.rhs())),
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(
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
780 {
782 {
784 }
785 else
786 {
788 }
789 }
790 else
791 {
793 "Generation of SMT formula for divide expression: " + divide.pretty());
794 }
795}
796
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
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 =
819
820 const bool both_operands_unsigned =
823
825 {
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
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
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;
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 }
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 {
916 }
918 "Generation of SMT formula for address of expression: " +
919 address_of.pretty());
920}
921
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
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(
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();
971 {
972 return factory(
974 extension_for_type(shift.op1().type())(first_width - second_width)(
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)(
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 }
1002 {
1003 return convert_to_smt_shift(
1006 converted);
1007 }
1009 {
1010 return convert_to_smt_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());
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
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,
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();
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
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
1091 width - 1, width - object_bits)(converted.at(pointer_expr));
1092
1093 const auto &invalid_pointer = object_map.at(make_invalid_pointer_expr());
1094
1096 invalid_pointer.unique_id, config.bv_encoding.object_bits);
1097
1099}
1100
1103 const sub_expression_mapt &converted)
1104{
1106 "Generation of SMT formula for string constant expression: " +
1107 string_constant.pretty());
1108}
1109
1112 const sub_expression_mapt &converted)
1113{
1115 "Generation of SMT formula for extract bit expression: " +
1116 extract_bit.pretty());
1117}
1118
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.");
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
1139 const sub_expression_mapt &converted)
1140{
1142 "Generation of SMT formula for bit vector replication expression: " +
1143 replication.pretty());
1144}
1145
1148 const sub_expression_mapt &converted)
1149{
1151 "Generation of SMT formula for byte extract expression: " +
1152 byte_extraction.pretty());
1153}
1154
1157 const sub_expression_mapt &converted)
1158{
1160 "Generation of SMT formula for byte update expression: " +
1161 byte_update.pretty());
1162}
1163
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
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
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
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(
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;
1227}
1228
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 {
1240 }
1242 {
1243 // Overflow has occurred if the operands have the same sign and adding them
1244 // gives a result of the opposite sign.
1250 msb_left,
1252 }
1254 "Generation of SMT formula for plus overflow expression: " +
1255 plus_overflow.pretty());
1256}
1257
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());
1265 {
1267 }
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
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
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);
1306 smt_bit_vector_constant_termt{power(2, width), width * 2});
1307 }
1308 if(
1309 const auto signed_type =
1311 {
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 =
1320 smt_bit_vector_constant_termt{power(2, width - 1), width * 2});
1324 smt_bit_vector_constant_termt{power(2, width - 1), width * 2}));
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;
1348 width - 1, width - object_bits)(converted_expr);
1349 if(ext > 0)
1350 {
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 =
1370 if(width > offset_bits)
1371 {
1373 }
1374 return extract_op;
1375}
1376
1379 const sub_expression_mapt &converted)
1380{
1382 "Generation of SMT formula for shift left overflow expression: " +
1383 shl_overflow.pretty());
1384}
1385
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,
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
1462 const sub_expression_mapt &converted)
1463{
1465 "Generation of SMT formula for population count expression: " +
1466 population_count.pretty());
1467}
1468
1471 const sub_expression_mapt &converted)
1472{
1474 "Generation of SMT formula for count leading zeros expression: " +
1475 count_leading_zeros.pretty());
1476}
1477
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
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
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,
1521{
1522 if(const auto symbol = expr_try_dynamic_cast<symbol_exprt>(expr))
1523 {
1524 return convert_expr_to_smt(*symbol);
1525 }
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(
1536 {
1537 return convert_expr_to_smt(*float_cast, converted);
1538 }
1540 {
1541 return convert_expr_to_smt(*struct_construction, converted);
1542 }
1544 {
1545 return convert_expr_to_smt(*union_construction, converted);
1546 }
1548 {
1550 }
1551 if(
1553 {
1554 return convert_expr_to_smt(*concatenation, converted);
1555 }
1557 {
1558 return convert_expr_to_smt(*bitwise_and_expr, converted);
1559 }
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 }
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 }
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 }
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 }
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 }
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 }
1726 {
1727 return convert_expr_to_smt(*string_constant, converted);
1728 }
1730 {
1731 return convert_expr_to_smt(*extract_bit, converted);
1732 }
1734 {
1735 return convert_expr_to_smt(*extract_bits, converted);
1736 }
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 }
1748 {
1749 return convert_expr_to_smt(*byte_update, converted);
1750 }
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 }
1760 {
1761 return convert_expr_to_smt(*is_finite_expr, converted);
1762 }
1764 {
1765 return convert_expr_to_smt(*is_infinite_expr, converted);
1766 }
1768 {
1769 return convert_expr_to_smt(*is_normal_expr, converted);
1770 }
1771 if(
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(
1784 {
1785 return convert_expr_to_smt(*mult_overflow, converted);
1786 }
1788 {
1789 return convert_expr_to_smt(*shl_overflow, converted);
1790 }
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 {
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 }
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 {
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) {
1891 if(!address_of_expr)
1892 return;
1893 const auto array_index_expr =
1895 if(!array_index_expr)
1896 return;
1897 expr = plus_exprt{
1899 array_index_expr->array(),
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,
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(
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
1964 const auto lowered_expr = lower_address_of_array_index(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.
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,
1984 object_map,
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.
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.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
ait()
Definition ai.h:569
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.
struct configt::bv_encodingt bv_encoding
A constant literal expression.
Definition std_expr.h:3007
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
Boolean implication.
Definition std_expr.h:2154
Array index operator.
Definition std_expr.h:1431
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
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
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
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
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.
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)
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