CBMC
convert_expr_to_smt.cpp
Go to the documentation of this file.
1 // Author: Diffblue Ltd.
2 #include <util/arith_tools.h>
3 #include <util/bitvector_expr.h>
4 #include <util/byte_operators.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>
10 #include <util/mathematical_expr.h>
11 #include <util/pointer_expr.h>
13 #include <util/range.h>
14 #include <util/std_expr.h>
15 #include <util/string_constant.h>
16 
22 
23 #include <algorithm>
24 #include <functional>
25 #include <numeric>
26 #include <stack>
27 
37 using sub_expression_mapt = std::unordered_map<exprt, smt_termt, irep_hash>;
38 
51 template <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 
73 template <typename target_typet>
74 static 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 
88 {
89  return smt_bit_vector_sortt{type.get_width()};
90 }
91 
93 {
94  return smt_array_sortt{
97 }
98 
100 {
101  if(const auto bool_type = type_try_dynamic_cast<bool_typet>(type))
102  {
103  return convert_type_to_smt_sort(*bool_type);
104  }
105  if(const auto bitvector_type = type_try_dynamic_cast<bitvector_typet>(type))
106  {
107  return convert_type_to_smt_sort(*bitvector_type);
108  }
109  if(const auto array_type = type_try_dynamic_cast<array_typet>(type))
110  {
111  return convert_type_to_smt_sort(*array_type);
112  }
113  UNIMPLEMENTED_FEATURE("Generation of SMT formula for type: " + type.pretty());
114 }
115 
116 static smt_termt convert_expr_to_smt(const symbol_exprt &symbol_expr)
117 {
118  return smt_identifier_termt{symbol_expr.get_identifier(),
119  convert_type_to_smt_sort(symbol_expr.type())};
120 }
121 
123  const nondet_symbol_exprt &nondet_symbol,
124  const sub_expression_mapt &converted)
125 {
126  // A nondet_symbol is a reference to an unconstrained function. This function
127  // will already have been added as a dependency.
128  return smt_identifier_termt{
129  nondet_symbol.get_identifier(),
130  convert_type_to_smt_sort(nondet_symbol.type())};
131 }
132 
134 static smt_termt make_not_zero(const smt_termt &input, const typet &source_type)
135 {
136  if(input.get_sort().cast<smt_bool_sortt>())
137  return input;
138  if(const auto bit_vector_sort = input.get_sort().cast<smt_bit_vector_sortt>())
139  {
141  input, smt_bit_vector_constant_termt{0, *bit_vector_sort});
142  }
143  UNREACHABLE;
144 }
145 
148  const smt_termt &from_term,
149  const typet &from_type,
150  const bitvector_typet &to_type)
151 {
152  const std::size_t c_bool_width = to_type.get_width();
154  make_not_zero(from_term, from_type),
155  smt_bit_vector_constant_termt{1, c_bool_width},
156  smt_bit_vector_constant_termt{0, c_bool_width});
157 }
158 
159 static std::function<std::function<smt_termt(smt_termt)>(std::size_t)>
161 {
166  if(can_cast_type<bv_typet>(type))
170  UNREACHABLE;
171 }
172 
174  const smt_termt &from_term,
175  const bitvector_typet &from_type,
176  const bitvector_typet &to_type)
177 {
178  if(const auto to_fixedbv_type = type_try_dynamic_cast<fixedbv_typet>(to_type))
179  {
181  "Generation of SMT formula for type cast to fixed-point bitvector "
182  "type: " +
183  to_type.pretty());
184  }
185  if(const auto to_floatbv_type = type_try_dynamic_cast<floatbv_typet>(to_type))
186  {
188  "Generation of SMT formula for type cast to floating-point bitvector "
189  "type: " +
190  to_type.pretty());
191  }
192  const std::size_t from_width = from_type.get_width();
193  const std::size_t to_width = to_type.get_width();
194  if(to_width == from_width)
195  return from_term;
196  if(to_width < from_width)
197  return smt_bit_vector_theoryt::extract(to_width - 1, 0)(from_term);
198  const std::size_t extension_size = to_width - from_width;
199  return extension_for_type(from_type)(extension_size)(from_term);
200 }
201 
204 {
206  const typet &from_type;
208  std::optional<smt_termt> result;
209 
211  const smt_termt &from_term,
212  const typet &from_type,
213  const bitvector_typet &to_type)
215  {
216  }
217 
218  void visit(const smt_bool_sortt &) override
219  {
222  }
223 
224  void visit(const smt_bit_vector_sortt &) override
225  {
226  if(const auto bitvector = type_try_dynamic_cast<bitvector_typet>(from_type))
228  else
230  "Generation of SMT formula for type cast to bit vector from type: " +
231  from_type.pretty());
232  }
233 
234  void visit(const smt_array_sortt &) override
235  {
237  "Generation of SMT formula for type cast to bit vector from type: " +
238  from_type.pretty());
239  }
240 };
241 
243  const smt_termt &from_term,
244  const typet &from_type,
245  const bitvector_typet &to_type)
246 {
248  from_term, from_type, to_type};
249  from_term.get_sort().accept(converter);
250  POSTCONDITION(converter.result);
251  return *converter.result;
252 }
253 
255  const typecast_exprt &cast,
256  const sub_expression_mapt &converted)
257 {
258  const auto &from_term = converted.at(cast.op());
259  const typet &from_type = cast.op().type();
260  const typet &to_type = cast.type();
261  if(const auto bool_type = type_try_dynamic_cast<bool_typet>(to_type))
262  return make_not_zero(from_term, cast.op().type());
263  if(const auto c_bool_type = type_try_dynamic_cast<c_bool_typet>(to_type))
264  return convert_c_bool_cast(from_term, from_type, *c_bool_type);
265  if(const auto bit_vector = type_try_dynamic_cast<bitvector_typet>(to_type))
266  return convert_bit_vector_cast(from_term, from_type, *bit_vector);
268  "Generation of SMT formula for type cast expression: " + cast.pretty());
269 }
270 
272  const floatbv_typecast_exprt &float_cast,
273  const sub_expression_mapt &converted)
274 {
276  "Generation of SMT formula for floating point type cast expression: " +
277  float_cast.pretty());
278 }
279 
281  const struct_exprt &struct_construction,
282  const sub_expression_mapt &converted)
283 {
285  "Generation of SMT formula for struct construction expression: " +
286  struct_construction.pretty());
287 }
288 
290  const union_exprt &union_construction,
291  const sub_expression_mapt &converted)
292 {
294  "Generation of SMT formula for union construction expression: " +
295  union_construction.pretty());
296 }
297 
299 {
301  std::optional<smt_termt> result;
302 
304  : member_input{input}
305  {
306  }
307 
308  void visit(const smt_bool_sortt &) override
309  {
311  }
312 
313  void visit(const smt_bit_vector_sortt &bit_vector_sort) override
314  {
315  const auto &width = bit_vector_sort.bit_width();
316  // We get the value using a non-signed interpretation, as smt bit vector
317  // terms do not carry signedness.
318  const auto value = bvrep2integer(member_input.get_value(), width, false);
319  result = smt_bit_vector_constant_termt{value, bit_vector_sort};
320  }
321 
322  void visit(const smt_array_sortt &array_sort) override
323  {
325  "Conversion of array SMT literal " + array_sort.pretty());
326  }
327 };
328 
329 static smt_termt convert_expr_to_smt(const constant_exprt &constant_literal)
330 {
331  if(constant_literal.is_null_pointer())
332  {
333  const size_t bit_width =
334  type_checked_cast<pointer_typet>(constant_literal.type()).get_width();
335  // An address of 0 encodes an object identifier of 0 for the NULL object
336  // and an offset of 0 into the object.
337  const auto address = 0;
338  return smt_bit_vector_constant_termt{address, bit_width};
339  }
340  if(constant_literal.type() == integer_typet{})
341  {
342  // This is converting integer constants into bit vectors for use with
343  // bit vector based smt logics. As bit vector widths are not specified for
344  // non bit vector types, this chooses a width based on the minimum needed
345  // to hold the integer constant value.
346  const auto value = numeric_cast_v<mp_integer>(constant_literal);
347  return smt_bit_vector_constant_termt{value, address_bits(value + 1)};
348  }
349  const auto sort = convert_type_to_smt_sort(constant_literal.type());
350  sort_based_literal_convertert converter(constant_literal);
351  sort.accept(converter);
352  return *converter.result;
353 }
354 
356  const concatenation_exprt &concatenation,
357  const sub_expression_mapt &converted)
358 {
359  if(operands_are_of_type<bitvector_typet>(concatenation))
360  {
362  concatenation, converted, smt_bit_vector_theoryt::concat);
363  }
365  "Generation of SMT formula for concatenation expression: " +
366  concatenation.pretty());
367 }
368 
370  const bitand_exprt &bitwise_and_expr,
371  const sub_expression_mapt &converted)
372 {
373  if(operands_are_of_type<bitvector_typet>(bitwise_and_expr))
374  {
376  bitwise_and_expr, converted, smt_bit_vector_theoryt::make_and);
377  }
378  else
379  {
381  "Generation of SMT formula for bitwise and expression: " +
382  bitwise_and_expr.pretty());
383  }
384 }
385 
387  const bitor_exprt &bitwise_or_expr,
388  const sub_expression_mapt &converted)
389 {
390  if(operands_are_of_type<bitvector_typet>(bitwise_or_expr))
391  {
393  bitwise_or_expr, converted, smt_bit_vector_theoryt::make_or);
394  }
395  else
396  {
398  "Generation of SMT formula for bitwise or expression: " +
399  bitwise_or_expr.pretty());
400  }
401 }
402 
404  const bitxor_exprt &bitwise_xor,
405  const sub_expression_mapt &converted)
406 {
407  if(operands_are_of_type<bitvector_typet>(bitwise_xor))
408  {
411  }
412  else
413  {
415  "Generation of SMT formula for bitwise xor expression: " +
416  bitwise_xor.pretty());
417  }
418 }
419 
421  const bitnot_exprt &bitwise_not,
422  const sub_expression_mapt &converted)
423 {
424  if(can_cast_type<bitvector_typet>(bitwise_not.op().type()))
425  {
426  return smt_bit_vector_theoryt::make_not(converted.at(bitwise_not.op()));
427  }
428  else
429  {
431  "Generation of SMT formula for bitnot_exprt: " + bitwise_not.pretty());
432  }
433 }
434 
436  const unary_minus_exprt &unary_minus,
437  const sub_expression_mapt &converted)
438 {
439  if(can_cast_type<integer_bitvector_typet>(unary_minus.op().type()))
440  {
441  return smt_bit_vector_theoryt::negate(converted.at(unary_minus.op()));
442  }
443  else
444  {
446  "Generation of SMT formula for unary minus expression: " +
447  unary_minus.pretty());
448  }
449 }
450 
452  const unary_plus_exprt &unary_plus,
453  const sub_expression_mapt &converted)
454 {
456  "Generation of SMT formula for unary plus expression: " +
457  unary_plus.pretty());
458 }
459 
461  const sign_exprt &is_negative,
462  const sub_expression_mapt &converted)
463 {
465  "Generation of SMT formula for \"is negative\" expression: " +
466  is_negative.pretty());
467 }
468 
470  const if_exprt &if_expression,
471  const sub_expression_mapt &converted)
472 {
474  converted.at(if_expression.cond()),
475  converted.at(if_expression.true_case()),
476  converted.at(if_expression.false_case()));
477 }
478 
480  const and_exprt &and_expression,
481  const sub_expression_mapt &converted)
482 {
484  and_expression, converted, smt_core_theoryt::make_and);
485 }
486 
488  const or_exprt &or_expression,
489  const sub_expression_mapt &converted)
490 {
492  or_expression, converted, smt_core_theoryt::make_or);
493 }
494 
496  const xor_exprt &xor_expression,
497  const sub_expression_mapt &converted)
498 {
500  xor_expression, converted, smt_core_theoryt::make_xor);
501 }
502 
504  const implies_exprt &implies,
505  const sub_expression_mapt &converted)
506 {
508  converted.at(implies.op0()), converted.at(implies.op1()));
509 }
510 
512  const not_exprt &logical_not,
513  const sub_expression_mapt &converted)
514 {
515  return smt_core_theoryt::make_not(converted.at(logical_not.op()));
516 }
517 
519  const equal_exprt &equal,
520  const sub_expression_mapt &converted)
521 {
523  converted.at(equal.op0()), converted.at(equal.op1()));
524 }
525 
527  const notequal_exprt &not_equal,
528  const sub_expression_mapt &converted)
529 {
531  converted.at(not_equal.op0()), converted.at(not_equal.op1()));
532 }
533 
535  const ieee_float_equal_exprt &float_equal,
536  const sub_expression_mapt &converted)
537 {
539  "Generation of SMT formula for floating point equality expression: " +
540  float_equal.pretty());
541 }
542 
544  const ieee_float_notequal_exprt &float_not_equal,
545  const sub_expression_mapt &converted)
546 {
548  "Generation of SMT formula for floating point not equal expression: " +
549  float_not_equal.pretty());
550 }
551 
552 template <typename unsigned_factory_typet, typename signed_factory_typet>
554  const binary_relation_exprt &binary_relation,
555  const unsigned_factory_typet &unsigned_factory,
556  const signed_factory_typet &signed_factory,
557  const sub_expression_mapt &converted)
558 {
559  PRECONDITION(binary_relation.lhs().type() == binary_relation.rhs().type());
560  const auto &lhs = converted.at(binary_relation.lhs());
561  const auto &rhs = converted.at(binary_relation.rhs());
562  const typet operand_type = binary_relation.lhs().type();
563  if(can_cast_type<pointer_typet>(operand_type))
564  {
565  // The code here is operating under the assumption that the comparison
566  // operands have types for which the comparison makes sense.
567 
568  // We already know this is the case given that we have followed
569  // the if statement branch, but including the same check here
570  // for consistency (it's cheap).
571  const auto lhs_type_is_pointer =
572  can_cast_type<pointer_typet>(binary_relation.lhs().type());
573  const auto rhs_type_is_pointer =
574  can_cast_type<pointer_typet>(binary_relation.rhs().type());
575  INVARIANT(
576  lhs_type_is_pointer && rhs_type_is_pointer,
577  "pointer comparison requires that both operand types are pointers.");
578  return unsigned_factory(lhs, rhs);
579  }
580  else if(lhs.get_sort().cast<smt_bit_vector_sortt>())
581  {
582  if(can_cast_type<unsignedbv_typet>(operand_type))
583  return unsigned_factory(lhs, rhs);
584  if(can_cast_type<signedbv_typet>(operand_type))
585  return signed_factory(lhs, rhs);
586  }
587 
589  "Generation of SMT formula for relational expression: " +
590  binary_relation.pretty());
591 }
592 
593 static std::optional<smt_termt> try_relational_conversion(
594  const exprt &expr,
595  const sub_expression_mapt &converted)
596 {
597  if(const auto greater_than = expr_try_dynamic_cast<greater_than_exprt>(expr))
598  {
600  *greater_than,
603  converted);
604  }
605  if(
606  const auto greater_than_or_equal =
607  expr_try_dynamic_cast<greater_than_or_equal_exprt>(expr))
608  {
610  *greater_than_or_equal,
613  converted);
614  }
615  if(const auto less_than = expr_try_dynamic_cast<less_than_exprt>(expr))
616  {
618  *less_than,
621  converted);
622  }
623  if(
624  const auto less_than_or_equal =
625  expr_try_dynamic_cast<less_than_or_equal_exprt>(expr))
626  {
628  *less_than_or_equal,
631  converted);
632  }
633  return {};
634 }
635 
637  const plus_exprt &plus,
638  const sub_expression_mapt &converted,
639  const type_size_mapt &pointer_sizes)
640 {
641  if(std::all_of(
642  plus.operands().cbegin(), plus.operands().cend(), [](exprt operand) {
643  return can_cast_type<integer_bitvector_typet>(operand.type());
644  }))
645  {
647  plus, converted, smt_bit_vector_theoryt::add);
648  }
649  else if(can_cast_type<pointer_typet>(plus.type()))
650  {
651  INVARIANT(
652  plus.operands().size() == 2,
653  "We are only handling a binary version of plus when it has a pointer "
654  "operand");
655 
656  exprt pointer;
657  exprt scalar;
658  for(auto &operand : plus.operands())
659  {
660  if(can_cast_type<pointer_typet>(operand.type()))
661  {
662  pointer = operand;
663  }
664  else
665  {
666  scalar = operand;
667  }
668  }
669 
670  // We need to ensure that we follow this code path only if the expression
671  // our assumptions about the structure of the addition expression hold.
672  INVARIANT(
674  "An addition expression with both operands being pointers when they are "
675  "not dereferenced is malformed");
676 
678  *type_try_dynamic_cast<pointer_typet>(pointer.type());
679  const auto base_type = pointer_type.base_type();
680  const auto pointer_size = pointer_sizes.at(base_type);
681 
683  converted.at(pointer),
684  smt_bit_vector_theoryt::multiply(converted.at(scalar), pointer_size));
685  }
686  else
687  {
689  "Generation of SMT formula for plus expression: " + plus.pretty());
690  }
691 }
692 
694  const minus_exprt &minus,
695  const sub_expression_mapt &converted,
696  const type_size_mapt &pointer_sizes)
697 {
698  const bool both_operands_bitvector =
701 
702  const bool lhs_is_pointer = can_cast_type<pointer_typet>(minus.lhs().type());
703  const bool rhs_is_pointer = can_cast_type<pointer_typet>(minus.rhs().type());
704 
705  const bool both_operands_pointers = lhs_is_pointer && rhs_is_pointer;
706 
707  // We don't really handle this - we just compute this to fall
708  // into an if-else branch that gives proper error handling information.
709  const bool one_operand_pointer = lhs_is_pointer || rhs_is_pointer;
710 
711  if(both_operands_bitvector)
712  {
714  converted.at(minus.lhs()), converted.at(minus.rhs()));
715  }
716  else if(both_operands_pointers)
717  {
718  const auto lhs_base_type = to_pointer_type(minus.lhs().type()).base_type();
719  const auto rhs_base_type = to_pointer_type(minus.rhs().type()).base_type();
720  INVARIANT(
721  lhs_base_type == rhs_base_type,
722  "only pointers of the same object type can be subtracted.");
725  converted.at(minus.lhs()), converted.at(minus.rhs())),
726  pointer_sizes.at(lhs_base_type));
727  }
728  else if(one_operand_pointer)
729  {
730  // It's semantically void to have an expression `3 - a` where `a`
731  // is a pointer.
732  INVARIANT(
733  lhs_is_pointer,
734  "minus expressions of pointer and integer expect lhs to be the pointer");
735  const auto lhs_base_type = to_pointer_type(minus.lhs().type()).base_type();
736 
738  converted.at(minus.lhs()),
740  converted.at(minus.rhs()), pointer_sizes.at(lhs_base_type)));
741  }
742  else
743  {
745  "Generation of SMT formula for minus expression: " + minus.pretty());
746  }
747 }
748 
750  const div_exprt &divide,
751  const sub_expression_mapt &converted)
752 {
753  const smt_termt &lhs = converted.at(divide.lhs());
754  const smt_termt &rhs = converted.at(divide.rhs());
755 
756  const bool both_operands_bitvector =
759 
760  const bool both_operands_unsigned =
763 
764  if(both_operands_bitvector)
765  {
766  if(both_operands_unsigned)
767  {
769  }
770  else
771  {
772  return smt_bit_vector_theoryt::signed_divide(lhs, rhs);
773  }
774  }
775  else
776  {
778  "Generation of SMT formula for divide expression: " + divide.pretty());
779  }
780 }
781 
783  const ieee_float_op_exprt &float_operation,
784  const sub_expression_mapt &converted)
785 {
786  // This case includes the floating point plus, minus, division and
787  // multiplication operations.
789  "Generation of SMT formula for floating point operation expression: " +
790  float_operation.pretty());
791 }
792 
794  const mod_exprt &truncation_modulo,
795  const sub_expression_mapt &converted)
796 {
797  const smt_termt &lhs = converted.at(truncation_modulo.lhs());
798  const smt_termt &rhs = converted.at(truncation_modulo.rhs());
799 
800  const bool both_operands_bitvector =
801  can_cast_type<integer_bitvector_typet>(truncation_modulo.lhs().type()) &&
802  can_cast_type<integer_bitvector_typet>(truncation_modulo.rhs().type());
803 
804  const bool both_operands_unsigned =
805  can_cast_type<unsignedbv_typet>(truncation_modulo.lhs().type()) &&
806  can_cast_type<unsignedbv_typet>(truncation_modulo.rhs().type());
807 
808  if(both_operands_bitvector)
809  {
810  if(both_operands_unsigned)
811  {
813  }
814  else
815  {
817  }
818  }
819  else
820  {
822  "Generation of SMT formula for remainder (modulus) expression: " +
823  truncation_modulo.pretty());
824  }
825 }
826 
828  const euclidean_mod_exprt &euclidean_modulo,
829  const sub_expression_mapt &converted)
830 {
832  "Generation of SMT formula for euclidean modulo expression: " +
833  euclidean_modulo.pretty());
834 }
835 
837  const mult_exprt &multiply,
838  const sub_expression_mapt &converted)
839 {
840  if(std::all_of(
841  multiply.operands().cbegin(),
842  multiply.operands().cend(),
843  [](exprt operand) {
844  return can_cast_type<integer_bitvector_typet>(operand.type());
845  }))
846  {
848  multiply, converted, smt_bit_vector_theoryt::multiply);
849  }
850  else
851  {
853  "Generation of SMT formula for multiply expression: " +
854  multiply.pretty());
855  }
856 }
857 
866  const address_of_exprt &address_of,
867  const sub_expression_mapt &converted,
868  const smt_object_mapt &object_map)
869 {
870  const auto type = type_try_dynamic_cast<pointer_typet>(address_of.type());
871  INVARIANT(
872  type, "Result of the address_of operator should have pointer type.");
873  const auto base = find_object_base_expression(address_of);
874  const auto object = object_map.find(base);
875  INVARIANT(
876  object != object_map.end(),
877  "Objects should be tracked before converting their address to SMT terms");
878  const std::size_t object_id = object->second.unique_id;
879  const std::size_t object_bits = config.bv_encoding.object_bits;
880  const std::size_t max_objects = std::size_t(1) << object_bits;
881  if(object_id >= max_objects)
882  {
883  throw analysis_exceptiont{
884  "too many addressed objects: maximum number of objects is set to 2^n=" +
885  std::to_string(max_objects) + " (with n=" + std::to_string(object_bits) +
886  "); " +
887  "use the `--object-bits n` option to increase the maximum number"};
888  }
889  const smt_termt object_bit_vector =
890  smt_bit_vector_constant_termt{object_id, object_bits};
891  INVARIANT(
892  type->get_width() > object_bits,
893  "Pointer should be wider than object_bits in order to allow for offset "
894  "encoding.");
895  const size_t offset_bits = type->get_width() - object_bits;
896  if(
897  const auto symbol =
898  expr_try_dynamic_cast<symbol_exprt>(address_of.object()))
899  {
900  const smt_bit_vector_constant_termt offset{0, offset_bits};
901  return smt_bit_vector_theoryt::concat(object_bit_vector, offset);
902  }
904  "Generation of SMT formula for address of expression: " +
905  address_of.pretty());
906 }
907 
909  const array_of_exprt &array_of,
910  const sub_expression_mapt &converted)
911 {
912  // This function is unreachable as the `array_of_exprt` nodes are already
913  // fully converted by the incremental decision procedure functions
914  // (smt2_incremental_decision_proceduret::define_array_function).
916 }
917 
919  const array_comprehension_exprt &array_comprehension,
920  const sub_expression_mapt &converted)
921 {
923  "Generation of SMT formula for array comprehension expression: " +
924  array_comprehension.pretty());
925 }
926 
928  const index_exprt &index_of,
929  const sub_expression_mapt &converted)
930 {
931  const smt_termt &array = converted.at(index_of.array());
932  const smt_termt &index = converted.at(index_of.index());
933  return smt_array_theoryt::select(array, index);
934 }
935 
936 template <typename factoryt, typename shiftt>
938  const factoryt &factory,
939  const shiftt &shift,
940  const sub_expression_mapt &converted)
941 {
942  const smt_termt &first_operand = converted.at(shift.op0());
943  const smt_termt &second_operand = converted.at(shift.op1());
944  const auto first_bit_vector_sort =
945  first_operand.get_sort().cast<smt_bit_vector_sortt>();
946  const auto second_bit_vector_sort =
947  second_operand.get_sort().cast<smt_bit_vector_sortt>();
948  INVARIANT(
949  first_bit_vector_sort && second_bit_vector_sort,
950  "Shift expressions are expected to have bit vector operands.");
951  INVARIANT(
952  shift.type() == shift.op0().type(),
953  "Shift expression type must be equals to first operand type.");
954  const std::size_t first_width = first_bit_vector_sort->bit_width();
955  const std::size_t second_width = second_bit_vector_sort->bit_width();
956  if(first_width > second_width)
957  {
958  return factory(
959  first_operand,
960  extension_for_type(shift.op1().type())(first_width - second_width)(
961  second_operand));
962  }
963  else if(first_width < second_width)
964  {
965  const auto result = factory(
966  extension_for_type(shift.op0().type())(second_width - first_width)(
967  first_operand),
968  second_operand);
969  return smt_bit_vector_theoryt::extract(first_width - 1, 0)(result);
970  }
971  else
972  {
973  return factory(first_operand, second_operand);
974  }
975 }
976 
978  const shift_exprt &shift,
979  const sub_expression_mapt &converted)
980 {
981  // TODO: Dispatch for rotation expressions. A `shift_exprt` can be a rotation.
982  if(const auto left_shift = expr_try_dynamic_cast<shl_exprt>(shift))
983  {
984  return convert_to_smt_shift(
985  smt_bit_vector_theoryt::shift_left, *left_shift, converted);
986  }
987  if(const auto right_logical_shift = expr_try_dynamic_cast<lshr_exprt>(shift))
988  {
989  return convert_to_smt_shift(
991  *right_logical_shift,
992  converted);
993  }
994  if(const auto right_arith_shift = expr_try_dynamic_cast<ashr_exprt>(shift))
995  {
996  return convert_to_smt_shift(
998  *right_arith_shift,
999  converted);
1000  }
1002  "Generation of SMT formula for shift expression: " + shift.pretty());
1003 }
1004 
1006  const with_exprt &with,
1007  const sub_expression_mapt &converted)
1008 {
1009  smt_termt array = converted.at(with.old());
1010  for(auto it = ++with.operands().begin(); it != with.operands().end(); it += 2)
1011  {
1012  const smt_termt &index_term = converted.at(it[0]);
1013  const smt_termt &value_term = converted.at(it[1]);
1014  array = smt_array_theoryt::store(array, index_term, value_term);
1015  }
1016  return array;
1017 }
1018 
1020  const with_exprt &with,
1021  const sub_expression_mapt &converted)
1022 {
1023  if(can_cast_type<array_typet>(with.type()))
1024  return convert_array_update_to_smt(with, converted);
1025  // 'with' expression is also used to update struct fields, but for now we do
1026  // not support them, so we fail.
1028  "Generation of SMT formula for with expression: " + with.pretty());
1029 }
1030 
1032  const update_exprt &update,
1033  const sub_expression_mapt &converted)
1034 {
1036  "Generation of SMT formula for update expression: " + update.pretty());
1037 }
1038 
1040  const member_exprt &member_extraction,
1041  const sub_expression_mapt &converted)
1042 {
1044  "Generation of SMT formula for member extraction expression: " +
1045  member_extraction.pretty());
1046 }
1047 
1049  const is_dynamic_object_exprt &is_dynamic_object,
1050  const sub_expression_mapt &converted,
1051  const smt_is_dynamic_objectt::make_applicationt &apply_is_dynamic_object)
1052 {
1053  const smt_termt &pointer = converted.at(is_dynamic_object.address());
1054  const auto pointer_sort = pointer.get_sort().cast<smt_bit_vector_sortt>();
1055  INVARIANT(
1056  pointer_sort, "Pointers should be encoded as bit vector sorted terms.");
1057  const std::size_t pointer_width = pointer_sort->bit_width();
1058  return apply_is_dynamic_object(
1059  std::vector<smt_termt>{smt_bit_vector_theoryt::extract(
1060  pointer_width - 1,
1061  pointer_width - config.bv_encoding.object_bits)(pointer)});
1062 }
1063 
1065  const is_invalid_pointer_exprt &is_invalid_pointer,
1066  const smt_object_mapt &object_map,
1067  const sub_expression_mapt &converted)
1068 {
1069  const exprt &pointer_expr(to_unary_expr(is_invalid_pointer).op());
1070  const bitvector_typet *pointer_type =
1071  type_try_dynamic_cast<bitvector_typet>(pointer_expr.type());
1072  INVARIANT(pointer_type, "Pointer object should have a bitvector-based type.");
1073  const std::size_t object_bits = config.bv_encoding.object_bits;
1074  const std::size_t width = pointer_type->get_width();
1075  INVARIANT(
1076  width >= object_bits,
1077  "Width should be at least as big as the number of object bits.");
1078 
1079  const auto extract_op = smt_bit_vector_theoryt::extract(
1080  width - 1, width - object_bits)(converted.at(pointer_expr));
1081 
1082  const auto &invalid_pointer = object_map.at(make_invalid_pointer_expr());
1083 
1084  const smt_termt invalid_pointer_address = smt_bit_vector_constant_termt(
1085  invalid_pointer.unique_id, config.bv_encoding.object_bits);
1086 
1087  return smt_core_theoryt::equal(invalid_pointer_address, extract_op);
1088 }
1089 
1091  const string_constantt &string_constant,
1092  const sub_expression_mapt &converted)
1093 {
1095  "Generation of SMT formula for string constant expression: " +
1096  string_constant.pretty());
1097 }
1098 
1100  const extractbit_exprt &extract_bit,
1101  const sub_expression_mapt &converted)
1102 {
1104  "Generation of SMT formula for extract bit expression: " +
1105  extract_bit.pretty());
1106 }
1107 
1109  const extractbits_exprt &extract_bits,
1110  const sub_expression_mapt &converted)
1111 {
1112  const smt_termt &from = converted.at(extract_bits.src());
1113  const auto bit_vector_sort =
1115  INVARIANT(
1116  bit_vector_sort, "Extract can only be applied to bit vector terms.");
1117  const auto index_value = numeric_cast<std::size_t>(extract_bits.index());
1118  if(index_value)
1120  *index_value + bit_vector_sort->bit_width() - 1, *index_value)(from);
1122  "Generation of SMT formula for extract bits expression: " +
1123  extract_bits.pretty());
1124 }
1125 
1127  const replication_exprt &replication,
1128  const sub_expression_mapt &converted)
1129 {
1131  "Generation of SMT formula for bit vector replication expression: " +
1132  replication.pretty());
1133 }
1134 
1136  const byte_extract_exprt &byte_extraction,
1137  const sub_expression_mapt &converted)
1138 {
1140  "Generation of SMT formula for byte extract expression: " +
1141  byte_extraction.pretty());
1142 }
1143 
1145  const byte_update_exprt &byte_update,
1146  const sub_expression_mapt &converted)
1147 {
1149  "Generation of SMT formula for byte update expression: " +
1150  byte_update.pretty());
1151 }
1152 
1154  const abs_exprt &absolute_value_of,
1155  const sub_expression_mapt &converted)
1156 {
1158  "Generation of SMT formula for absolute value of expression: " +
1159  absolute_value_of.pretty());
1160 }
1161 
1163  const isnan_exprt &is_nan_expr,
1164  const sub_expression_mapt &converted)
1165 {
1167  "Generation of SMT formula for is not a number expression: " +
1168  is_nan_expr.pretty());
1169 }
1170 
1172  const isfinite_exprt &is_finite_expr,
1173  const sub_expression_mapt &converted)
1174 {
1176  "Generation of SMT formula for is finite expression: " +
1177  is_finite_expr.pretty());
1178 }
1179 
1181  const isinf_exprt &is_infinite_expr,
1182  const sub_expression_mapt &converted)
1183 {
1185  "Generation of SMT formula for is infinite expression: " +
1186  is_infinite_expr.pretty());
1187 }
1188 
1190  const isnormal_exprt &is_normal_expr,
1191  const sub_expression_mapt &converted)
1192 {
1194  "Generation of SMT formula for is infinite expression: " +
1195  is_normal_expr.pretty());
1196 }
1197 
1202 {
1203  const auto bit_vector_sort = input.get_sort().cast<smt_bit_vector_sortt>();
1204  INVARIANT(
1205  bit_vector_sort,
1206  "Most significant bit can only be extracted from bit vector terms.");
1207  const size_t most_significant_bit_index = bit_vector_sort->bit_width() - 1;
1208  const auto extract_most_significant_bit = smt_bit_vector_theoryt::extract(
1209  most_significant_bit_index, most_significant_bit_index);
1210  return smt_core_theoryt::equal(
1211  extract_most_significant_bit(input), smt_bit_vector_constant_termt{1, 1});
1212 }
1213 
1215  const plus_overflow_exprt &plus_overflow,
1216  const sub_expression_mapt &converted)
1217 {
1218  const smt_termt &left = converted.at(plus_overflow.lhs());
1219  const smt_termt &right = converted.at(plus_overflow.rhs());
1220  if(operands_are_of_type<unsignedbv_typet>(plus_overflow))
1221  {
1222  const auto add_carry_bit = smt_bit_vector_theoryt::zero_extend(1);
1224  smt_bit_vector_theoryt::add(add_carry_bit(left), add_carry_bit(right)));
1225  }
1226  if(operands_are_of_type<signedbv_typet>(plus_overflow))
1227  {
1228  // Overflow has occurred if the operands have the same sign and adding them
1229  // gives a result of the opposite sign.
1230  const smt_termt msb_left = most_significant_bit_is_set(left);
1231  const smt_termt msb_right = most_significant_bit_is_set(right);
1233  smt_core_theoryt::equal(msb_left, msb_right),
1235  msb_left,
1237  }
1239  "Generation of SMT formula for plus overflow expression: " +
1240  plus_overflow.pretty());
1241 }
1242 
1244  const minus_overflow_exprt &minus_overflow,
1245  const sub_expression_mapt &converted)
1246 {
1247  const smt_termt &left = converted.at(minus_overflow.lhs());
1248  const smt_termt &right = converted.at(minus_overflow.rhs());
1249  if(operands_are_of_type<unsignedbv_typet>(minus_overflow))
1250  {
1251  return smt_bit_vector_theoryt::unsigned_less_than(left, right);
1252  }
1253  if(operands_are_of_type<signedbv_typet>(minus_overflow))
1254  {
1255  // Overflow has occurred if the operands have the opposing signs and
1256  // subtracting them gives a result having the same signedness as the
1257  // right-hand operand. For example the following would be overflow for cases
1258  // for 8 bit wide bit vectors -
1259  // -128 - 1 == 127
1260  // 127 - (-1) == -128
1261  const smt_termt msb_left = most_significant_bit_is_set(left);
1262  const smt_termt msb_right = most_significant_bit_is_set(right);
1264  smt_core_theoryt::distinct(msb_left, msb_right),
1266  msb_right,
1268  smt_bit_vector_theoryt::subtract(left, right))));
1269  }
1271  "Generation of SMT formula for minus overflow expression: " +
1272  minus_overflow.pretty());
1273 }
1274 
1276  const mult_overflow_exprt &mult_overflow,
1277  const sub_expression_mapt &converted)
1278 {
1279  PRECONDITION(mult_overflow.lhs().type() == mult_overflow.rhs().type());
1280  const auto &operand_type = mult_overflow.lhs().type();
1281  const smt_termt &left = converted.at(mult_overflow.lhs());
1282  const smt_termt &right = converted.at(mult_overflow.rhs());
1283  if(
1284  const auto unsigned_type =
1285  type_try_dynamic_cast<unsignedbv_typet>(operand_type))
1286  {
1287  const std::size_t width = unsigned_type->get_width();
1288  const auto extend = smt_bit_vector_theoryt::zero_extend(width);
1290  smt_bit_vector_theoryt::multiply(extend(left), extend(right)),
1291  smt_bit_vector_constant_termt{power(2, width), width * 2});
1292  }
1293  if(
1294  const auto signed_type =
1295  type_try_dynamic_cast<signedbv_typet>(operand_type))
1296  {
1297  const smt_termt msb_left = most_significant_bit_is_set(left);
1298  const smt_termt msb_right = most_significant_bit_is_set(right);
1299  const std::size_t width = signed_type->get_width();
1300  const auto extend = smt_bit_vector_theoryt::sign_extend(width);
1301  const auto multiplication =
1302  smt_bit_vector_theoryt::multiply(extend(left), extend(right));
1304  multiplication,
1305  smt_bit_vector_constant_termt{power(2, width - 1), width * 2});
1306  const auto too_small = smt_bit_vector_theoryt::signed_less_than(
1307  multiplication,
1309  smt_bit_vector_constant_termt{power(2, width - 1), width * 2}));
1311  smt_core_theoryt::equal(msb_left, msb_right), too_large, too_small);
1312  }
1314  "Generation of SMT formula for multiply overflow expression: " +
1315  mult_overflow.pretty());
1316 }
1317 
1320  const sub_expression_mapt &converted)
1321 {
1322  const auto type =
1323  type_try_dynamic_cast<bitvector_typet>(pointer_object.type());
1324  INVARIANT(type, "Pointer object should have a bitvector-based type.");
1325  const auto converted_expr = converted.at(pointer_object.pointer());
1326  const std::size_t width = type->get_width();
1327  const std::size_t object_bits = config.bv_encoding.object_bits;
1328  INVARIANT(
1329  width >= object_bits,
1330  "Width should be at least as big as the number of object bits.");
1331  const std::size_t ext = width - object_bits;
1332  const auto extract_op = smt_bit_vector_theoryt::extract(
1333  width - 1, width - object_bits)(converted_expr);
1334  if(ext > 0)
1335  {
1336  return smt_bit_vector_theoryt::zero_extend(ext)(extract_op);
1337  }
1338  return extract_op;
1339 }
1340 
1343  const sub_expression_mapt &converted)
1344 {
1345  const auto type =
1346  type_try_dynamic_cast<bitvector_typet>(pointer_offset.type());
1347  INVARIANT(type, "Pointer offset should have a bitvector-based type.");
1348  const auto converted_expr = converted.at(pointer_offset.pointer());
1349  const std::size_t width = type->get_width();
1350  std::size_t offset_bits = width - config.bv_encoding.object_bits;
1351  if(offset_bits > width)
1352  offset_bits = width;
1353  const auto extract_op =
1354  smt_bit_vector_theoryt::extract(offset_bits - 1, 0)(converted_expr);
1355  if(width > offset_bits)
1356  {
1357  return smt_bit_vector_theoryt::sign_extend(width - offset_bits)(extract_op);
1358  }
1359  return extract_op;
1360 }
1361 
1363  const shl_overflow_exprt &shl_overflow,
1364  const sub_expression_mapt &converted)
1365 {
1367  "Generation of SMT formula for shift left overflow expression: " +
1368  shl_overflow.pretty());
1369 }
1370 
1372  const array_exprt &array_construction,
1373  const sub_expression_mapt &converted)
1374 {
1375  // This function is unreachable as the `array_exprt` nodes are already fully
1376  // converted by the incremental decision procedure functions
1377  // (smt2_incremental_decision_proceduret::define_array_function).
1379 }
1380 
1382  const literal_exprt &literal,
1383  const sub_expression_mapt &converted)
1384 {
1386  "Generation of SMT formula for literal expression: " + literal.pretty());
1387 }
1388 
1390  const forall_exprt &for_all,
1391  const sub_expression_mapt &converted)
1392 {
1394  "Generation of SMT formula for for all expression: " + for_all.pretty());
1395 }
1396 
1398  const exists_exprt &exists,
1399  const sub_expression_mapt &converted)
1400 {
1402  "Generation of SMT formula for exists expression: " + exists.pretty());
1403 }
1404 
1406  const vector_exprt &vector,
1407  const sub_expression_mapt &converted)
1408 {
1410  "Generation of SMT formula for vector expression: " + vector.pretty());
1411 }
1412 
1415  const sub_expression_mapt &converted,
1416  const smt_object_sizet::make_applicationt &call_object_size)
1417 {
1418  const smt_termt &pointer = converted.at(object_size.pointer());
1419  const auto pointer_sort = pointer.get_sort().cast<smt_bit_vector_sortt>();
1420  INVARIANT(
1421  pointer_sort, "Pointers should be encoded as bit vector sorted terms.");
1422  const std::size_t pointer_width = pointer_sort->bit_width();
1423  return call_object_size(
1424  std::vector<smt_termt>{smt_bit_vector_theoryt::extract(
1425  pointer_width - 1,
1426  pointer_width - config.bv_encoding.object_bits)(pointer)});
1427 }
1428 
1429 static smt_termt
1431 {
1433  "Generation of SMT formula for let expression: " + let.pretty());
1434 }
1435 
1437  const bswap_exprt &byte_swap,
1438  const sub_expression_mapt &converted)
1439 {
1441  "Generation of SMT formula for byte swap expression: " +
1442  byte_swap.pretty());
1443 }
1444 
1446  const popcount_exprt &population_count,
1447  const sub_expression_mapt &converted)
1448 {
1450  "Generation of SMT formula for population count expression: " +
1451  population_count.pretty());
1452 }
1453 
1455  const count_leading_zeros_exprt &count_leading_zeros,
1456  const sub_expression_mapt &converted)
1457 {
1459  "Generation of SMT formula for count leading zeros expression: " +
1460  count_leading_zeros.pretty());
1461 }
1462 
1464  const count_trailing_zeros_exprt &count_trailing_zeros,
1465  const sub_expression_mapt &converted)
1466 {
1468  "Generation of SMT formula for count trailing zeros expression: " +
1469  count_trailing_zeros.pretty());
1470 }
1471 
1473  const zero_extend_exprt &zero_extend,
1474  const sub_expression_mapt &converted)
1475 {
1477  "zero_extend expression should have been lowered by the decision "
1478  "procedure before conversion to smt terms");
1479 }
1480 
1482  const prophecy_r_or_w_ok_exprt &prophecy_r_or_w_ok,
1483  const sub_expression_mapt &converted)
1484 {
1486  "prophecy_r_or_w_ok expression should have been lowered by the decision "
1487  "procedure before conversion to smt terms");
1488 }
1489 
1491  const prophecy_pointer_in_range_exprt &prophecy_pointer_in_range,
1492  const sub_expression_mapt &converted)
1493 {
1495  "prophecy_pointer_in_range expression should have been lowered by the "
1496  "decision procedure before conversion to smt terms");
1497 }
1498 
1500  const exprt &expr,
1501  const sub_expression_mapt &converted,
1502  const smt_object_mapt &object_map,
1503  const type_size_mapt &pointer_sizes,
1504  const smt_object_sizet::make_applicationt &call_object_size,
1505  const smt_is_dynamic_objectt::make_applicationt &apply_is_dynamic_object)
1506 {
1507  if(const auto symbol = expr_try_dynamic_cast<symbol_exprt>(expr))
1508  {
1509  return convert_expr_to_smt(*symbol);
1510  }
1511  if(const auto nondet = expr_try_dynamic_cast<nondet_symbol_exprt>(expr))
1512  {
1513  return convert_expr_to_smt(*nondet, converted);
1514  }
1515  if(const auto cast = expr_try_dynamic_cast<typecast_exprt>(expr))
1516  {
1517  return convert_expr_to_smt(*cast, converted);
1518  }
1519  if(
1520  const auto float_cast = expr_try_dynamic_cast<floatbv_typecast_exprt>(expr))
1521  {
1522  return convert_expr_to_smt(*float_cast, converted);
1523  }
1524  if(const auto struct_construction = expr_try_dynamic_cast<struct_exprt>(expr))
1525  {
1526  return convert_expr_to_smt(*struct_construction, converted);
1527  }
1528  if(const auto union_construction = expr_try_dynamic_cast<union_exprt>(expr))
1529  {
1530  return convert_expr_to_smt(*union_construction, converted);
1531  }
1532  if(const auto constant_literal = expr_try_dynamic_cast<constant_exprt>(expr))
1533  {
1534  return convert_expr_to_smt(*constant_literal);
1535  }
1536  if(
1537  const auto concatenation = expr_try_dynamic_cast<concatenation_exprt>(expr))
1538  {
1539  return convert_expr_to_smt(*concatenation, converted);
1540  }
1541  if(const auto bitwise_and_expr = expr_try_dynamic_cast<bitand_exprt>(expr))
1542  {
1543  return convert_expr_to_smt(*bitwise_and_expr, converted);
1544  }
1545  if(const auto bitwise_or_expr = expr_try_dynamic_cast<bitor_exprt>(expr))
1546  {
1547  return convert_expr_to_smt(*bitwise_or_expr, converted);
1548  }
1549  if(const auto bitwise_xor = expr_try_dynamic_cast<bitxor_exprt>(expr))
1550  {
1551  return convert_expr_to_smt(*bitwise_xor, converted);
1552  }
1553  if(const auto bitwise_not = expr_try_dynamic_cast<bitnot_exprt>(expr))
1554  {
1555  return convert_expr_to_smt(*bitwise_not, converted);
1556  }
1557  if(const auto unary_minus = expr_try_dynamic_cast<unary_minus_exprt>(expr))
1558  {
1559  return convert_expr_to_smt(*unary_minus, converted);
1560  }
1561  if(const auto unary_plus = expr_try_dynamic_cast<unary_plus_exprt>(expr))
1562  {
1563  return convert_expr_to_smt(*unary_plus, converted);
1564  }
1565  if(const auto is_negative = expr_try_dynamic_cast<sign_exprt>(expr))
1566  {
1567  return convert_expr_to_smt(*is_negative, converted);
1568  }
1569  if(const auto if_expression = expr_try_dynamic_cast<if_exprt>(expr))
1570  {
1571  return convert_expr_to_smt(*if_expression, converted);
1572  }
1573  if(const auto and_expression = expr_try_dynamic_cast<and_exprt>(expr))
1574  {
1575  return convert_expr_to_smt(*and_expression, converted);
1576  }
1577  if(const auto or_expression = expr_try_dynamic_cast<or_exprt>(expr))
1578  {
1579  return convert_expr_to_smt(*or_expression, converted);
1580  }
1581  if(const auto xor_expression = expr_try_dynamic_cast<xor_exprt>(expr))
1582  {
1583  return convert_expr_to_smt(*xor_expression, converted);
1584  }
1585  if(const auto implies = expr_try_dynamic_cast<implies_exprt>(expr))
1586  {
1587  return convert_expr_to_smt(*implies, converted);
1588  }
1589  if(const auto logical_not = expr_try_dynamic_cast<not_exprt>(expr))
1590  {
1591  return convert_expr_to_smt(*logical_not, converted);
1592  }
1593  if(const auto equal = expr_try_dynamic_cast<equal_exprt>(expr))
1594  {
1595  return convert_expr_to_smt(*equal, converted);
1596  }
1597  if(const auto not_equal = expr_try_dynamic_cast<notequal_exprt>(expr))
1598  {
1599  return convert_expr_to_smt(*not_equal, converted);
1600  }
1601  if(
1602  const auto float_equal =
1603  expr_try_dynamic_cast<ieee_float_equal_exprt>(expr))
1604  {
1605  return convert_expr_to_smt(*float_equal, converted);
1606  }
1607  if(
1608  const auto float_not_equal =
1609  expr_try_dynamic_cast<ieee_float_notequal_exprt>(expr))
1610  {
1611  return convert_expr_to_smt(*float_not_equal, converted);
1612  }
1613  if(
1614  const auto converted_relational =
1615  try_relational_conversion(expr, converted))
1616  {
1617  return *converted_relational;
1618  }
1619  if(const auto plus = expr_try_dynamic_cast<plus_exprt>(expr))
1620  {
1621  return convert_expr_to_smt(*plus, converted, pointer_sizes);
1622  }
1623  if(const auto minus = expr_try_dynamic_cast<minus_exprt>(expr))
1624  {
1625  return convert_expr_to_smt(*minus, converted, pointer_sizes);
1626  }
1627  if(const auto divide = expr_try_dynamic_cast<div_exprt>(expr))
1628  {
1629  return convert_expr_to_smt(*divide, converted);
1630  }
1631  if(
1632  const auto float_operation =
1633  expr_try_dynamic_cast<ieee_float_op_exprt>(expr))
1634  {
1635  return convert_expr_to_smt(*float_operation, converted);
1636  }
1637  if(const auto truncation_modulo = expr_try_dynamic_cast<mod_exprt>(expr))
1638  {
1639  return convert_expr_to_smt(*truncation_modulo, converted);
1640  }
1641  if(
1642  const auto euclidean_modulo =
1643  expr_try_dynamic_cast<euclidean_mod_exprt>(expr))
1644  {
1645  return convert_expr_to_smt(*euclidean_modulo, converted);
1646  }
1647  if(const auto multiply = expr_try_dynamic_cast<mult_exprt>(expr))
1648  {
1649  return convert_expr_to_smt(*multiply, converted);
1650  }
1651 #if 0
1652  else if(expr.id() == ID_floatbv_rem)
1653  {
1654  convert_floatbv_rem(to_binary_expr(expr));
1655  }
1656 #endif
1657  if(const auto address_of = expr_try_dynamic_cast<address_of_exprt>(expr))
1658  {
1659  return convert_expr_to_smt(*address_of, converted, object_map);
1660  }
1661  if(const auto array_of = expr_try_dynamic_cast<array_of_exprt>(expr))
1662  {
1663  return convert_expr_to_smt(*array_of, converted);
1664  }
1665  if(
1666  const auto array_comprehension =
1667  expr_try_dynamic_cast<array_comprehension_exprt>(expr))
1668  {
1669  return convert_expr_to_smt(*array_comprehension, converted);
1670  }
1671  if(const auto index = expr_try_dynamic_cast<index_exprt>(expr))
1672  {
1673  return convert_expr_to_smt(*index, converted);
1674  }
1675  if(const auto shift = expr_try_dynamic_cast<shift_exprt>(expr))
1676  {
1677  return convert_expr_to_smt(*shift, converted);
1678  }
1679  if(const auto with = expr_try_dynamic_cast<with_exprt>(expr))
1680  {
1681  return convert_expr_to_smt(*with, converted);
1682  }
1683  if(const auto update = expr_try_dynamic_cast<update_exprt>(expr))
1684  {
1685  return convert_expr_to_smt(*update, converted);
1686  }
1687  if(const auto member_extraction = expr_try_dynamic_cast<member_exprt>(expr))
1688  {
1689  return convert_expr_to_smt(*member_extraction, converted);
1690  }
1691  else if(
1692  const auto pointer_offset =
1693  expr_try_dynamic_cast<pointer_offset_exprt>(expr))
1694  {
1695  return convert_expr_to_smt(*pointer_offset, converted);
1696  }
1697  else if(
1698  const auto pointer_object =
1699  expr_try_dynamic_cast<pointer_object_exprt>(expr))
1700  {
1701  return convert_expr_to_smt(*pointer_object, converted);
1702  }
1703  if(
1704  const auto is_dynamic_object =
1705  expr_try_dynamic_cast<is_dynamic_object_exprt>(expr))
1706  {
1707  return convert_expr_to_smt(
1708  *is_dynamic_object, converted, apply_is_dynamic_object);
1709  }
1710  if(
1711  const auto is_invalid_pointer =
1712  expr_try_dynamic_cast<is_invalid_pointer_exprt>(expr))
1713  {
1714  return convert_expr_to_smt(*is_invalid_pointer, object_map, converted);
1715  }
1716  if(const auto string_constant = expr_try_dynamic_cast<string_constantt>(expr))
1717  {
1718  return convert_expr_to_smt(*string_constant, converted);
1719  }
1720  if(const auto extract_bit = expr_try_dynamic_cast<extractbit_exprt>(expr))
1721  {
1722  return convert_expr_to_smt(*extract_bit, converted);
1723  }
1724  if(const auto extract_bits = expr_try_dynamic_cast<extractbits_exprt>(expr))
1725  {
1726  return convert_expr_to_smt(*extract_bits, converted);
1727  }
1728  if(const auto replication = expr_try_dynamic_cast<replication_exprt>(expr))
1729  {
1730  return convert_expr_to_smt(*replication, converted);
1731  }
1732  if(
1733  const auto byte_extraction =
1734  expr_try_dynamic_cast<byte_extract_exprt>(expr))
1735  {
1736  return convert_expr_to_smt(*byte_extraction, converted);
1737  }
1738  if(const auto byte_update = expr_try_dynamic_cast<byte_update_exprt>(expr))
1739  {
1740  return convert_expr_to_smt(*byte_update, converted);
1741  }
1742  if(const auto absolute_value_of = expr_try_dynamic_cast<abs_exprt>(expr))
1743  {
1744  return convert_expr_to_smt(*absolute_value_of, converted);
1745  }
1746  if(const auto is_nan_expr = expr_try_dynamic_cast<isnan_exprt>(expr))
1747  {
1748  return convert_expr_to_smt(*is_nan_expr, converted);
1749  }
1750  if(const auto is_finite_expr = expr_try_dynamic_cast<isfinite_exprt>(expr))
1751  {
1752  return convert_expr_to_smt(*is_finite_expr, converted);
1753  }
1754  if(const auto is_infinite_expr = expr_try_dynamic_cast<isinf_exprt>(expr))
1755  {
1756  return convert_expr_to_smt(*is_infinite_expr, converted);
1757  }
1758  if(const auto is_normal_expr = expr_try_dynamic_cast<isnormal_exprt>(expr))
1759  {
1760  return convert_expr_to_smt(*is_normal_expr, converted);
1761  }
1762  if(
1763  const auto plus_overflow = expr_try_dynamic_cast<plus_overflow_exprt>(expr))
1764  {
1765  return convert_expr_to_smt(*plus_overflow, converted);
1766  }
1767  if(
1768  const auto minus_overflow =
1769  expr_try_dynamic_cast<minus_overflow_exprt>(expr))
1770  {
1771  return convert_expr_to_smt(*minus_overflow, converted);
1772  }
1773  if(
1774  const auto mult_overflow = expr_try_dynamic_cast<mult_overflow_exprt>(expr))
1775  {
1776  return convert_expr_to_smt(*mult_overflow, converted);
1777  }
1778  if(const auto shl_overflow = expr_try_dynamic_cast<shl_overflow_exprt>(expr))
1779  {
1780  return convert_expr_to_smt(*shl_overflow, converted);
1781  }
1782  if(const auto array_construction = expr_try_dynamic_cast<array_exprt>(expr))
1783  {
1784  return convert_expr_to_smt(*array_construction, converted);
1785  }
1786  if(const auto literal = expr_try_dynamic_cast<literal_exprt>(expr))
1787  {
1788  return convert_expr_to_smt(*literal, converted);
1789  }
1790  if(const auto for_all = expr_try_dynamic_cast<forall_exprt>(expr))
1791  {
1792  return convert_expr_to_smt(*for_all, converted);
1793  }
1794  if(const auto exists = expr_try_dynamic_cast<exists_exprt>(expr))
1795  {
1796  return convert_expr_to_smt(*exists, converted);
1797  }
1798  if(const auto vector = expr_try_dynamic_cast<vector_exprt>(expr))
1799  {
1800  return convert_expr_to_smt(*vector, converted);
1801  }
1802  if(const auto object_size = expr_try_dynamic_cast<object_size_exprt>(expr))
1803  {
1804  return convert_expr_to_smt(*object_size, converted, call_object_size);
1805  }
1806  if(const auto let = expr_try_dynamic_cast<let_exprt>(expr))
1807  {
1808  return convert_expr_to_smt(*let, converted);
1809  }
1810  INVARIANT(
1811  expr.id() != ID_constraint_select_one,
1812  "constraint_select_one is not expected in smt conversion: " +
1813  expr.pretty());
1814  if(const auto byte_swap = expr_try_dynamic_cast<bswap_exprt>(expr))
1815  {
1816  return convert_expr_to_smt(*byte_swap, converted);
1817  }
1818  if(const auto population_count = expr_try_dynamic_cast<popcount_exprt>(expr))
1819  {
1820  return convert_expr_to_smt(*population_count, converted);
1821  }
1822  if(
1823  const auto count_leading_zeros =
1824  expr_try_dynamic_cast<count_leading_zeros_exprt>(expr))
1825  {
1826  return convert_expr_to_smt(*count_leading_zeros, converted);
1827  }
1828  if(
1829  const auto count_trailing_zeros =
1830  expr_try_dynamic_cast<count_trailing_zeros_exprt>(expr))
1831  {
1832  return convert_expr_to_smt(*count_trailing_zeros, converted);
1833  }
1834  if(const auto zero_extend = expr_try_dynamic_cast<zero_extend_exprt>(expr))
1835  {
1836  return convert_expr_to_smt(*zero_extend, converted);
1837  }
1838  if(
1839  const auto prophecy_r_or_w_ok =
1840  expr_try_dynamic_cast<prophecy_r_or_w_ok_exprt>(expr))
1841  {
1842  return convert_expr_to_smt(*prophecy_r_or_w_ok, converted);
1843  }
1844  if(
1845  const auto prophecy_pointer_in_range =
1846  expr_try_dynamic_cast<prophecy_pointer_in_range_exprt>(expr))
1847  {
1848  return convert_expr_to_smt(*prophecy_pointer_in_range, converted);
1849  }
1850 
1852  "Generation of SMT formula for unknown kind of expression: " +
1853  expr.pretty());
1854 }
1855 
1856 #ifndef CPROVER_INVARIANT_DO_NOT_CHECK
1857 template <typename functiont>
1859 {
1862  {
1863  }
1865  {
1866  exit_function();
1867  }
1869 };
1870 
1871 template <typename functiont>
1873 {
1874  return at_scope_exitt<functiont>(exit_function);
1875 }
1876 #endif
1877 
1879 {
1880  expr.visit_pre([](exprt &expr) {
1881  const auto address_of_expr = expr_try_dynamic_cast<address_of_exprt>(expr);
1882  if(!address_of_expr)
1883  return;
1884  const auto array_index_expr =
1885  expr_try_dynamic_cast<index_exprt>(address_of_expr->object());
1886  if(!array_index_expr)
1887  return;
1888  expr = plus_exprt{
1890  array_index_expr->array(),
1891  type_checked_cast<pointer_typet>(address_of_expr->type())},
1892  array_index_expr->index()};
1893  });
1894  return expr;
1895 }
1896 
1901  const exprt &_expr,
1902  std::function<bool(const exprt &)> filter,
1903  std::function<void(const exprt &)> visitor)
1904 {
1905  struct stack_entryt
1906  {
1907  const exprt *e;
1908  bool operands_pushed;
1909  explicit stack_entryt(const exprt *_e) : e(_e), operands_pushed(false)
1910  {
1911  }
1912  };
1913 
1914  std::stack<stack_entryt> stack;
1915 
1916  stack.emplace(&_expr);
1917 
1918  while(!stack.empty())
1919  {
1920  auto &top = stack.top();
1921  if(top.operands_pushed)
1922  {
1923  visitor(*top.e);
1924  stack.pop();
1925  }
1926  else
1927  {
1928  // do modification of 'top' before pushing in case 'top' isn't stable
1929  top.operands_pushed = true;
1930  if(filter(*top.e))
1931  for(auto &op : top.e->operands())
1932  stack.emplace(&op);
1933  }
1934  }
1935 }
1936 
1938  const exprt &expr,
1939  const smt_object_mapt &object_map,
1940  const type_size_mapt &pointer_sizes,
1942  const smt_is_dynamic_objectt::make_applicationt &is_dynamic_object)
1943 {
1944 #ifndef CPROVER_INVARIANT_DO_NOT_CHECK
1945  static bool in_conversion = false;
1946  INVARIANT(
1947  !in_conversion,
1948  "Conversion of expr to smt should be non-recursive. "
1949  "Re-entrance found in conversion of " +
1950  expr.pretty(1, 0));
1951  in_conversion = true;
1952  const auto end_conversion = at_scope_exit([&]() { in_conversion = false; });
1953 #endif
1954  sub_expression_mapt sub_expression_map;
1955  const auto lowered_expr = lower_address_of_array_index(expr);
1957  lowered_expr,
1958  [](const exprt &expr) {
1959  // Code values inside "address of" expressions do not need to be converted
1960  // as the "address of" conversion only depends on the object identifier.
1961  // Avoiding the conversion side steps a need to convert arbitrary code to
1962  // SMT terms.
1963  const auto address_of = expr_try_dynamic_cast<address_of_exprt>(expr);
1964  if(!address_of)
1965  return true;
1966  return !can_cast_type<code_typet>(address_of->object().type());
1967  },
1968  [&](const exprt &expr) {
1969  const auto find_result = sub_expression_map.find(expr);
1970  if(find_result != sub_expression_map.cend())
1971  return;
1973  expr,
1974  sub_expression_map,
1975  object_map,
1976  pointer_sizes,
1977  object_size,
1978  is_dynamic_object);
1979  sub_expression_map.emplace_hint(find_result, expr, std::move(term));
1980  });
1981  return std::move(sub_expression_map.at(lowered_expr));
1982 }
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.
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
bool can_cast_type< signedbv_typet >(const typet &type)
Check whether a reference to a typet is a signedbv_typet.
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< bv_typet >(const typet &type)
Check whether a reference to a typet is a bv_typet.
const fixedbv_typet & to_fixedbv_type(const typet &type)
Cast a typet to a fixedbv_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:442
Operator to return the address of an object.
Definition: pointer_expr.h:540
exprt & object()
Definition: pointer_expr.h:549
Thrown when an unexpected error occurs during the analysis (e.g., when the SAT solver returns an erro...
Boolean AND.
Definition: std_expr.h:2120
Expression to define a mapping from an argument (index) to elements.
Definition: std_expr.h:3413
Array constructor from list of elements.
Definition: std_expr.h:1616
Array constructor from single element.
Definition: std_expr.h:1553
Arrays with given size.
Definition: std_types.h:807
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:827
exprt & op1()
Definition: expr.h:136
exprt & lhs()
Definition: std_expr.h:668
exprt & op0()
Definition: expr.h:133
exprt & rhs()
Definition: std_expr.h:678
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition: std_expr.h:762
Bit-wise AND.
Bit-wise negation of bit-vectors.
Bit-wise OR.
Base class of fixed-width bit-vector types.
Definition: std_types.h:909
std::size_t get_width() const
Definition: std_types.h:925
Bit-wise XOR.
The Boolean type.
Definition: std_types.h:36
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:2990
const irep_idt & get_value() const
Definition: std_expr.h:2998
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:25
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:1361
Boute's Euclidean definition of Modulo – to match SMT-LIB2.
Definition: std_expr.h:1291
An exists expression.
Base class for all expressions.
Definition: expr.h:56
bool is_true() const
Return whether the expression is a constant representing true.
Definition: expr.cpp:27
void visit_pre(std::function< void(exprt &)>)
Definition: expr.cpp:227
typet & type()
Return the type of the expression.
Definition: expr.h:84
operandst & operands()
Definition: expr.h:94
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.
Definition: floatbv_expr.h:19
A forall expression.
IEEE-floating-point equality.
Definition: floatbv_expr.h:264
IEEE floating-point disequality.
Definition: floatbv_expr.h:312
IEEE floating-point operations These have two data operands (op0 and op1) and one rounding mode (op2)...
Definition: floatbv_expr.h:364
The trinary if-then-else operator.
Definition: std_expr.h:2370
exprt & true_case()
Definition: std_expr.h:2397
exprt & false_case()
Definition: std_expr.h:2407
exprt & cond()
Definition: std_expr.h:2387
Boolean implication.
Definition: std_expr.h:2183
Array index operator.
Definition: std_expr.h:1465
exprt & array()
Definition: std_expr.h:1495
exprt & index()
Definition: std_expr.h:1505
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.
Definition: pointer_expr.h:335
Evaluates to true if the operand is finite.
Definition: floatbv_expr.h:176
Evaluates to true if the operand is infinite.
Definition: floatbv_expr.h:132
Evaluates to true if the operand is NaN.
Definition: floatbv_expr.h:88
Evaluates to true if the operand is a normal number.
Definition: floatbv_expr.h:220
A let expression.
Definition: std_expr.h:3204
Extract member of struct or union.
Definition: std_expr.h:2844
Binary minus.
Definition: std_expr.h:1061
Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
Definition: std_expr.h:1223
Binary multiplication Associativity is not specified.
Definition: std_expr.h:1107
A base class for multi-ary expressions Associativity is not specified.
Definition: std_expr.h:912
Expression to hold a nondeterministic choice.
Definition: std_expr.h:292
const irep_idt & get_identifier() const
Definition: std_expr.h:320
Boolean negation.
Definition: std_expr.h:2327
Disequality.
Definition: std_expr.h:1420
Expression for finding the size (in bytes) of the object a pointer points to.
Boolean OR.
Definition: std_expr.h:2228
The plus expression Associativity is not specified.
Definition: std_expr.h:1002
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 ...
Definition: pointer_expr.h:24
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
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...
Definition: pointer_expr.h:453
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:596
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:1872
Expression to hold a symbol (variable)
Definition: std_expr.h:131
const irep_idt & get_identifier() const
Definition: std_expr.h:160
Semantic type conversion.
Definition: std_expr.h:2068
The type of an expression, extends irept.
Definition: type.h:29
const exprt & op() const
Definition: std_expr.h:391
The unary minus expression.
Definition: std_expr.h:484
The unary plus expression.
Definition: std_expr.h:531
Union constructor from single element.
Definition: std_expr.h:1765
Operator to update elements in structs and arrays.
Definition: std_expr.h:2655
Vector constructor from list of elements.
Definition: std_expr.h:1729
Operator to update elements in structs and arrays.
Definition: std_expr.h:2471
exprt & old()
Definition: std_expr.h:2481
Boolean XOR.
Definition: std_expr.h:2291
zero extension The operand is converted to the given type by either a) truncating if the new type is ...
static std::function< std::function< smt_termt(smt_termt)>std::size_t)> extension_for_type(const typet &type)
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 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::optional< smt_termt > try_relational_conversion(const exprt &expr, const sub_expression_mapt &converted)
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)
at_scope_exitt< functiont > at_scope_exit(functiont exit_function)
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.
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.
Definition: pointer_expr.h:80
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:93
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 binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition: std_expr.h:715
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition: std_expr.h:426
bool can_cast_type< array_typet >(const typet &type)
Check whether a reference to a typet is a array_typet.
Definition: std_types.h:875
bool can_cast_type< code_typet >(const typet &type)
Check whether a reference to a typet is a code_typet.
Definition: std_types.h:775
bool can_cast_type< bitvector_typet >(const typet &type)
Check whether a reference to a typet is a bitvector_typet.
Definition: std_types.h:952
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
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)
std::size_t object_bits
Definition: config.h:355
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
const constant_exprt & member_input
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