CBMC
Loading...
Searching...
No Matches
smt2_conv.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: SMT Backend
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#include "smt2_conv.h"
13
15#include <util/arith_tools.h>
16#include <util/bitvector_expr.h>
17#include <util/byte_operators.h>
18#include <util/c_types.h>
19#include <util/config.h>
20#include <util/expr_iterator.h>
21#include <util/expr_util.h>
22#include <util/fixedbv.h>
23#include <util/floatbv_expr.h>
24#include <util/format_expr.h>
25#include <util/ieee_float.h>
26#include <util/invariant.h>
28#include <util/namespace.h>
31#include <util/prefix.h>
32#include <util/range.h>
33#include <util/rational.h>
34#include <util/rational_tools.h>
35#include <util/simplify_expr.h>
36#include <util/std_expr.h>
37#include <util/string2int.h>
39#include <util/threeval.h>
40
45
46#include "smt2_tokenizer.h"
47
48#include <cstdint>
49
50// Mark different kinds of error conditions
51
52// Unexpected types and other combinations not implemented and not
53// expected to be needed
54#define UNEXPECTEDCASE(S) PRECONDITION_WITH_DIAGNOSTICS(false, S);
55
56// General todos
57#define SMT2_TODO(S) PRECONDITION_WITH_DIAGNOSTICS(false, "TODO: " S)
58
60 const namespacet &_ns,
61 const std::string &_benchmark,
62 const std::string &_notes,
63 const std::string &_logic,
65 std::ostream &_out)
66 : use_FPA_theory(false),
67 use_array_of_bool(false),
68 use_as_const(false),
69 use_check_sat_assuming(false),
70 use_datatypes(false),
71 use_lambda_for_array(false),
72 emit_set_logic(true),
73 ns(_ns),
74 out(_out),
75 benchmark(_benchmark),
76 notes(_notes),
77 logic(_logic),
79 boolbv_width(_ns),
80 pointer_logic(_ns),
81 no_boolean_variables(0)
82{
83 // We set some defaults differently
84 // for some solvers.
85
86 switch(solver)
87 {
89 break;
90
92 use_FPA_theory = true;
93 use_array_of_bool = true;
94 use_as_const = true;
97 emit_set_logic = false;
98 break;
99
101 break;
102
104 use_FPA_theory = true;
105 use_array_of_bool = true;
106 use_as_const = true;
108 emit_set_logic = false;
109 break;
110
111 case solvert::CVC3:
112 break;
113
114 case solvert::CVC4:
115 logic = "ALL";
116 use_array_of_bool = true;
117 use_as_const = true;
118 break;
119
120 case solvert::CVC5:
121 logic = "ALL";
122 use_FPA_theory = true;
123 use_array_of_bool = true;
124 use_as_const = true;
126 use_datatypes = true;
127 break;
128
129 case solvert::MATHSAT:
130 break;
131
132 case solvert::YICES:
133 break;
134
135 case solvert::Z3:
136 use_array_of_bool = true;
137 use_as_const = true;
140 emit_set_logic = false;
141 use_datatypes = true;
142 break;
143 }
144
145 write_header();
146}
147
149{
150 return "SMT2";
151}
152
153void smt2_convt::print_assignment(std::ostream &os) const
154{
155 // Boolean stuff
156
157 for(std::size_t v=0; v<boolean_assignment.size(); v++)
158 os << "b" << v << "=" << boolean_assignment[v] << "\n";
159
160 // others
161}
162
164{
165 if(l.is_true())
166 return tvt(true);
167 if(l.is_false())
168 return tvt(false);
169
170 INVARIANT(
171 l.var_no() < boolean_assignment.size(),
172 "variable number shall be within bounds");
173 return tvt(boolean_assignment[l.var_no()]^l.sign());
174}
175
177{
178 out << "; SMT 2" << "\n";
179
180 switch(solver)
181 {
182 // clang-format off
183 case solvert::GENERIC: break;
184 case solvert::BITWUZLA: out << "; Generated for Bitwuzla\n"; break;
185 case solvert::BOOLECTOR: out << "; Generated for Boolector\n"; break;
187 out << "; Generated for the CPROVER SMT2 solver\n"; break;
188 case solvert::CVC3: out << "; Generated for CVC 3\n"; break;
189 case solvert::CVC4: out << "; Generated for CVC 4\n"; break;
190 case solvert::CVC5: out << "; Generated for CVC 5\n"; break;
191 case solvert::MATHSAT: out << "; Generated for MathSAT\n"; break;
192 case solvert::YICES: out << "; Generated for Yices\n"; break;
193 case solvert::Z3: out << "; Generated for Z3\n"; break;
194 // clang-format on
195 }
196
197 out << "(set-info :source \"" << notes << "\")" << "\n";
198
199 out << "(set-option :produce-models true)" << "\n";
200
201 // We use a broad mixture of logics, so on some solvers
202 // its better not to declare here.
203 // set-logic should come after setting options
204 if(emit_set_logic && !logic.empty())
205 out << "(set-logic " << logic << ")" << "\n";
206}
207
209{
210 out << "\n";
211
212 // fix up the object sizes
213 for(const auto &object : object_sizes)
214 define_object_size(object.second, object.first);
215
216 if(use_check_sat_assuming && !assumptions.empty())
217 {
218 out << "(check-sat-assuming (";
219 for(const auto &assumption : assumptions)
220 convert_literal(assumption);
221 out << "))\n";
222 }
223 else
224 {
225 // add the assumptions, if any
226 if(!assumptions.empty())
227 {
228 out << "; assumptions\n";
229
230 for(const auto &assumption : assumptions)
231 {
232 out << "(assert ";
233 convert_literal(assumption);
234 out << ")"
235 << "\n";
236 }
237 }
238
239 out << "(check-sat)\n";
240 }
241
242 out << "\n";
243
245 {
246 for(const auto &id : smt2_identifiers)
247 out << "(get-value (" << id << "))"
248 << "\n";
249 }
250
251 out << "\n";
252
253 out << "(exit)\n";
254
255 out << "; end of SMT2 file"
256 << "\n";
257}
258
260static bool is_zero_width(const typet &type, const namespacet &ns)
261{
262 if(type.id() == ID_empty)
263 return true;
264 else if(type.id() == ID_struct_tag)
265 return is_zero_width(ns.follow_tag(to_struct_tag_type(type)), ns);
266 else if(type.id() == ID_union_tag)
267 return is_zero_width(ns.follow_tag(to_union_tag_type(type)), ns);
268 else if(type.id() == ID_struct || type.id() == ID_union)
269 {
270 for(const auto &comp : to_struct_union_type(type).components())
271 {
272 if(!is_zero_width(comp.type(), ns))
273 return false;
274 }
275 return true;
276 }
278 {
279 // we ignore array_type->size().is_zero() for now as there may be
280 // out-of-bounds accesses that we need to model
281 return is_zero_width(array_type->element_type(), ns);
282 }
283 else
284 return false;
285}
286
288 const irep_idt &id,
289 const object_size_exprt &expr)
290{
291 const exprt &ptr = expr.pointer();
292 std::size_t pointer_width = boolbv_width(ptr.type());
293 std::size_t number = 0;
294 std::size_t h=pointer_width-1;
295 std::size_t l=pointer_width-config.bv_encoding.object_bits;
296
297 for(const auto &o : pointer_logic.objects)
298 {
299 const typet &type = o.type();
300 auto size_expr = size_of_expr(type, ns);
301
302 if(
303 (o.id() != ID_symbol && o.id() != ID_string_constant) ||
304 !size_expr.has_value())
305 {
306 ++number;
307 continue;
308 }
309
311 out << "(assert (=> (= "
312 << "((_ extract " << h << " " << l << ") ";
313 convert_expr(ptr);
314 out << ") (_ bv" << number << " " << config.bv_encoding.object_bits << "))"
315 << "(= " << id << " ";
317 out << ")))\n";
318
319 ++number;
320 }
321}
322
324{
325 if(assumption.is_nil())
326 write_footer();
327 else
328 {
329 assumptions.push_back(convert(assumption));
330 write_footer();
331 assumptions.pop_back();
332 }
333
334 out.flush();
336}
337
338exprt smt2_convt::get(const exprt &expr) const
339{
340 if(expr.id()==ID_symbol)
341 {
342 const irep_idt &id=to_symbol_expr(expr).get_identifier();
343
344 identifier_mapt::const_iterator it=identifier_map.find(id);
345
346 if(it!=identifier_map.end())
347 return it->second.value;
348 return expr;
349 }
350 else if(expr.id()==ID_nondet_symbol)
351 {
352 const irep_idt &id=to_nondet_symbol_expr(expr).get_identifier();
353
354 identifier_mapt::const_iterator it=identifier_map.find(id);
355
356 if(it!=identifier_map.end())
357 return it->second.value;
358 }
359 else if(expr.id() == ID_literal)
360 {
361 auto l = to_literal_expr(expr).get_literal();
362 if(l_get(l).is_true())
363 return true_exprt();
364 else
365 return false_exprt();
366 }
367 else if(expr.id() == ID_not)
368 {
369 auto op = get(to_not_expr(expr).op());
370 if(op == true)
371 return false_exprt();
372 else if(op == false)
373 return true_exprt();
374 }
375 else if(
376 expr.is_constant() || expr.id() == ID_empty_union ||
377 (!expr.has_operands() && (expr.id() == ID_struct || expr.id() == ID_array)))
378 {
379 return expr;
380 }
381 else if(expr.has_operands())
382 {
383 exprt copy = expr;
384 for(auto &op : copy.operands())
385 {
386 exprt eval_op = get(op);
387 if(eval_op.is_nil())
388 return nil_exprt{};
389 op = std::move(eval_op);
390 }
391 return copy;
392 }
393
394 return nil_exprt();
395}
396
398 const irept &src,
399 const typet &type)
400{
401 // See http://www.grammatech.com/resources/smt/SMTLIBTutorial.pdf for the
402 // syntax of SMTlib2 literals.
403 //
404 // A literal expression is one of the following forms:
405 //
406 // * Numeral -- this is a natural number in decimal and is of the form:
407 // 0|([1-9][0-9]*)
408 // * Decimal -- this is a decimal expansion of a real number of the form:
409 // (0|[1-9][0-9]*)[.]([0-9]+)
410 // * Binary -- this is a natural number in binary and is of the form:
411 // #b[01]+
412 // * Hex -- this is a natural number in hexadecimal and is of the form:
413 // #x[0-9a-fA-F]+
414 //
415 // Right now I'm not parsing decimals. It'd be nice if we had a real YACC
416 // parser here, but whatever.
417
418 mp_integer value;
419
420 if(!src.id().empty())
421 {
422 const std::string &s=src.id_string();
423
424 if(s.size()>=2 && s[0]=='#' && s[1]=='b')
425 {
426 // Binary #b010101
427 value=string2integer(s.substr(2), 2);
428 }
429 else if(s.size()>=2 && s[0]=='#' && s[1]=='x')
430 {
431 // Hex #x012345
432 value=string2integer(s.substr(2), 16);
433 }
434 else
435 {
436 std::size_t pos = s.find(".");
437 if(pos != std::string::npos)
438 {
439 // Decimal, return as rational or real
440 if(type.id() == ID_rational)
441 {
443 bool failed = to_rational(
447 }
448 else if(type.id() == ID_real)
449 {
451 bool failed = to_rational(
454 return algebraic_numbert{rational_value}.as_expr();
455 }
456 else
457 {
459 "smt2_convt::parse_literal parsed a number with a decimal point "
460 "as type " +
461 type.id_string());
462 }
463 }
464 // Numeral
465 value=string2integer(s);
466 }
467 }
468 else if(src.get_sub().size()==2 &&
469 src.get_sub()[0].id()=="-") // (- 100)
470 {
471 value=-string2integer(src.get_sub()[1].id_string());
472 }
473 else if(src.get_sub().size()==3 &&
474 src.get_sub()[0].id()=="_" &&
475 // (_ bvDECIMAL_VALUE SIZE)
476 src.get_sub()[1].id_string().substr(0, 2)=="bv")
477 {
478 value=string2integer(src.get_sub()[1].id_string().substr(2));
479 }
480 else if(
481 type.id() == ID_rational && src.get_sub().size() == 3 &&
482 src.get_sub()[0].id() == "/")
483 {
484 rationalt numerator;
485 rationalt denominator;
486 bool failed =
487 to_rational(parse_literal(src.get_sub()[1], type), numerator) ||
488 to_rational(parse_literal(src.get_sub()[2], type), denominator);
490 return from_rational(numerator / denominator);
491 }
492 else if(src.get_sub().size()==4 &&
493 src.get_sub()[0].id()=="fp") // (fp signbv exponentbv significandbv)
494 {
495 if(type.id()==ID_floatbv)
496 {
503
507
508 // stitch the bits together
509 value = bitwise_or(
510 s1_int << (floatbv_type.get_e() + floatbv_type.get_f()),
511 bitwise_or((s2_int << floatbv_type.get_f()), s3_int));
512 }
513 else
514 value=0;
515 }
516 else if(src.get_sub().size()==4 &&
517 src.get_sub()[0].id()=="_" &&
518 src.get_sub()[1].id()=="+oo") // (_ +oo e s)
519 {
520 std::size_t e = unsafe_string2size_t(src.get_sub()[2].id_string());
521 std::size_t s = unsafe_string2size_t(src.get_sub()[3].id_string());
523 .to_expr();
524 }
525 else if(src.get_sub().size()==4 &&
526 src.get_sub()[0].id()=="_" &&
527 src.get_sub()[1].id()=="-oo") // (_ -oo e s)
528 {
529 std::size_t e = unsafe_string2size_t(src.get_sub()[2].id_string());
530 std::size_t s = unsafe_string2size_t(src.get_sub()[3].id_string());
532 .to_expr();
533 }
534 else if(src.get_sub().size()==4 &&
535 src.get_sub()[0].id()=="_" &&
536 src.get_sub()[1].id()=="NaN") // (_ NaN e s)
537 {
538 std::size_t e = unsafe_string2size_t(src.get_sub()[2].id_string());
539 std::size_t s = unsafe_string2size_t(src.get_sub()[3].id_string());
540 return ieee_float_valuet::NaN(ieee_float_spect(s - 1, e)).to_expr();
541 }
542 else if(
543 src.get_sub().size() == 3 &&
544 src.get_sub()[0].id() == "root-obj") // (root-obj (+ ...) 1)
545 {
546 // Z3 emits these while there isn't an agreed-upon standard for representing
547 // algebraic numbers just yet. https://smt-comp.github.io/2023/model.html
548 // gave some proposals, but these don't seem to have been implemented.
549 // For now, we use DATA_INVARIANT as our parsing may be overly restrictive.
550 // Eventually, these should become proper, user-facing exceptions.
552 src.get_sub()[1].id().empty() && src.get_sub()[1].get_sub().size() == 3 &&
553 src.get_sub()[1].get_sub()[0].id() == "+" &&
554 src.get_sub()[2].id() == "1",
555 "unexpected root-obj expression",
556 src.pretty());
557 irept sum_rhs = src.get_sub()[1].get_sub()[2];
559 bool failed =
562 !failed, "failed to parse rational constant coefficient", src.pretty());
563 irept sum_lhs = src.get_sub()[1].get_sub()[1];
565 sum_lhs.id().empty() && sum_lhs.get_sub().size() == 3 &&
566 sum_lhs.get_sub()[0].id() == "^" && sum_lhs.get_sub()[1].id() == "x",
567 "unexpected first operand to root-obj",
568 src.pretty());
569 std::size_t degree = unsafe_string2size_t(sum_lhs.get_sub()[2].id_string());
571 degree > 0, "polynomial degree must be positive", src.pretty());
572 std::vector<rationalt> coefficients{degree + 1, rationalt{}};
573 coefficients.front() = constant_coeff;
574 coefficients.back() = rationalt{1};
575 algebraic_numbert a{coefficients};
576 return a.as_expr();
577 }
578
579 if(type.id()==ID_signedbv ||
580 type.id()==ID_unsignedbv ||
581 type.id()==ID_c_enum ||
582 type.id()==ID_c_bool)
583 {
584 return from_integer(value, type);
585 }
586 else if(type.id()==ID_c_enum_tag)
587 {
588 constant_exprt result =
589 from_integer(value, ns.follow_tag(to_c_enum_tag_type(type)));
590
591 // restore the c_enum_tag type
592 result.type() = type;
593 return result;
594 }
595 else if(type.id()==ID_fixedbv ||
596 type.id()==ID_floatbv)
597 {
598 std::size_t width=boolbv_width(type);
599 return constant_exprt(integer2bvrep(value, width), type);
600 }
601 else if(
602 type.id() == ID_integer || type.id() == ID_natural ||
603 type.id() == ID_rational || type.id() == ID_real)
604 {
605 return from_integer(value, type);
606 }
607 else if(type.id() == ID_range)
608 {
609 return from_integer(value + to_range_type(type).get_from(), type);
610 }
611 else
613 "smt2_convt::parse_literal should not be of unsupported type " +
614 type.id_string());
615}
616
618 const irept &src,
619 const array_typet &type)
620{
621 std::unordered_map<int64_t, exprt> operands_map;
622 walk_array_tree(&operands_map, src, type);
623 exprt::operandst operands;
624 // Try to find the default value, if there is none then set it
625 auto maybe_default_op = operands_map.find(-1);
627 if(maybe_default_op == operands_map.end())
629 else
631 int64_t i = 0;
633 if(maybe_size.has_value())
634 {
635 while(i < maybe_size.value())
636 {
637 auto found_op = operands_map.find(i);
638 if(found_op != operands_map.end())
639 operands.emplace_back(found_op->second);
640 else
641 operands.emplace_back(default_op);
642 i++;
643 }
644 }
645 else
646 {
647 // Array size is unknown, keep adding with known indexes in order
648 // until we fail to find one.
649 auto found_op = operands_map.find(i);
650 while(found_op != operands_map.end())
651 {
652 operands.emplace_back(found_op->second);
653 i++;
654 found_op = operands_map.find(i);
655 }
656 operands.emplace_back(default_op);
657 }
658 return array_exprt(operands, type);
659}
660
662 std::unordered_map<int64_t, exprt> *operands_map,
663 const irept &src,
664 const array_typet &type)
665{
666 if(src.get_sub().size()==4 && src.get_sub()[0].id()=="store")
667 {
668 // This is the SMT syntax being parsed here
669 // (store array index value)
670 // Recurse
671 walk_array_tree(operands_map, src.get_sub()[1], type);
672 const auto index_expr = parse_rec(src.get_sub()[2], type.size().type());
675 bool failure = to_integer(index_constant, tempint);
676 if(failure)
677 return;
678 long index = tempint.to_long();
679 exprt value = parse_rec(src.get_sub()[3], type.element_type());
680 operands_map->emplace(index, value);
681 }
682 else if(src.get_sub().size()==2 &&
683 src.get_sub()[0].get_sub().size()==3 &&
684 src.get_sub()[0].get_sub()[0].id()=="as" &&
685 src.get_sub()[0].get_sub()[1].id()=="const")
686 {
687 // (as const type_info default_value)
688 exprt default_value = parse_rec(src.get_sub()[1], type.element_type());
689 operands_map->emplace(-1, default_value);
690 }
691 else
692 {
693 auto bindings_it = current_bindings.find(src.id());
694 if(bindings_it != current_bindings.end())
696 }
697}
698
700 const irept &src,
701 const union_typet &type)
702{
703 // these are always flat
704 PRECONDITION(!type.components().empty());
705 const union_typet::componentt &first=type.components().front();
706 std::size_t width=boolbv_width(type);
707 exprt value = parse_rec(src, unsignedbv_typet(width));
708 if(value.is_nil())
709 return nil_exprt();
710 const typecast_exprt converted(value, first.type());
711 return union_exprt(first.get_name(), converted, type);
712}
713
716{
717 const struct_typet::componentst &components =
718 type.components();
719
720 struct_exprt result(exprt::operandst(components.size(), nil_exprt()), type);
721
722 if(components.empty())
723 return result;
724
725 if(use_datatypes)
726 {
727 // Structs look like:
728 // (mk-struct.1 <component0> <component1> ... <componentN>)
729 std::size_t j = 1;
730 for(std::size_t i=0; i<components.size(); i++)
731 {
732 const struct_typet::componentt &c=components[i];
733 if(is_zero_width(components[i].type(), ns))
734 {
735 result.operands()[i] = nil_exprt{};
736 }
737 else
738 {
740 src.get_sub().size() > j, "insufficient number of component values");
741 result.operands()[i] = parse_rec(src.get_sub()[j], c.type());
742 ++j;
743 }
744 }
745 }
746 else
747 {
748 // These are just flattened, i.e., we expect to see a monster bit vector.
749 std::size_t total_width=boolbv_width(type);
750 const auto l = parse_literal(src, unsignedbv_typet(total_width));
751
752 const irep_idt binary =
754
755 CHECK_RETURN(binary.size() == total_width);
756
757 std::size_t offset=0;
758
759 for(std::size_t i=0; i<components.size(); i++)
760 {
761 if(is_zero_width(components[i].type(), ns))
762 continue;
763
764 std::size_t component_width=boolbv_width(components[i].type());
765
766 INVARIANT(
767 offset + component_width <= total_width,
768 "struct component bits shall be within struct bit vector");
769
770 std::string component_binary=
771 "#b"+id2string(binary).substr(
772 total_width-offset-component_width, component_width);
773
774 result.operands()[i]=
775 parse_rec(irept(component_binary), components[i].type());
776
777 offset+=component_width;
778 }
779 }
780
781 return result;
782}
783
784exprt smt2_convt::parse_rec(const irept &src, const typet &type)
785{
786 if(src.get_sub().size() == 3 && src.get_sub()[0].id() == ID_let)
787 {
788 // This is produced by Z3
789 // (let (....) (....))
791 for(const auto &binding : src.get_sub()[1].get_sub())
792 {
793 const irep_idt &name = binding.get_sub()[0].id();
794 current_bindings.emplace(name, binding.get_sub()[1]);
795 }
796 exprt result = parse_rec(src.get_sub()[2], type);
798 return result;
799 }
800
801 auto bindings_it = current_bindings.find(src.id());
802 if(bindings_it != current_bindings.end())
803 {
804 return parse_rec(bindings_it->second, type);
805 }
806
807 if(
808 type.id() == ID_signedbv || type.id() == ID_unsignedbv ||
809 type.id() == ID_integer || type.id() == ID_rational ||
810 type.id() == ID_natural || type.id() == ID_real || type.id() == ID_c_enum ||
811 type.id() == ID_c_enum_tag || type.id() == ID_fixedbv ||
812 type.id() == ID_floatbv || type.id() == ID_c_bool || type.id() == ID_range)
813 {
814 return parse_literal(src, type);
815 }
816 else if(type.id()==ID_bool)
817 {
818 if(src.id()==ID_1 || src.id()==ID_true)
819 return true_exprt();
820 else if(src.id()==ID_0 || src.id()==ID_false)
821 return false_exprt();
822 }
823 else if(type.id()==ID_pointer)
824 {
825 // these come in as bit-vector literals
826 std::size_t width=boolbv_width(type);
828
830
831 // split into object and offset
832 mp_integer pow=power(2, width-config.bv_encoding.object_bits);
835 bv_expr.get_value(),
837 }
838 else if(type.id()==ID_struct)
839 {
840 return parse_struct(src, to_struct_type(type));
841 }
842 else if(type.id() == ID_struct_tag)
843 {
844 auto struct_expr =
845 parse_struct(src, ns.follow_tag(to_struct_tag_type(type)));
846 // restore the tag type
847 struct_expr.type() = type;
848 return std::move(struct_expr);
849 }
850 else if(type.id()==ID_union)
851 {
852 return parse_union(src, to_union_type(type));
853 }
854 else if(type.id() == ID_union_tag)
855 {
856 auto union_expr = parse_union(src, ns.follow_tag(to_union_tag_type(type)));
857 // restore the tag type
858 union_expr.type() = type;
859 return union_expr;
860 }
861 else if(type.id()==ID_array)
862 {
863 return parse_array(src, to_array_type(type));
864 }
865
866 return nil_exprt();
867}
868
870 const exprt &expr,
871 const pointer_typet &result_type)
872{
873 if(
874 expr.id() == ID_symbol || expr.is_constant() ||
875 expr.id() == ID_string_constant || expr.id() == ID_label)
876 {
877 const std::size_t object_bits = config.bv_encoding.object_bits;
878 const std::size_t max_objects = std::size_t(1) << object_bits;
880
882 {
884 "too many addressed objects: maximum number of objects is set to 2^n=" +
885 std::to_string(max_objects) +
886 " (with n=" + std::to_string(object_bits) + "); " +
887 "use the `--object-bits n` option to increase the maximum number"};
888 }
889
890 out << "(concat (_ bv" << object_id << " " << object_bits << ")"
891 << " (_ bv0 " << boolbv_width(result_type) - object_bits << "))";
892 }
893 else if(expr.id()==ID_index)
894 {
895 const index_exprt &index_expr = to_index_expr(expr);
896
897 const exprt &array = index_expr.array();
898 const exprt &index = index_expr.index();
899
900 if(index == 0)
901 {
902 if(array.type().id()==ID_pointer)
903 convert_expr(array);
904 else if(array.type().id()==ID_array)
905 convert_address_of_rec(array, result_type);
906 else
908 }
909 else
910 {
911 // this is really pointer arithmetic
913 new_index_expr.index() = from_integer(0, index.type());
914
917 pointer_type(to_array_type(array.type()).element_type()));
918
920
922 }
923 }
924 else if(expr.id()==ID_member)
925 {
927
928 const exprt &struct_op=member_expr.struct_op();
929 const typet &struct_op_type = struct_op.type();
930
933 "member expression operand shall have struct type");
934
939
940 const irep_idt &component_name = member_expr.get_component_name();
941
942 const auto offset = member_offset(struct_type, component_name, ns);
943 CHECK_RETURN(offset.has_value() && *offset >= 0);
944
945 unsignedbv_typet index_type(boolbv_width(result_type));
946
947 // pointer arithmetic
948 out << "(bvadd ";
949 convert_address_of_rec(struct_op, result_type);
950 convert_expr(from_integer(*offset, index_type));
951 out << ")"; // bvadd
952 }
953 else if(expr.id()==ID_if)
954 {
955 const if_exprt &if_expr = to_if_expr(expr);
956
957 out << "(ite ";
958 convert_expr(if_expr.cond());
959 out << " ";
960 convert_address_of_rec(if_expr.true_case(), result_type);
961 out << " ";
962 convert_address_of_rec(if_expr.false_case(), result_type);
963 out << ")";
964 }
965 else
966 INVARIANT(
967 false,
968 "operand of address of expression should not be of kind " +
969 expr.id_string());
970}
971
972static bool has_quantifier(const exprt &expr)
973{
974 bool result = false;
975 expr.visit_post([&result](const exprt &node) {
976 if(node.id() == ID_exists || node.id() == ID_forall)
977 result = true;
978 });
979 return result;
980}
981
983{
984 PRECONDITION(expr.is_boolean());
985
986 // Three cases where no new handle is needed.
987
988 if(expr == true)
989 return const_literal(true);
990 else if(expr == false)
991 return const_literal(false);
992 else if(expr.id()==ID_literal)
993 return to_literal_expr(expr).get_literal();
994
995 // Need a new handle
996
997 out << "\n";
998
1000
1003
1004 out << "; convert\n";
1005 out << "; Converting var_no " << l.var_no() << " with expr ID of "
1006 << expr.id_string() << "\n";
1007 // We're converting the expression, so store it in the defined_expressions
1008 // store and in future we use the literal instead of the whole expression
1009 // Note that here we are always converting, so we do not need to consider
1010 // other literal kinds, only "|B###|"
1011
1012 // Z3 refuses get-value when a defined symbol contains a quantifier.
1014 {
1015 out << "(declare-fun ";
1016 convert_literal(l);
1017 out << " () Bool)\n";
1018 out << "(assert (= ";
1019 convert_literal(l);
1020 out << ' ';
1022 out << "))\n";
1023 }
1024 else
1025 {
1026 auto identifier =
1027 convert_identifier(std::string{"B"} + std::to_string(l.var_no()));
1028 defined_expressions[expr] = identifier;
1029 smt2_identifiers.insert(identifier);
1030 out << "(define-fun " << identifier << " () Bool ";
1032 out << ")\n";
1033 }
1034
1035 return l;
1036}
1037
1039{
1040 // We can only improve Booleans.
1041 if(!expr.is_boolean())
1042 return expr;
1043
1044 return literal_exprt(convert(expr));
1045}
1046
1048{
1049 if(l==const_literal(false))
1050 out << "false";
1051 else if(l==const_literal(true))
1052 out << "true";
1053 else
1054 {
1055 if(l.sign())
1056 out << "(not ";
1057
1058 const auto identifier =
1059 convert_identifier("B" + std::to_string(l.var_no()));
1060
1061 out << identifier;
1062
1063 if(l.sign())
1064 out << ")";
1065
1066 smt2_identifiers.insert(identifier);
1067 }
1068}
1069
1071{
1073}
1074
1075void smt2_convt::push(const std::vector<exprt> &_assumptions)
1076{
1077 INVARIANT(assumptions.empty(), "nested contexts are not supported");
1078
1079 assumptions.reserve(_assumptions.size());
1080 for(auto &assumption : _assumptions)
1081 assumptions.push_back(convert(assumption));
1082}
1083
1085{
1087}
1088
1089static bool is_smt2_simple_identifier(const std::string &identifier)
1090{
1091 if(identifier.empty())
1092 return false;
1093
1094 if(isdigit(identifier[0]))
1095 return false;
1096
1097 for(auto ch : id2string(identifier))
1098 {
1100 return false;
1101 }
1102
1103 return true;
1104}
1105
1106std::string smt2_convt::convert_identifier(const irep_idt &identifier)
1107{
1108 // Is this a "simple identifier"?
1109 if(is_smt2_simple_identifier(id2string(identifier)))
1110 return id2string(identifier);
1111
1112 // Backslashes are disallowed in quoted symbols just for simplicity.
1113 // Otherwise, for Common Lisp compatibility they would have to be treated
1114 // as escaping symbols.
1115
1116 std::string result = "|";
1117
1118 for(auto ch : identifier)
1119 {
1120 switch(ch)
1121 {
1122 case '|':
1123 case '\\':
1124 case '&': // we use the & for escaping
1125 result+='&';
1126 result+=std::to_string(ch);
1127 result+=';';
1128 break;
1129
1130 case '$': // $ _is_ allowed
1131 default:
1132 result+=ch;
1133 }
1134 }
1135
1136 result += '|';
1137
1138 return result;
1139}
1140
1141std::string smt2_convt::type2id(const typet &type) const
1142{
1143 if(type.id()==ID_floatbv)
1144 {
1146 return "f"+std::to_string(spec.width())+"_"+std::to_string(spec.f);
1147 }
1148 else if(type.id() == ID_bv)
1149 {
1150 return "B" + std::to_string(to_bitvector_type(type).get_width());
1151 }
1152 else if(type.id()==ID_unsignedbv)
1153 {
1154 return "u"+std::to_string(to_unsignedbv_type(type).get_width());
1155 }
1156 else if(type.id()==ID_c_bool)
1157 {
1158 return "u"+std::to_string(to_c_bool_type(type).get_width());
1159 }
1160 else if(type.id()==ID_signedbv)
1161 {
1162 return "s"+std::to_string(to_signedbv_type(type).get_width());
1163 }
1164 else if(type.id()==ID_bool)
1165 {
1166 return "b";
1167 }
1168 else if(type.id()==ID_c_enum_tag)
1169 {
1170 return type2id(ns.follow_tag(to_c_enum_tag_type(type)).underlying_type());
1171 }
1172 else if(type.id() == ID_pointer)
1173 {
1174 return "p" + std::to_string(to_pointer_type(type).get_width());
1175 }
1176 else if(type.id() == ID_struct_tag)
1177 {
1178 if(use_datatypes)
1179 return datatype_map.at(type);
1180 else
1181 return "S" + std::to_string(boolbv_width(type));
1182 }
1183 else if(type.id() == ID_union_tag)
1184 {
1185 return "U" + std::to_string(boolbv_width(type));
1186 }
1187 else if(type.id() == ID_array)
1188 {
1189 return "A" + type2id(to_array_type(type).element_type());
1190 }
1191 else
1192 {
1194 }
1195}
1196
1197std::string smt2_convt::floatbv_suffix(const exprt &expr) const
1198{
1199 PRECONDITION(!expr.operands().empty());
1200 return "_" + type2id(to_multi_ary_expr(expr).op0().type()) + "->" +
1201 type2id(expr.type());
1202}
1203
1205{
1207
1208 if(expr.id()==ID_symbol)
1209 {
1210 const irep_idt &id = to_symbol_expr(expr).get_identifier();
1211 out << convert_identifier(id);
1212 return;
1213 }
1214
1215 if(expr.id()==ID_smt2_symbol)
1216 {
1217 const irep_idt &id = to_smt2_symbol(expr).get_identifier();
1218 out << id;
1219 return;
1220 }
1221
1222 INVARIANT(
1223 !expr.operands().empty(), "non-symbol expressions shall have operands");
1224
1225 out << '('
1227 "float_bv." + expr.id_string() + floatbv_suffix(expr));
1228
1229 for(const auto &op : expr.operands())
1230 {
1231 out << ' ';
1232 convert_expr(op);
1233 }
1234
1235 out << ')';
1236}
1237
1238void smt2_convt::convert_string_literal(const std::string &s)
1239{
1240 out << '"';
1241 for(auto ch : s)
1242 {
1243 // " is escaped by double-quoting
1244 if(ch == '"')
1245 out << '"';
1246 out << ch;
1247 }
1248 out << '"';
1249}
1250
1252{
1253 // try hash table first
1254 auto converter_result = converters.find(expr.id());
1255 if(converter_result != converters.end())
1256 {
1257 converter_result->second(expr);
1258 return; // done
1259 }
1260
1261 // huge monster case split over expression id
1262 if(expr.id()==ID_symbol)
1263 {
1264 const irep_idt &id = to_symbol_expr(expr).get_identifier();
1265 DATA_INVARIANT(!id.empty(), "symbol must have identifier");
1266 out << convert_identifier(id);
1267 }
1268 else if(expr.id()==ID_nondet_symbol)
1269 {
1270 const irep_idt &id = to_nondet_symbol_expr(expr).get_identifier();
1271 DATA_INVARIANT(!id.empty(), "nondet symbol must have identifier");
1272 out << convert_identifier("nondet_" + id2string(id));
1273 }
1274 else if(expr.id()==ID_smt2_symbol)
1275 {
1276 const irep_idt &id = to_smt2_symbol(expr).get_identifier();
1277 DATA_INVARIANT(!id.empty(), "smt2 symbol must have identifier");
1278 out << id;
1279 }
1280 else if(expr.id()==ID_typecast)
1281 {
1283 }
1284 else if(expr.id()==ID_floatbv_typecast)
1285 {
1287 }
1288 else if(expr.id() == ID_floatbv_round_to_integral)
1289 {
1291 }
1292 else if(expr.id()==ID_struct)
1293 {
1295 }
1296 else if(expr.id()==ID_union)
1297 {
1299 }
1300 else if(expr.is_constant())
1301 {
1303 }
1304 else if(expr.id() == ID_concatenation)
1305 {
1307 !expr.operands().empty(),
1308 "concatenation expression should have at least one operand",
1309 expr.id_string());
1310
1311 if(expr.operands().size() == 1)
1312 {
1313 flatten2bv(expr.operands().front());
1314 }
1315 else // >= 2
1316 {
1317 out << "(concat";
1318
1319 for(const auto &op : expr.operands())
1320 {
1321 // drop zero-width operands, which are not allowed by SMT-LIB
1322 if(!is_zero_width(op.type(), ns))
1323 {
1324 out << ' ';
1325 flatten2bv(op);
1326 }
1327 }
1328
1329 out << ')';
1330 }
1331 }
1332 else if(
1333 expr.id() == ID_bitand || expr.id() == ID_bitor || expr.id() == ID_bitxor)
1334 {
1336 !expr.operands().empty(),
1337 "given expression should have at least one operand",
1338 expr.id_string());
1339
1340 if(expr.operands().size() == 1)
1341 {
1342 flatten2bv(expr.operands().front());
1343 }
1344 else // >= 2
1345 {
1346 out << '(';
1347
1348 if(expr.id() == ID_concatenation)
1349 out << "concat";
1350 else if(expr.id() == ID_bitand)
1351 out << "bvand";
1352 else if(expr.id() == ID_bitor)
1353 out << "bvor";
1354 else if(expr.id() == ID_bitxor)
1355 out << "bvxor";
1356
1357 for(const auto &op : expr.operands())
1358 {
1359 out << ' ';
1360 flatten2bv(op);
1361 }
1362
1363 out << ')';
1364 }
1365 }
1366 else if(
1367 expr.id() == ID_bitxnor || expr.id() == ID_bitnand ||
1368 expr.id() == ID_bitnor)
1369 {
1370 // SMT-LIB only has these as a binary expression,
1371 // owing to their ambiguity.
1372 if(expr.operands().size() == 2)
1373 {
1374 const auto &binary_expr = to_binary_expr(expr);
1375
1376 out << '(';
1377 if(binary_expr.id() == ID_bitxnor)
1378 out << "bvxnor";
1379 else if(binary_expr.id() == ID_bitnand)
1380 out << "bvnand";
1381 else if(binary_expr.id() == ID_bitnor)
1382 out << "bvnor";
1383 out << ' ';
1384 flatten2bv(binary_expr.op0());
1385 out << ' ';
1386 flatten2bv(binary_expr.op1());
1387 out << ')';
1388 }
1389 else if(expr.operands().size() == 1)
1390 {
1391 out << "(bvnot ";
1392 flatten2bv(to_unary_expr(expr).op());
1393 out << ')';
1394 }
1395 else if(expr.operands().size() >= 3)
1396 {
1397 out << "(bvnot (";
1398 if(expr.id() == ID_bitxnor)
1399 out << "bvxor";
1400 else if(expr.id() == ID_bitnand)
1401 out << "bvand";
1402 else if(expr.id() == ID_bitnor)
1403 out << "bvor";
1404
1405 for(const auto &op : expr.operands())
1406 {
1407 out << ' ';
1408 flatten2bv(op);
1409 }
1410
1411 out << "))"; // bvX, bvnot
1412 }
1413 else
1414 {
1416 expr.operands().size() >= 1,
1417 expr.id_string() + " should have at least one operand");
1418 }
1419 }
1420 else if(expr.id()==ID_bitnot)
1421 {
1423
1424 out << "(bvnot ";
1426 out << ")";
1427 }
1428 else if(expr.id()==ID_unary_minus)
1429 {
1431 const auto &type = expr.type();
1432
1433 if(
1434 type.id() == ID_rational || type.id() == ID_integer ||
1435 type.id() == ID_real)
1436 {
1437 out << "(- ";
1439 out << ")";
1440 }
1441 else if(type.id() == ID_range)
1442 {
1443 auto &range_type = to_range_type(type);
1444 PRECONDITION(type == unary_minus_expr.op().type());
1445 // turn -x into 0-x
1446 auto minus_expr =
1447 minus_exprt{range_type.zero_expr(), unary_minus_expr.op()};
1449 }
1450 else if(type.id() == ID_floatbv)
1451 {
1452 // this has no rounding mode
1453 if(use_FPA_theory)
1454 {
1455 out << "(fp.neg ";
1457 out << ")";
1458 }
1459 else
1461 }
1462 else
1463 {
1464 PRECONDITION(type.id() != ID_natural);
1465 out << "(bvneg ";
1467 out << ")";
1468 }
1469 }
1470 else if(expr.id()==ID_unary_plus)
1471 {
1472 // A no-op (apart from type promotion)
1473 convert_expr(to_unary_plus_expr(expr).op());
1474 }
1475 else if(expr.id()==ID_sign)
1476 {
1477 const sign_exprt &sign_expr = to_sign_expr(expr);
1478
1479 const typet &op_type = sign_expr.op().type();
1480
1481 if(op_type.id()==ID_floatbv)
1482 {
1483 if(use_FPA_theory)
1484 {
1485 out << "(fp.isNegative ";
1486 convert_expr(sign_expr.op());
1487 out << ")";
1488 }
1489 else
1491 }
1492 else if(op_type.id()==ID_signedbv)
1493 {
1494 std::size_t op_width=to_signedbv_type(op_type).get_width();
1495
1496 out << "(bvslt ";
1497 convert_expr(sign_expr.op());
1498 out << " (_ bv0 " << op_width << "))";
1499 }
1500 else
1502 false,
1503 "sign should not be applied to unsupported type",
1504 sign_expr.type().id_string());
1505 }
1506 else if(expr.id()==ID_if)
1507 {
1508 const if_exprt &if_expr = to_if_expr(expr);
1509
1510 out << "(ite ";
1511 convert_expr(if_expr.cond());
1512 out << " ";
1513 if(
1514 expr.type().id() == ID_array && !use_array_theory(if_expr.true_case()) &&
1515 use_array_theory(if_expr.false_case()))
1516 {
1517 unflatten(wheret::BEGIN, expr.type());
1518
1519 convert_expr(if_expr.true_case());
1520
1521 unflatten(wheret::END, expr.type());
1522 }
1523 else
1524 {
1525 convert_expr(if_expr.true_case());
1526 }
1527 out << " ";
1528 if(
1529 expr.type().id() == ID_array && use_array_theory(if_expr.true_case()) &&
1530 !use_array_theory(if_expr.false_case()))
1531 {
1532 unflatten(wheret::BEGIN, expr.type());
1533
1534 convert_expr(if_expr.false_case());
1535
1536 unflatten(wheret::END, expr.type());
1537 }
1538 else
1539 {
1540 convert_expr(if_expr.false_case());
1541 }
1542 out << ")";
1543 }
1544 else if(expr.id()==ID_and ||
1545 expr.id()==ID_or ||
1546 expr.id()==ID_xor)
1547 {
1549 expr.is_boolean(),
1550 "logical and, or, and xor expressions should have Boolean type");
1552 expr.operands().size() >= 2,
1553 "logical and, or, and xor expressions should have at least two operands");
1554
1555 out << "(" << expr.id();
1556 for(const auto &op : expr.operands())
1557 {
1558 out << " ";
1559 convert_expr(op);
1560 }
1561 out << ")";
1562 }
1563 else if(expr.id() == ID_nand || expr.id() == ID_nor || expr.id() == ID_xnor)
1564 {
1566 expr.is_boolean(),
1567 "logical nand, nor, xnor expressions should have Boolean type");
1569 expr.operands().size() >= 1,
1570 "logical nand, nor, xnor expressions should have at least one operand");
1571
1572 // SMT-LIB doesn't have nand, nor, xnor
1573 out << "(not ";
1574 if(expr.operands().size() == 1)
1575 convert_expr(to_multi_ary_expr(expr).op0());
1576 else
1577 {
1578 if(expr.id() == ID_nand)
1579 out << "(and";
1580 else if(expr.id() == ID_nor)
1581 out << "(and";
1582 else if(expr.id() == ID_xnor)
1583 out << "(xor";
1584 else
1585 DATA_INVARIANT(false, "unexpected expression");
1586 for(const auto &op : expr.operands())
1587 {
1588 out << ' ';
1589 convert_expr(op);
1590 }
1591 out << ')'; // or, and, xor
1592 }
1593 out << ')'; // not
1594 }
1595 else if(expr.id()==ID_implies)
1596 {
1598
1600 implies_expr.is_boolean(), "implies expression should have Boolean type");
1601
1602 out << "(=> ";
1604 out << " ";
1606 out << ")";
1607 }
1608 else if(expr.id()==ID_not)
1609 {
1610 const not_exprt &not_expr = to_not_expr(expr);
1611
1613 not_expr.is_boolean(), "not expression should have Boolean type");
1614
1615 out << "(not ";
1616 convert_expr(not_expr.op());
1617 out << ")";
1618 }
1619 else if(expr.id() == ID_equal)
1620 {
1621 const equal_exprt &equal_expr = to_equal_expr(expr);
1622
1624 equal_expr.op0().type() == equal_expr.op1().type(),
1625 "operands of equal expression shall have same type");
1626
1627 if(is_zero_width(equal_expr.lhs().type(), ns))
1628 {
1630 }
1631 else
1632 {
1633 out << "(= ";
1634 convert_expr(equal_expr.op0());
1635 out << " ";
1636 convert_expr(equal_expr.op1());
1637 out << ")";
1638 }
1639 }
1640 else if(expr.id() == ID_notequal)
1641 {
1643
1645 notequal_expr.op0().type() == notequal_expr.op1().type(),
1646 "operands of not equal expression shall have same type");
1647
1648 out << "(not (= ";
1650 out << " ";
1652 out << "))";
1653 }
1654 else if(expr.id()==ID_ieee_float_equal ||
1655 expr.id()==ID_ieee_float_notequal)
1656 {
1657 // These are not the same as (= A B)
1658 // because of NaN and negative zero.
1659 const auto &rel_expr = to_binary_relation_expr(expr);
1660
1662 rel_expr.lhs().type() == rel_expr.rhs().type(),
1663 "operands of float equal and not equal expressions shall have same type");
1664
1665 // The FPA theory properly treats NaN and negative zero.
1666 if(use_FPA_theory)
1667 {
1669 out << "(not ";
1670
1671 out << "(fp.eq ";
1672 convert_expr(rel_expr.lhs());
1673 out << " ";
1674 convert_expr(rel_expr.rhs());
1675 out << ")";
1676
1678 out << ")";
1679 }
1680 else
1681 convert_floatbv(expr);
1682 }
1683 else if(expr.id()==ID_le ||
1684 expr.id()==ID_lt ||
1685 expr.id()==ID_ge ||
1686 expr.id()==ID_gt)
1687 {
1689 }
1690 else if(expr.id()==ID_plus)
1691 {
1693 }
1694 else if(expr.id()==ID_floatbv_plus)
1695 {
1697 }
1698 else if(expr.id()==ID_minus)
1699 {
1701 }
1702 else if(expr.id()==ID_floatbv_minus)
1703 {
1705 }
1706 else if(expr.id()==ID_div)
1707 {
1708 convert_div(to_div_expr(expr));
1709 }
1710 else if(expr.id()==ID_floatbv_div)
1711 {
1713 }
1714 else if(expr.id()==ID_mod)
1715 {
1716 convert_mod(to_mod_expr(expr));
1717 }
1718 else if(expr.id() == ID_euclidean_mod)
1719 {
1721 }
1722 else if(expr.id()==ID_mult)
1723 {
1725 }
1726 else if(expr.id()==ID_floatbv_mult)
1727 {
1729 }
1730 else if(expr.id() == ID_floatbv_rem)
1731 {
1733 }
1734 else if(expr.id()==ID_address_of)
1735 {
1739 }
1740 else if(expr.id() == ID_array_of)
1741 {
1742 const auto &array_of_expr = to_array_of_expr(expr);
1743
1745 array_of_expr.type().id() == ID_array,
1746 "array of expression shall have array type");
1747
1748 if(use_as_const)
1749 {
1750 out << "((as const ";
1752 out << ") ";
1754 out << ")";
1755 }
1756 else
1757 {
1758 defined_expressionst::const_iterator it =
1760 CHECK_RETURN(it != defined_expressions.end());
1761 out << it->second;
1762 }
1763 }
1764 else if(expr.id() == ID_array_comprehension)
1765 {
1767
1769 array_comprehension.type().id() == ID_array,
1770 "array_comprehension expression shall have array type");
1771
1773 {
1774 out << "(lambda ((";
1776 out << " ";
1777 convert_type(array_comprehension.type().size().type());
1778 out << ")) ";
1780 out << ")";
1781 }
1782 else
1783 {
1784 const auto &it = defined_expressions.find(array_comprehension);
1785 CHECK_RETURN(it != defined_expressions.end());
1786 out << it->second;
1787 }
1788 }
1789 else if(expr.id()==ID_index)
1790 {
1792 }
1793 else if(expr.id()==ID_ashr ||
1794 expr.id()==ID_lshr ||
1795 expr.id()==ID_shl)
1796 {
1797 const shift_exprt &shift_expr = to_shift_expr(expr);
1798 const typet &type = shift_expr.type();
1799
1800 if(type.id()==ID_unsignedbv ||
1801 type.id()==ID_signedbv ||
1802 type.id()==ID_bv)
1803 {
1804 if(shift_expr.id() == ID_ashr)
1805 out << "(bvashr ";
1806 else if(shift_expr.id() == ID_lshr)
1807 out << "(bvlshr ";
1808 else if(shift_expr.id() == ID_shl)
1809 out << "(bvshl ";
1810 else
1812
1814 out << " ";
1815
1816 // SMT2 requires the shift distance to have the same width as
1817 // the value that is shifted -- odd!
1818
1819 const auto &distance_type = shift_expr.distance().type();
1820 if(distance_type.id() == ID_integer || distance_type.id() == ID_natural)
1821 {
1822 const mp_integer i =
1824
1825 // shift distance must be bit vector
1826 std::size_t width_op0 = boolbv_width(shift_expr.op().type());
1829 }
1830 else if(
1831 distance_type.id() == ID_signedbv ||
1832 distance_type.id() == ID_unsignedbv ||
1834 {
1835 std::size_t width_op0 = boolbv_width(shift_expr.op().type());
1836 std::size_t width_op1 = boolbv_width(distance_type);
1837
1838 if(width_op0==width_op1)
1839 convert_expr(shift_expr.distance());
1840 else if(width_op0>width_op1)
1841 {
1842 out << "((_ zero_extend " << width_op0-width_op1 << ") ";
1843 convert_expr(shift_expr.distance());
1844 out << ")"; // zero_extend
1845 }
1846 else // width_op0<width_op1
1847 {
1848 out << "((_ extract " << width_op0-1 << " 0) ";
1849 convert_expr(shift_expr.distance());
1850 out << ")"; // extract
1851 }
1852 }
1853 else
1854 {
1856 "unsupported distance type for " + shift_expr.id_string() + ": " +
1857 distance_type.id_string());
1858 }
1859
1860 out << ")"; // bv*sh
1861 }
1862 else
1864 "unsupported type for " + shift_expr.id_string() + ": " +
1865 type.id_string());
1866 }
1867 else if(expr.id() == ID_rol || expr.id() == ID_ror)
1868 {
1869 const shift_exprt &shift_expr = to_shift_expr(expr);
1870 const typet &type = shift_expr.type();
1871
1872 if(
1873 type.id() == ID_unsignedbv || type.id() == ID_signedbv ||
1874 type.id() == ID_bv)
1875 {
1876 // SMT-LIB offers rotate_left and rotate_right, but these require a
1877 // constant distance.
1878 if(shift_expr.id() == ID_rol)
1879 out << "((_ rotate_left";
1880 else if(shift_expr.id() == ID_ror)
1881 out << "((_ rotate_right";
1882 else
1884
1885 out << ' ';
1886
1888
1889 if(distance_int_op.has_value())
1890 {
1891 out << distance_int_op.value();
1892 }
1893 else
1895 "distance type for " + shift_expr.id_string() + "must be constant");
1896
1897 out << ") ";
1899
1900 out << ")"; // rotate_*
1901 }
1902 else
1904 "unsupported type for " + shift_expr.id_string() + ": " +
1905 type.id_string());
1906 }
1907 else if(expr.id() == ID_named_term)
1908 {
1909 const auto &named_term_expr = to_named_term_expr(expr);
1910 out << "(! ";
1911 convert(named_term_expr.value());
1912 out << " :named "
1913 << convert_identifier(named_term_expr.symbol().get_identifier()) << ')';
1914 }
1915 else if(expr.id()==ID_with)
1916 {
1918 }
1919 else if(expr.id()==ID_update)
1920 {
1922 }
1923 else if(expr.id() == ID_update_bit)
1924 {
1926 }
1927 else if(expr.id() == ID_update_bits)
1928 {
1930 }
1931 else if(expr.id() == ID_object_address)
1932 {
1933 out << "(object-address ";
1935 id2string(to_object_address_expr(expr).object_identifier()));
1936 out << ')';
1937 }
1938 else if(expr.id() == ID_element_address)
1939 {
1940 // We turn this binary expression into a ternary expression
1941 // by adding the size of the array elements as third argument.
1943
1945 ::size_of_expr(element_address_expr.element_type(), ns);
1947
1948 out << "(element-address-" << type2id(expr.type()) << ' ';
1950 out << ' ';
1952 out << ' ';
1955 out << ')';
1956 }
1957 else if(expr.id() == ID_field_address)
1958 {
1959 const auto &field_address_expr = to_field_address_expr(expr);
1960 out << "(field-address-" << type2id(expr.type()) << ' ';
1962 out << ' ';
1964 out << ')';
1965 }
1966 else if(expr.id()==ID_member)
1967 {
1969 }
1970 else if(expr.id()==ID_pointer_offset)
1971 {
1972 const auto &op = to_pointer_offset_expr(expr).pointer();
1973
1975 op.type().id() == ID_pointer,
1976 "operand of pointer offset expression shall be of pointer type");
1977
1978 std::size_t offset_bits =
1979 boolbv_width(op.type()) - config.bv_encoding.object_bits;
1980 std::size_t result_width=boolbv_width(expr.type());
1981
1982 // max extract width
1985
1986 // too few bits?
1988 out << "((_ zero_extend " << result_width-offset_bits << ") ";
1989
1990 out << "((_ extract " << offset_bits-1 << " 0) ";
1991 convert_expr(op);
1992 out << ")";
1993
1995 out << ")"; // zero_extend
1996 }
1997 else if(expr.id()==ID_pointer_object)
1998 {
1999 const auto &op = to_pointer_object_expr(expr).pointer();
2000
2002 op.type().id() == ID_pointer,
2003 "pointer object expressions should be of pointer type");
2004
2005 std::size_t ext=boolbv_width(expr.type())-config.bv_encoding.object_bits;
2006 std::size_t pointer_width = boolbv_width(op.type());
2007
2008 if(ext>0)
2009 out << "((_ zero_extend " << ext << ") ";
2010
2011 out << "((_ extract "
2012 << pointer_width-1 << " "
2013 << pointer_width-config.bv_encoding.object_bits << ") ";
2014 convert_expr(op);
2015 out << ")";
2016
2017 if(ext>0)
2018 out << ")"; // zero_extend
2019 }
2020 else if(expr.id() == ID_is_dynamic_object)
2021 {
2023 }
2024 else if(expr.id() == ID_is_invalid_pointer)
2025 {
2026 const auto &op = to_unary_expr(expr).op();
2027 std::size_t pointer_width = boolbv_width(op.type());
2028 out << "(= ((_ extract "
2029 << pointer_width-1 << " "
2030 << pointer_width-config.bv_encoding.object_bits << ") ";
2031 convert_expr(op);
2032 out << ") (_ bv" << pointer_logic.get_invalid_object()
2033 << " " << config.bv_encoding.object_bits << "))";
2034 }
2035 else if(expr.id()==ID_string_constant)
2036 {
2037 defined_expressionst::const_iterator it=defined_expressions.find(expr);
2038 CHECK_RETURN(it != defined_expressions.end());
2039 out << it->second;
2040 }
2041 else if(expr.id()==ID_extractbit)
2042 {
2044
2045 if(extractbit_expr.index().is_constant())
2046 {
2047 const mp_integer i =
2049
2050 out << "(= ((_ extract " << i << " " << i << ") ";
2052 out << ") #b1)";
2053 }
2054 else
2055 {
2056 out << "(= ((_ extract 0 0) ";
2057 // the arguments of the shift need to have the same width
2058 out << "(bvlshr ";
2060 out << ' ';
2061 typecast_exprt tmp(extractbit_expr.index(), extractbit_expr.src().type());
2063 out << ")) #b1)"; // bvlshr, extract, =
2064 }
2065 }
2066 else if(expr.id() == ID_onehot)
2067 {
2068 convert_expr(to_onehot_expr(expr).lower());
2069 }
2070 else if(expr.id() == ID_onehot0)
2071 {
2072 convert_expr(to_onehot0_expr(expr).lower());
2073 }
2074 else if(expr.id()==ID_extractbits)
2075 {
2077 auto width = boolbv_width(expr.type());
2078
2079 if(extractbits_expr.index().is_constant())
2080 {
2083
2084 out << "((_ extract " << (width + index_i - 1) << " " << index_i << ") ";
2086 out << ")";
2087 }
2088 else
2089 {
2090 #if 0
2091 out << "(= ((_ extract 0 0) ";
2092 // the arguments of the shift need to have the same width
2093 out << "(bvlshr ";
2094 convert_expr(expr.op0());
2095 typecast_exprt tmp(expr.op0().type());
2096 tmp.op0()=expr.op1();
2098 out << ")) bin1)"; // bvlshr, extract, =
2099 #endif
2100 SMT2_TODO("smt2: extractbits with non-constant index");
2101 }
2102 }
2103 else if(expr.id()==ID_replication)
2104 {
2106
2108
2109 // SMT-LIB requires that repeat is given a number of repetitions that is at
2110 // least 1.
2111 PRECONDITION(times >= 1);
2112
2113 out << "((_ repeat " << times << ") ";
2115 out << ")";
2116 }
2117 else if(expr.id()==ID_byte_extract_little_endian ||
2119 {
2120 INVARIANT(
2121 false, "byte_extract ops should be lowered in prepare_for_convert_expr");
2122 }
2123 else if(expr.id()==ID_byte_update_little_endian ||
2125 {
2126 INVARIANT(
2127 false, "byte_update ops should be lowered in prepare_for_convert_expr");
2128 }
2129 else if(expr.id()==ID_abs)
2130 {
2131 const abs_exprt &abs_expr = to_abs_expr(expr);
2132
2133 const typet &type = abs_expr.type();
2134
2135 if(type.id()==ID_signedbv)
2136 {
2137 std::size_t result_width = to_signedbv_type(type).get_width();
2138
2139 out << "(ite (bvslt ";
2140 convert_expr(abs_expr.op());
2141 out << " (_ bv0 " << result_width << ")) ";
2142 out << "(bvneg ";
2143 convert_expr(abs_expr.op());
2144 out << ") ";
2145 convert_expr(abs_expr.op());
2146 out << ")";
2147 }
2148 else if(type.id()==ID_fixedbv)
2149 {
2150 std::size_t result_width=to_fixedbv_type(type).get_width();
2151
2152 out << "(ite (bvslt ";
2153 convert_expr(abs_expr.op());
2154 out << " (_ bv0 " << result_width << ")) ";
2155 out << "(bvneg ";
2156 convert_expr(abs_expr.op());
2157 out << ") ";
2158 convert_expr(abs_expr.op());
2159 out << ")";
2160 }
2161 else if(type.id()==ID_floatbv)
2162 {
2163 if(use_FPA_theory)
2164 {
2165 out << "(fp.abs ";
2166 convert_expr(abs_expr.op());
2167 out << ")";
2168 }
2169 else
2171 }
2172 else
2174 }
2175 else if(expr.id()==ID_isnan)
2176 {
2177 const isnan_exprt &isnan_expr = to_isnan_expr(expr);
2178
2179 const typet &op_type = isnan_expr.op().type();
2180
2181 if(op_type.id()==ID_fixedbv)
2182 out << "false";
2183 else if(op_type.id()==ID_floatbv)
2184 {
2185 if(use_FPA_theory)
2186 {
2187 out << "(fp.isNaN ";
2189 out << ")";
2190 }
2191 else
2193 }
2194 else
2196 }
2197 else if(expr.id()==ID_isfinite)
2198 {
2200
2201 const typet &op_type = isfinite_expr.op().type();
2202
2203 if(op_type.id()==ID_fixedbv)
2204 out << "true";
2205 else if(op_type.id()==ID_floatbv)
2206 {
2207 if(use_FPA_theory)
2208 {
2209 out << "(and ";
2210
2211 out << "(not (fp.isNaN ";
2213 out << "))";
2214
2215 out << "(not (fp.isInfinite ";
2217 out << "))";
2218
2219 out << ")";
2220 }
2221 else
2223 }
2224 else
2226 }
2227 else if(expr.id()==ID_isinf)
2228 {
2229 const isinf_exprt &isinf_expr = to_isinf_expr(expr);
2230
2231 const typet &op_type = isinf_expr.op().type();
2232
2233 if(op_type.id()==ID_fixedbv)
2234 out << "false";
2235 else if(op_type.id()==ID_floatbv)
2236 {
2237 if(use_FPA_theory)
2238 {
2239 out << "(fp.isInfinite ";
2241 out << ")";
2242 }
2243 else
2245 }
2246 else
2248 }
2249 else if(expr.id()==ID_isnormal)
2250 {
2252
2253 const typet &op_type = isnormal_expr.op().type();
2254
2255 if(op_type.id()==ID_fixedbv)
2256 out << "true";
2257 else if(op_type.id()==ID_floatbv)
2258 {
2259 if(use_FPA_theory)
2260 {
2261 out << "(fp.isNormal ";
2263 out << ")";
2264 }
2265 else
2267 }
2268 else
2270 }
2271 else if(
2274 expr.id() == ID_overflow_result_plus ||
2275 expr.id() == ID_overflow_result_minus)
2276 {
2278
2279 const auto &op0 = to_binary_expr(expr).op0();
2280 const auto &op1 = to_binary_expr(expr).op1();
2281
2283 keep_result || expr.is_boolean(),
2284 "overflow plus and overflow minus expressions shall be of Boolean type");
2285
2286 bool subtract = can_cast_expr<minus_overflow_exprt>(expr) ||
2287 expr.id() == ID_overflow_result_minus;
2288 const typet &op_type = op0.type();
2289 std::size_t width=boolbv_width(op_type);
2290
2291 if(op_type.id()==ID_signedbv)
2292 {
2293 // an overflow occurs if the top two bits of the extended sum differ
2294 out << "(let ((?sum (";
2295 out << (subtract?"bvsub":"bvadd");
2296 out << " ((_ sign_extend 1) ";
2297 convert_expr(op0);
2298 out << ")";
2299 out << " ((_ sign_extend 1) ";
2300 convert_expr(op1);
2301 out << ")))) "; // sign_extend, bvadd/sub
2302 if(keep_result)
2303 {
2304 if(use_datatypes)
2305 {
2306 const std::string &smt_typename = datatype_map.at(expr.type());
2307
2308 // use the constructor for the Z3 datatype
2309 out << "(mk-" << smt_typename;
2310 }
2311 else
2312 out << "(concat";
2313
2314 out << " ((_ extract " << width - 1 << " 0) ?sum) ";
2315 if(!use_datatypes)
2316 out << "(ite ";
2317 }
2318 out << "(not (= "
2319 "((_ extract " << width << " " << width << ") ?sum) "
2320 "((_ extract " << (width-1) << " " << (width-1) << ") ?sum)";
2321 out << "))"; // =, not
2322 if(keep_result)
2323 {
2324 if(!use_datatypes)
2325 out << " #b1 #b0)";
2326 out << ")"; // concat
2327 }
2328 out << ")"; // let
2329 }
2330 else if(op_type.id()==ID_unsignedbv ||
2331 op_type.id()==ID_pointer)
2332 {
2333 // overflow is simply carry-out
2334 out << "(let ((?sum (" << (subtract ? "bvsub" : "bvadd");
2335 out << " ((_ zero_extend 1) ";
2336 convert_expr(op0);
2337 out << ")";
2338 out << " ((_ zero_extend 1) ";
2339 convert_expr(op1);
2340 out << "))))"; // zero_extend, bvsub/bvadd
2342 out << " ?sum";
2343 else
2344 {
2346 {
2347 const std::string &smt_typename = datatype_map.at(expr.type());
2348
2349 // use the constructor for the Z3 datatype
2350 out << "(mk-" << smt_typename;
2351 out << " ((_ extract " << width - 1 << " 0) ?sum) ";
2352 }
2353
2354 out << "(= ";
2355 out << "((_ extract " << width << " " << width << ") ?sum)";
2356 out << "#b1)"; // =
2357
2359 out << ")"; // mk
2360 }
2361 out << ")"; // let
2362 }
2363 else
2365 false,
2366 "overflow check should not be performed on unsupported type",
2367 op_type.id_string());
2368 }
2369 else if(
2371 expr.id() == ID_overflow_result_mult)
2372 {
2374
2375 const auto &op0 = to_binary_expr(expr).op0();
2376 const auto &op1 = to_binary_expr(expr).op1();
2377
2379 keep_result || expr.is_boolean(),
2380 "overflow mult expression shall be of Boolean type");
2381
2382 // No better idea than to multiply with double the bits and then compare
2383 // with max value.
2384
2385 const typet &op_type = op0.type();
2386 std::size_t width=boolbv_width(op_type);
2387
2388 if(op_type.id()==ID_signedbv)
2389 {
2390 out << "(let ( (prod (bvmul ((_ sign_extend " << width << ") ";
2391 convert_expr(op0);
2392 out << ") ((_ sign_extend " << width << ") ";
2393 convert_expr(op1);
2394 out << ")) )) ";
2395 if(keep_result)
2396 {
2397 if(use_datatypes)
2398 {
2399 const std::string &smt_typename = datatype_map.at(expr.type());
2400
2401 // use the constructor for the Z3 datatype
2402 out << "(mk-" << smt_typename;
2403 }
2404 else
2405 out << "(concat";
2406
2407 out << " ((_ extract " << width - 1 << " 0) prod) ";
2408 if(!use_datatypes)
2409 out << "(ite ";
2410 }
2411 out << "(or (bvsge prod (_ bv" << power(2, width-1) << " "
2412 << width*2 << "))";
2413 out << " (bvslt prod (bvneg (_ bv" << power(2, width - 1) << " "
2414 << width * 2 << "))))";
2415 if(keep_result)
2416 {
2417 if(!use_datatypes)
2418 out << " #b1 #b0)";
2419 out << ")"; // concat
2420 }
2421 out << ")";
2422 }
2423 else if(op_type.id()==ID_unsignedbv)
2424 {
2425 out << "(let ((prod (bvmul ((_ zero_extend " << width << ") ";
2426 convert_expr(op0);
2427 out << ") ((_ zero_extend " << width << ") ";
2428 convert_expr(op1);
2429 out << ")))) ";
2430 if(keep_result)
2431 {
2432 if(use_datatypes)
2433 {
2434 const std::string &smt_typename = datatype_map.at(expr.type());
2435
2436 // use the constructor for the Z3 datatype
2437 out << "(mk-" << smt_typename;
2438 }
2439 else
2440 out << "(concat";
2441
2442 out << " ((_ extract " << width - 1 << " 0) prod) ";
2443 if(!use_datatypes)
2444 out << "(ite ";
2445 }
2446 out << "(bvuge prod (_ bv" << power(2, width) << " " << width * 2 << "))";
2447 if(keep_result)
2448 {
2449 if(!use_datatypes)
2450 out << " #b1 #b0)";
2451 out << ")"; // concat
2452 }
2453 out << ")";
2454 }
2455 else
2457 false,
2458 "overflow check should not be performed on unsupported type",
2459 op_type.id_string());
2460 }
2461 else if(expr.id() == ID_saturating_plus || expr.id() == ID_saturating_minus)
2462 {
2463 const bool subtract = expr.id() == ID_saturating_minus;
2464 const auto &op_type = expr.type();
2465 const auto &op0 = to_binary_expr(expr).op0();
2466 const auto &op1 = to_binary_expr(expr).op1();
2467
2468 if(op_type.id() == ID_signedbv)
2469 {
2470 auto width = to_signedbv_type(op_type).get_width();
2471
2472 // compute sum with one extra bit
2473 out << "(let ((?sum (";
2474 out << (subtract ? "bvsub" : "bvadd");
2475 out << " ((_ sign_extend 1) ";
2476 convert_expr(op0);
2477 out << ")";
2478 out << " ((_ sign_extend 1) ";
2479 convert_expr(op1);
2480 out << ")))) "; // sign_extend, bvadd/sub
2481
2482 // pick one of MAX, MIN, or the sum
2483 out << "(ite (= "
2484 "((_ extract "
2485 << width << " " << width
2486 << ") ?sum) "
2487 "((_ extract "
2488 << (width - 1) << " " << (width - 1) << ") ?sum)";
2489 out << ") "; // =
2490
2491 // no overflow and no underflow case, return the sum
2492 out << "((_ extract " << width - 1 << " 0) ?sum) ";
2493
2494 // MAX
2495 out << "(ite (= ((_ extract " << width << " " << width << ") ?sum) #b0) ";
2496 convert_expr(to_signedbv_type(op_type).largest_expr());
2497
2498 // MIN
2499 convert_expr(to_signedbv_type(op_type).smallest_expr());
2500 out << ")))"; // ite, ite, let
2501 }
2502 else if(op_type.id() == ID_unsignedbv)
2503 {
2504 auto width = to_unsignedbv_type(op_type).get_width();
2505
2506 // compute sum with one extra bit
2507 out << "(let ((?sum (" << (subtract ? "bvsub" : "bvadd");
2508 out << " ((_ zero_extend 1) ";
2509 convert_expr(op0);
2510 out << ")";
2511 out << " ((_ zero_extend 1) ";
2512 convert_expr(op1);
2513 out << "))))"; // zero_extend, bvsub/bvadd
2514
2515 // pick one of MAX, MIN, or the sum
2516 out << "(ite (= ((_ extract " << width << " " << width << ") ?sum) #b0) ";
2517
2518 // no overflow and no underflow case, return the sum
2519 out << " ((_ extract " << width - 1 << " 0) ?sum) ";
2520
2521 // overflow when adding, underflow when subtracting
2522 if(subtract)
2523 convert_expr(to_unsignedbv_type(op_type).smallest_expr());
2524 else
2525 convert_expr(to_unsignedbv_type(op_type).largest_expr());
2526
2527 // MIN
2528 out << "))"; // ite, let
2529 }
2530 else
2532 false,
2533 "saturating_plus/minus on unsupported type",
2534 op_type.id_string());
2535 }
2536 else if(expr.id()==ID_array)
2537 {
2538 defined_expressionst::const_iterator it=defined_expressions.find(expr);
2539 CHECK_RETURN(it != defined_expressions.end());
2540 out << it->second;
2541 }
2542 else if(expr.id()==ID_literal)
2543 {
2544 convert_literal(to_literal_expr(expr).get_literal());
2545 }
2546 else if(expr.id()==ID_forall ||
2547 expr.id()==ID_exists)
2548 {
2550
2552 // NOLINTNEXTLINE(readability/throw)
2553 throw "MathSAT does not support quantifiers";
2554
2555 if(quantifier_expr.id() == ID_forall)
2556 out << "(forall ";
2557 else if(quantifier_expr.id() == ID_exists)
2558 out << "(exists ";
2559
2560 out << '(';
2561 bool first = true;
2562 for(const auto &bound : quantifier_expr.variables())
2563 {
2564 if(first)
2565 first = false;
2566 else
2567 out << ' ';
2568 out << '(';
2570 out << ' ';
2571 convert_type(bound.type());
2572 out << ')';
2573 }
2574 out << ") ";
2575
2577
2578 out << ')';
2579 }
2580 else if(
2582 {
2584 }
2585 else if(expr.id()==ID_let)
2586 {
2587 const let_exprt &let_expr=to_let_expr(expr);
2588 const auto &variables = let_expr.variables();
2589 const auto &values = let_expr.values();
2590
2591 out << "(let (";
2592 bool first = true;
2593
2594 for(auto &binding : make_range(variables).zip(values))
2595 {
2596 if(first)
2597 first = false;
2598 else
2599 out << ' ';
2600
2601 out << '(';
2602 convert_expr(binding.first);
2603 out << ' ';
2604 convert_expr(binding.second);
2605 out << ')';
2606 }
2607
2608 out << ") "; // bindings
2609
2610 convert_expr(let_expr.where());
2611 out << ')'; // let
2612 }
2613 else if(expr.id()==ID_constraint_select_one)
2614 {
2616 "smt2_convt::convert_expr: '" + expr.id_string() +
2617 "' is not yet supported");
2618 }
2619 else if(expr.id() == ID_bswap)
2620 {
2621 const bswap_exprt &bswap_expr = to_bswap_expr(expr);
2622
2624 bswap_expr.op().type() == bswap_expr.type(),
2625 "operand of byte swap expression shall have same type as the expression");
2626
2627 // first 'let' the operand
2628 out << "(let ((bswap_op ";
2630 out << ")) ";
2631
2632 if(
2633 bswap_expr.type().id() == ID_signedbv ||
2634 bswap_expr.type().id() == ID_unsignedbv)
2635 {
2636 const std::size_t width =
2637 to_bitvector_type(bswap_expr.type()).get_width();
2638
2639 const std::size_t bits_per_byte = bswap_expr.get_bits_per_byte();
2640
2641 // width must be multiple of bytes
2643 width % bits_per_byte == 0,
2644 "bit width indicated by type of bswap expression should be a multiple "
2645 "of the number of bits per byte");
2646
2647 const std::size_t bytes = width / bits_per_byte;
2648
2649 if(bytes <= 1)
2650 out << "bswap_op";
2651 else
2652 {
2653 // do a parallel 'let' for each byte
2654 out << "(let (";
2655
2656 for(std::size_t byte = 0; byte < bytes; byte++)
2657 {
2658 if(byte != 0)
2659 out << ' ';
2660 out << "(bswap_byte_" << byte << ' ';
2661 out << "((_ extract " << (byte * bits_per_byte + (bits_per_byte - 1))
2662 << " " << (byte * bits_per_byte) << ") bswap_op)";
2663 out << ')';
2664 }
2665
2666 out << ") ";
2667
2668 // now stitch back together with 'concat'
2669 out << "(concat";
2670
2671 for(std::size_t byte = 0; byte < bytes; byte++)
2672 out << " bswap_byte_" << byte;
2673
2674 out << ')'; // concat
2675 out << ')'; // let bswap_byte_*
2676 }
2677 }
2678 else
2679 UNEXPECTEDCASE("bswap must get bitvector operand");
2680
2681 out << ')'; // let bswap_op
2682 }
2683 else if(expr.id() == ID_popcount)
2684 {
2686 }
2687 else if(expr.id() == ID_count_leading_zeros)
2688 {
2690 }
2691 else if(expr.id() == ID_count_trailing_zeros)
2692 {
2694 }
2695 else if(expr.id() == ID_find_first_set)
2696 {
2698 }
2699 else if(expr.id() == ID_bitreverse)
2700 {
2702 }
2703 else if(expr.id() == ID_zero_extend)
2704 {
2705 convert_expr(to_zero_extend_expr(expr).lower());
2706 }
2707 else if(expr.id() == ID_function_application)
2708 {
2710 // do not use parentheses if there function is a constant
2711 if(function_application_expr.arguments().empty())
2712 {
2714 }
2715 else
2716 {
2717 out << '(';
2719 for(auto &op : function_application_expr.arguments())
2720 {
2721 out << ' ';
2722 convert_expr(op);
2723 }
2724 out << ')';
2725 }
2726 }
2727 else if(expr.id() == ID_cond)
2728 {
2729 // use the lowering
2730 convert_expr(to_cond_expr(expr).lower());
2731 }
2732 else
2734 false,
2735 "smt2_convt::convert_expr should not be applied to unsupported "
2736 "expression",
2737 expr.id_string());
2738}
2739
2741{
2742 const exprt &src = expr.op();
2743
2744 typet dest_type = expr.type();
2745
2746 if(dest_type == src.type()) // identity
2747 {
2748 convert_expr(src);
2749 return;
2750 }
2751
2752 if(dest_type.id()==ID_c_enum_tag)
2754
2755 typet src_type = src.type();
2756 if(src_type.id()==ID_c_enum_tag)
2758
2759 if(dest_type.id()==ID_bool)
2760 {
2761 // this is comparison with zero
2762 if(
2763 src_type.id() == ID_signedbv || src_type.id() == ID_unsignedbv ||
2764 src_type.id() == ID_c_bool || src_type.id() == ID_fixedbv ||
2765 src_type.id() == ID_pointer || src_type.id() == ID_integer ||
2766 src_type.id() == ID_natural || src_type.id() == ID_rational ||
2767 src_type.id() == ID_real)
2768 {
2769 out << "(not (= ";
2770 convert_expr(src);
2771 out << " ";
2773 out << "))";
2774 }
2775 else if(src_type.id()==ID_floatbv)
2776 {
2777 if(use_FPA_theory)
2778 {
2779 out << "(not (fp.isZero ";
2780 convert_expr(src);
2781 out << "))";
2782 }
2783 else
2784 convert_floatbv(expr);
2785 }
2786 else
2787 {
2788 UNEXPECTEDCASE("TODO typecast1 "+src_type.id_string()+" -> bool");
2789 }
2790 }
2791 else if(dest_type.id()==ID_c_bool)
2792 {
2793 std::size_t to_width=boolbv_width(dest_type);
2794 out << "(ite ";
2795 out << "(not (= ";
2796 convert_expr(src);
2797 out << " ";
2799 out << "))"; // not, =
2800 out << " (_ bv1 " << to_width << ")";
2801 out << " (_ bv0 " << to_width << ")";
2802 out << ")"; // ite
2803 }
2804 else if(dest_type.id()==ID_signedbv ||
2805 dest_type.id()==ID_unsignedbv ||
2806 dest_type.id()==ID_c_enum ||
2807 dest_type.id()==ID_bv)
2808 {
2809 std::size_t to_width=boolbv_width(dest_type);
2810
2811 if(src_type.id()==ID_signedbv || // from signedbv
2812 src_type.id()==ID_unsignedbv || // from unsigedbv
2813 src_type.id()==ID_c_bool ||
2814 src_type.id()==ID_c_enum ||
2815 src_type.id()==ID_bv)
2816 {
2817 std::size_t from_width=boolbv_width(src_type);
2818
2819 if(from_width==to_width)
2820 convert_expr(src); // ignore
2821 else if(from_width<to_width) // extend
2822 {
2823 if(src_type.id()==ID_signedbv)
2824 out << "((_ sign_extend ";
2825 else
2826 out << "((_ zero_extend ";
2827
2829 << ") "; // ind
2830 convert_expr(src);
2831 out << ")";
2832 }
2833 else // chop off extra bits
2834 {
2835 out << "((_ extract " << (to_width-1) << " 0) ";
2836 convert_expr(src);
2837 out << ")";
2838 }
2839 }
2840 else if(src_type.id()==ID_fixedbv) // from fixedbv to int
2841 {
2843
2844 std::size_t from_width=fixedbv_type.get_width();
2845 std::size_t from_integer_bits=fixedbv_type.get_integer_bits();
2846 std::size_t from_fraction_bits=fixedbv_type.get_fraction_bits();
2847
2848 // we might need to round up in case of negative numbers
2849 // e.g., (int)(-1.00001)==1
2850
2851 out << "(let ((?tcop ";
2852 convert_expr(src);
2853 out << ")) ";
2854
2855 out << "(bvadd ";
2856
2858 {
2859 out << "((_ sign_extend "
2860 << (to_width-from_integer_bits) << ") ";
2861 out << "((_ extract " << (from_width-1) << " "
2862 << from_fraction_bits << ") ";
2863 convert_expr(src);
2864 out << "))";
2865 }
2866 else
2867 {
2868 out << "((_ extract " << (from_fraction_bits+to_width-1)
2869 << " " << from_fraction_bits << ") ";
2870 convert_expr(src);
2871 out << ")";
2872 }
2873
2874 out << " (ite (and ";
2875
2876 // some fraction bit is not zero
2877 out << "(not (= ((_ extract " << (from_fraction_bits-1) << " 0) ?tcop) "
2878 "(_ bv0 " << from_fraction_bits << ")))";
2879
2880 // number negative
2881 out << " (= ((_ extract " << (from_width-1) << " " << (from_width-1)
2882 << ") ?tcop) #b1)";
2883
2884 out << ")"; // and
2885
2886 out << " (_ bv1 " << to_width << ") (_ bv0 " << to_width << "))"; // ite
2887 out << ")"; // bvadd
2888 out << ")"; // let
2889 }
2890 else if(src_type.id()==ID_floatbv) // from floatbv to int
2891 {
2892 if(dest_type.id()==ID_bv)
2893 {
2894 // this is _NOT_ a semantic conversion, but bit-wise
2895
2896 if(use_FPA_theory)
2897 {
2898 defined_expressionst::const_iterator it =
2899 defined_expressions.find(expr);
2900 CHECK_RETURN(it != defined_expressions.end());
2901 out << it->second;
2902 }
2903 else
2904 {
2905 // straight-forward if width matches
2906 convert_expr(src);
2907 }
2908 }
2909 else if(dest_type.id()==ID_signedbv)
2910 {
2911 // this should be floatbv_typecast, not typecast
2913 "typecast unexpected "+src_type.id_string()+" -> "+
2914 dest_type.id_string());
2915 }
2916 else if(dest_type.id()==ID_unsignedbv)
2917 {
2918 // this should be floatbv_typecast, not typecast
2920 "typecast unexpected "+src_type.id_string()+" -> "+
2921 dest_type.id_string());
2922 }
2923 }
2924 else if(src_type.id()==ID_bool) // from boolean to int
2925 {
2926 out << "(ite ";
2927 convert_expr(src);
2928
2929 if(dest_type.id()==ID_fixedbv)
2930 {
2932 out << " (concat (_ bv1 "
2933 << spec.integer_bits << ") " <<
2934 "(_ bv0 " << spec.get_fraction_bits() << ")) " <<
2935 "(_ bv0 " << spec.width << ")";
2936 }
2937 else
2938 {
2939 out << " (_ bv1 " << to_width << ")";
2940 out << " (_ bv0 " << to_width << ")";
2941 }
2942
2943 out << ")";
2944 }
2945 else if(src_type.id()==ID_pointer) // from pointer to int
2946 {
2947 std::size_t from_width=boolbv_width(src_type);
2948
2949 if(from_width<to_width) // extend
2950 {
2951 out << "((_ sign_extend ";
2953 << ") ";
2954 convert_expr(src);
2955 out << ")";
2956 }
2957 else // chop off extra bits
2958 {
2959 out << "((_ extract " << (to_width-1) << " 0) ";
2960 convert_expr(src);
2961 out << ")";
2962 }
2963 }
2964 else if(src_type.id() == ID_integer || src_type.id() == ID_natural)
2965 {
2966 // from integer to bit-vector, must be constant
2967 if(src.is_constant())
2968 {
2970 out << "(_ bv" << i << " " << to_width << ")";
2971 }
2972 else
2973 SMT2_TODO("can't convert non-constant integer to bitvector");
2974 }
2975 else if(
2976 src_type.id() == ID_struct ||
2977 src_type.id() == ID_struct_tag) // flatten a struct to a bit-vector
2978 {
2979 if(use_datatypes)
2980 {
2981 INVARIANT(
2983 "bit vector with of source and destination type shall be equal");
2984 flatten2bv(src);
2985 }
2986 else
2987 {
2988 INVARIANT(
2990 "bit vector with of source and destination type shall be equal");
2991 convert_expr(src); // nothing else to do!
2992 }
2993 }
2994 else if(
2995 src_type.id() == ID_union ||
2996 src_type.id() == ID_union_tag) // flatten a union
2997 {
2998 INVARIANT(
3000 "bit vector with of source and destination type shall be equal");
3001 convert_expr(src); // nothing else to do!
3002 }
3003 else if(src_type.id()==ID_c_bit_field)
3004 {
3005 std::size_t from_width=boolbv_width(src_type);
3006
3007 if(from_width==to_width)
3008 convert_expr(src); // ignore
3009 else
3010 {
3014 }
3015 }
3016 else
3017 {
3018 std::ostringstream e_str;
3019 e_str << src_type.id() << " -> " << dest_type.id()
3020 << " src == " << format(src);
3021 UNEXPECTEDCASE("TODO typecast2 " + e_str.str());
3022 }
3023 }
3024 else if(dest_type.id()==ID_fixedbv) // to fixedbv
3025 {
3027 std::size_t to_fraction_bits=fixedbv_type.get_fraction_bits();
3028 std::size_t to_integer_bits=fixedbv_type.get_integer_bits();
3029
3030 if(src_type.id()==ID_unsignedbv ||
3031 src_type.id()==ID_signedbv ||
3032 src_type.id()==ID_c_enum)
3033 {
3034 // integer to fixedbv
3035
3036 std::size_t from_width=to_bitvector_type(src_type).get_width();
3037 out << "(concat ";
3038
3040 convert_expr(src);
3042 {
3043 // too many integer bits
3044 out << "((_ extract " << (to_integer_bits-1) << " 0) ";
3045 convert_expr(src);
3046 out << ")";
3047 }
3048 else
3049 {
3050 // too few integer bits
3051 INVARIANT(
3053 "from_width should be smaller than to_integer_bits as other case "
3054 "have been handled above");
3055 if(dest_type.id()==ID_unsignedbv)
3056 {
3057 out << "(_ zero_extend "
3058 << (to_integer_bits-from_width) << ") ";
3059 convert_expr(src);
3060 out << ")";
3061 }
3062 else
3063 {
3064 out << "((_ sign_extend "
3065 << (to_integer_bits-from_width) << ") ";
3066 convert_expr(src);
3067 out << ")";
3068 }
3069 }
3070
3071 out << "(_ bv0 " << to_fraction_bits << ")";
3072 out << ")"; // concat
3073 }
3074 else if(src_type.id()==ID_bool) // bool to fixedbv
3075 {
3076 out << "(concat (concat"
3077 << " (_ bv0 " << (to_integer_bits-1) << ") ";
3078 flatten2bv(src); // produces #b0 or #b1
3079 out << ") (_ bv0 "
3081 << "))";
3082 }
3083 else if(src_type.id()==ID_fixedbv) // fixedbv to fixedbv
3084 {
3086 std::size_t from_fraction_bits=from_fixedbv_type.get_fraction_bits();
3087 std::size_t from_integer_bits=from_fixedbv_type.get_integer_bits();
3088 std::size_t from_width=from_fixedbv_type.get_width();
3089
3090 out << "(let ((?tcop ";
3091 convert_expr(src);
3092 out << ")) ";
3093
3094 out << "(concat ";
3095
3097 {
3098 out << "((_ extract "
3101 << ") ?tcop)";
3102 }
3103 else
3104 {
3105 INVARIANT(
3107 "to_integer_bits should be greater than from_integer_bits as the"
3108 "other case has been handled above");
3109 out << "((_ sign_extend "
3111 << ") ((_ extract "
3112 << (from_width-1) << " "
3114 << ") ?tcop))";
3115 }
3116
3117 out << " ";
3118
3120 {
3121 out << "((_ extract "
3122 << (from_fraction_bits-1) << " "
3124 << ") ?tcop)";
3125 }
3126 else
3127 {
3128 INVARIANT(
3130 "to_fraction_bits should be greater than from_fraction_bits as the"
3131 "other case has been handled above");
3132 out << "(concat ((_ extract "
3133 << (from_fraction_bits-1) << " 0) ";
3134 convert_expr(src);
3135 out << ")"
3136 << " (_ bv0 " << to_fraction_bits-from_fraction_bits
3137 << "))";
3138 }
3139
3140 out << "))"; // concat, let
3141 }
3142 else
3143 UNEXPECTEDCASE("unexpected typecast to fixedbv");
3144 }
3145 else if(dest_type.id()==ID_pointer)
3146 {
3147 std::size_t to_width=boolbv_width(dest_type);
3148
3149 if(src_type.id()==ID_pointer) // pointer to pointer
3150 {
3151 // this just passes through
3152 convert_expr(src);
3153 }
3154 else if(
3155 src_type.id() == ID_unsignedbv || src_type.id() == ID_signedbv ||
3156 src_type.id() == ID_bv)
3157 {
3158 // integer to pointer
3159
3160 std::size_t from_width=boolbv_width(src_type);
3161
3162 if(from_width==to_width)
3163 convert_expr(src);
3164 else if(from_width<to_width)
3165 {
3166 out << "((_ sign_extend "
3167 << (to_width-from_width)
3168 << ") ";
3169 convert_expr(src);
3170 out << ")"; // sign_extend
3171 }
3172 else // from_width>to_width
3173 {
3174 out << "((_ extract " << to_width << " 0) ";
3175 convert_expr(src);
3176 out << ")"; // extract
3177 }
3178 }
3179 else
3180 UNEXPECTEDCASE("TODO typecast3 "+src_type.id_string()+" -> pointer");
3181 }
3182 else if(dest_type.id()==ID_range)
3183 {
3185 const auto dest_size =
3186 dest_range_type.get_to() - dest_range_type.get_from() + 1;
3187 const auto dest_width = address_bits(dest_size);
3188 if(src_type.id() == ID_range)
3189 {
3191 const auto src_size =
3192 src_range_type.get_to() - src_range_type.get_from() + 1;
3193 const auto src_width = address_bits(src_size);
3194 if(src_width < dest_width)
3195 {
3196 out << "((_ zero_extend " << dest_width - src_width << ") ";
3197 convert_expr(src);
3198 out << ')'; // zero_extend
3199 }
3200 else if(src_width > dest_width)
3201 {
3202 out << "((_ extract " << dest_width - 1 << " 0) ";
3203 convert_expr(src);
3204 out << ')'; // extract
3205 }
3206 else // src_width == dest_width
3207 {
3208 convert_expr(src);
3209 }
3210 }
3211 else
3212 SMT2_TODO("typecast from " + src_type.id_string() + " to range");
3213 }
3214 else if(dest_type.id()==ID_floatbv)
3215 {
3216 // Typecast from integer to floating-point should have be been
3217 // converted to ID_floatbv_typecast during symbolic execution,
3218 // adding the rounding mode. See
3219 // smt2_convt::convert_floatbv_typecast.
3220 // The exception is bool and c_bool to float.
3222
3223 if(src_type.id()==ID_bool)
3224 {
3225 out << "(ite ";
3226 convert_expr(src);
3227 out << ' ';
3229 out << ' ';
3231 out << ')';
3232 }
3233 else if(src_type.id()==ID_c_bool)
3234 {
3235 // turn into proper bool
3236 const typecast_exprt tmp(src, bool_typet());
3238 }
3239 else if(src_type.id() == ID_bv)
3240 {
3241 if(to_bv_type(src_type).get_width() != dest_floatbv_type.get_width())
3242 {
3243 UNEXPECTEDCASE("Typecast bv -> float with wrong width");
3244 }
3245
3246 if(use_FPA_theory)
3247 {
3248 out << "((_ to_fp " << dest_floatbv_type.get_e() << " "
3249 << dest_floatbv_type.get_f() + 1 << ") ";
3250 convert_expr(src);
3251 out << ')';
3252 }
3253 else
3254 convert_expr(src);
3255 }
3256 else
3257 UNEXPECTEDCASE("Unknown typecast "+src_type.id_string()+" -> float");
3258 }
3259 else if(dest_type.id() == ID_integer || dest_type.id() == ID_natural)
3260 {
3261 if(src_type.id()==ID_bool)
3262 {
3263 out << "(ite ";
3264 convert_expr(src);
3265 out <<" 1 0)";
3266 }
3267 else
3268 UNEXPECTEDCASE("Unknown typecast "+src_type.id_string()+" -> integer");
3269 }
3270 else if(dest_type.id()==ID_c_bit_field)
3271 {
3272 std::size_t from_width=boolbv_width(src_type);
3273 std::size_t to_width=boolbv_width(dest_type);
3274
3275 if(from_width==to_width)
3276 convert_expr(src); // ignore
3277 else
3278 {
3282 }
3283 }
3284 else if(dest_type.id() == ID_rational)
3285 {
3286 if(src_type.id() == ID_signedbv)
3287 {
3288 // TODO: negative numbers
3289 out << "(/ ";
3290 convert_expr(src);
3291 out << " 1)";
3292 }
3293 else
3295 "Unknown typecast " + src_type.id_string() + " -> rational");
3296 }
3297 else
3299 "TODO typecast8 "+src_type.id_string()+" -> "+dest_type.id_string());
3300}
3301
3303{
3304 const exprt &src=expr.op();
3305 // const exprt &rounding_mode=expr.rounding_mode();
3306 const typet &src_type=src.type();
3307 const typet &dest_type=expr.type();
3308
3309 if(dest_type.id()==ID_floatbv)
3310 {
3311 if(src_type.id()==ID_floatbv)
3312 {
3313 // float to float
3314
3315 /* ISO 9899:1999
3316 * 6.3.1.5 Real floating types
3317 * 1 When a float is promoted to double or long double, or a
3318 * double is promoted to long double, its value is unchanged.
3319 *
3320 * 2 When a double is demoted to float, a long double is
3321 * demoted to double or float, or a value being represented in
3322 * greater precision and range than required by its semantic
3323 * type (see 6.3.1.8) is explicitly converted to its semantic
3324 * type, if the value being converted can be represented
3325 * exactly in the new type, it is unchanged. If the value
3326 * being converted is in the range of values that can be
3327 * represented but cannot be represented exactly, the result
3328 * is either the nearest higher or nearest lower representable
3329 * value, chosen in an implementation-defined manner. If the
3330 * value being converted is outside the range of values that
3331 * can be represented, the behavior is undefined.
3332 */
3333
3335
3336 if(use_FPA_theory)
3337 {
3338 out << "((_ to_fp " << dst.get_e() << " "
3339 << dst.get_f() + 1 << ") ";
3341 out << " ";
3342 convert_expr(src);
3343 out << ")";
3344 }
3345 else
3346 convert_floatbv(expr);
3347 }
3348 else if(src_type.id()==ID_unsignedbv)
3349 {
3350 // unsigned to float
3351
3352 /* ISO 9899:1999
3353 * 6.3.1.4 Real floating and integer
3354 * 2 When a value of integer type is converted to a real
3355 * floating type, if the value being converted can be
3356 * represented exactly in the new type, it is unchanged. If the
3357 * value being converted is in the range of values that can be
3358 * represented but cannot be represented exactly, the result is
3359 * either the nearest higher or nearest lower representable
3360 * value, chosen in an implementation-defined manner. If the
3361 * value being converted is outside the range of values that can
3362 * be represented, the behavior is undefined.
3363 */
3364
3366
3367 if(use_FPA_theory)
3368 {
3369 out << "((_ to_fp_unsigned " << dst.get_e() << " "
3370 << dst.get_f() + 1 << ") ";
3372 out << " ";
3373 convert_expr(src);
3374 out << ")";
3375 }
3376 else
3377 convert_floatbv(expr);
3378 }
3379 else if(src_type.id()==ID_signedbv)
3380 {
3381 // signed to float
3382
3384
3385 if(use_FPA_theory)
3386 {
3387 out << "((_ to_fp " << dst.get_e() << " "
3388 << dst.get_f() + 1 << ") ";
3390 out << " ";
3391 convert_expr(src);
3392 out << ")";
3393 }
3394 else
3395 convert_floatbv(expr);
3396 }
3397 else if(src_type.id()==ID_c_enum_tag)
3398 {
3399 // enum to float
3400
3401 // We first convert to 'underlying type'
3403 tmp.op() = typecast_exprt(
3404 src, ns.follow_tag(to_c_enum_tag_type(src_type)).underlying_type());
3406 }
3407 else
3409 "TODO typecast11 "+src_type.id_string()+" -> "+dest_type.id_string());
3410 }
3411 else if(dest_type.id()==ID_signedbv)
3412 {
3413 if(use_FPA_theory)
3414 {
3415 std::size_t dest_width=to_signedbv_type(dest_type).get_width();
3416 out << "((_ fp.to_sbv " << dest_width << ") ";
3418 out << " ";
3419 convert_expr(src);
3420 out << ")";
3421 }
3422 else
3423 convert_floatbv(expr);
3424 }
3425 else if(dest_type.id()==ID_unsignedbv)
3426 {
3427 if(use_FPA_theory)
3428 {
3429 std::size_t dest_width=to_unsignedbv_type(dest_type).get_width();
3430 out << "((_ fp.to_ubv " << dest_width << ") ";
3432 out << " ";
3433 convert_expr(src);
3434 out << ")";
3435 }
3436 else
3437 convert_floatbv(expr);
3438 }
3439 else
3440 {
3442 "TODO typecast12 "+src_type.id_string()+" -> "+dest_type.id_string());
3443 }
3444}
3445
3448{
3449 PRECONDITION(expr.type().id() == ID_floatbv);
3450
3451 if(use_FPA_theory)
3452 {
3453 out << "(fp.roundToIntegral ";
3455 out << ' ';
3456 convert_expr(expr.op());
3457 out << ")";
3458 }
3459 else
3460 UNEXPECTEDCASE("TODO floatbv_round_to_integral without FPA");
3461}
3462
3464{
3465 const struct_typet &struct_type =
3466 expr.type().id() == ID_struct_tag
3467 ? ns.follow_tag(to_struct_tag_type(expr.type()))
3468 : to_struct_type(expr.type());
3469
3470 const struct_typet::componentst &components=
3471 struct_type.components();
3472
3474 components.size() == expr.operands().size(),
3475 "number of struct components as indicated by the struct type shall be equal"
3476 "to the number of operands of the struct expression");
3477
3478 DATA_INVARIANT(!components.empty(), "struct shall have struct components");
3479
3480 if(use_datatypes)
3481 {
3482 const std::string &smt_typename = datatype_map.at(struct_type);
3483
3484 // use the constructor for the Z3 datatype
3485 out << "(mk-" << smt_typename;
3486
3487 std::size_t i=0;
3488 for(struct_typet::componentst::const_iterator
3489 it=components.begin();
3490 it!=components.end();
3491 it++, i++)
3492 {
3493 if(is_zero_width(it->type(), ns))
3494 continue;
3495 out << " ";
3496 convert_expr(expr.operands()[i]);
3497 }
3498
3499 out << ")";
3500 }
3501 else
3502 {
3503 auto convert_operand = [this](const exprt &op) {
3504 // may need to flatten array-theory arrays in there
3505 if(op.type().id() == ID_array && use_array_theory(op))
3506 flatten_array(op);
3507 else if(op.type().id() == ID_bool)
3508 flatten2bv(op);
3509 else
3510 convert_expr(op);
3511 };
3512
3513 // SMT-LIB 2 concat is binary only
3514 std::size_t n_concat = 0;
3515 for(std::size_t i = components.size(); i > 1; i--)
3516 {
3517 if(is_zero_width(components[i - 1].type(), ns))
3518 continue;
3519 else if(i > 2 || !is_zero_width(components[0].type(), ns))
3520 {
3521 ++n_concat;
3522 out << "(concat ";
3523 }
3524
3525 convert_operand(expr.operands()[i - 1]);
3526
3527 out << " ";
3528 }
3529
3530 if(!is_zero_width(components[0].type(), ns))
3531 convert_operand(expr.op0());
3532
3533 out << std::string(n_concat, ')');
3534 }
3535}
3536
3539{
3540 const array_typet &array_type = to_array_type(expr.type());
3541 const auto &size_expr = array_type.size();
3542 PRECONDITION(size_expr.is_constant());
3543
3545 CHECK_RETURN_WITH_DIAGNOSTICS(size != 0, "can't convert zero-sized array");
3546
3547 out << "(let ((?far ";
3548 convert_expr(expr);
3549 out << ")) ";
3550
3551 for(mp_integer i=size; i!=0; --i)
3552 {
3553 if(i!=1)
3554 out << "(concat ";
3555 out << "(select ?far ";
3556 convert_expr(from_integer(i - 1, array_type.index_type()));
3557 out << ")";
3558 if(i!=1)
3559 out << " ";
3560 }
3561
3562 // close the many parentheses
3563 for(mp_integer i=size; i>1; --i)
3564 out << ")";
3565
3566 out << ")"; // let
3567}
3568
3570{
3571 const exprt &op=expr.op();
3572
3573 std::size_t total_width = boolbv_width(expr.type());
3574
3575 std::size_t member_width=boolbv_width(op.type());
3576
3577 if(total_width==member_width)
3578 {
3579 flatten2bv(op);
3580 }
3581 else
3582 {
3583 // we will pad with zeros, but non-det would be better
3584 INVARIANT(
3585 total_width > member_width,
3586 "total_width should be greater than member_width as member_width can be"
3587 "at most as large as total_width and the other case has been handled "
3588 "above");
3589 out << "(concat ";
3590 out << "(_ bv0 "
3591 << (total_width-member_width) << ") ";
3592 flatten2bv(op);
3593 out << ")";
3594 }
3595}
3596
3598{
3599 const typet &expr_type=expr.type();
3600
3601 if(expr_type.id()==ID_unsignedbv ||
3602 expr_type.id()==ID_signedbv ||
3603 expr_type.id()==ID_bv ||
3604 expr_type.id()==ID_c_enum ||
3605 expr_type.id()==ID_c_enum_tag ||
3606 expr_type.id()==ID_c_bool ||
3608 {
3609 const std::size_t width = boolbv_width(expr_type);
3610
3611 const mp_integer value = bvrep2integer(expr.get_value(), width, false);
3612
3613 out << "(_ bv" << value
3614 << " " << width << ")";
3615 }
3616 else if(expr_type.id()==ID_fixedbv)
3617 {
3619
3620 const mp_integer v = bvrep2integer(expr.get_value(), spec.width, false);
3621
3622 out << "(_ bv" << v << " " << spec.width << ")";
3623 }
3624 else if(expr_type.id()==ID_floatbv)
3625 {
3628
3629 if(use_FPA_theory)
3630 {
3631 /* CBMC stores floating point literals in the most
3632 computationally useful form; biased exponents and
3633 significands including the hidden bit. Thus some encoding
3634 is needed to get to IEEE-754 style representations. */
3635
3637 size_t e=floatbv_type.get_e();
3638 size_t f=floatbv_type.get_f()+1;
3639
3640 /* Should be sufficient, but not currently supported by mathsat */
3641 #if 0
3642 mp_integer binary = v.pack();
3643
3644 out << "((_ to_fp " << e << " " << f << ")"
3645 << " #b" << integer2binary(v.pack(), v.spec.width()) << ")";
3646 #endif
3647
3648 if(v.is_NaN())
3649 {
3650 out << "(_ NaN " << e << " " << f << ")";
3651 }
3652 else if(v.is_infinity())
3653 {
3654 if(v.get_sign())
3655 out << "(_ -oo " << e << " " << f << ")";
3656 else
3657 out << "(_ +oo " << e << " " << f << ")";
3658 }
3659 else
3660 {
3661 // Zero, normal or subnormal
3662
3663 mp_integer binary = v.pack();
3664 std::string binaryString(integer2binary(v.pack(), v.spec.width()));
3665
3666 out << "(fp "
3667 << "#b" << binaryString.substr(0, 1) << " "
3668 << "#b" << binaryString.substr(1, e) << " "
3669 << "#b" << binaryString.substr(1+e, f-1) << ")";
3670 }
3671 }
3672 else
3673 {
3674 // produce corresponding bit-vector
3675 const ieee_float_spect spec(floatbv_type);
3676 const mp_integer v = bvrep2integer(expr.get_value(), spec.width(), false);
3677 out << "(_ bv" << v << " " << spec.width() << ")";
3678 }
3679 }
3680 else if(expr_type.id()==ID_pointer)
3681 {
3682 if(expr.is_null_pointer())
3683 {
3684 out << "(_ bv0 " << boolbv_width(expr_type)
3685 << ")";
3686 }
3687 else
3688 {
3689 // just treat the pointer as a bit vector
3690 const std::size_t width = boolbv_width(expr_type);
3691
3692 const mp_integer value = bvrep2integer(expr.get_value(), width, false);
3693
3694 out << "(_ bv" << value << " " << width << ")";
3695 }
3696 }
3697 else if(expr_type.id()==ID_bool)
3698 {
3699 if(expr == true)
3700 out << "true";
3701 else if(expr == false)
3702 out << "false";
3703 else
3704 UNEXPECTEDCASE("unknown Boolean constant");
3705 }
3706 else if(expr_type.id()==ID_array)
3707 {
3708 defined_expressionst::const_iterator it=defined_expressions.find(expr);
3709 CHECK_RETURN(it != defined_expressions.end());
3710 out << it->second;
3711 }
3712 else if(expr_type.id()==ID_rational)
3713 {
3714 std::string value=id2string(expr.get_value());
3715 const bool negative = has_prefix(value, "-");
3716
3717 if(negative)
3718 {
3719 out << "(- ";
3720 value = value.substr(1);
3721 }
3722
3723 size_t pos=value.find("/");
3724
3725 if(pos==std::string::npos)
3726 out << value << ".0";
3727 else
3728 {
3729 out << "(/ " << value.substr(0, pos) << ".0 "
3730 << value.substr(pos+1) << ".0)";
3731 }
3732
3733 if(negative)
3734 out << ')';
3735 }
3736 else if(expr_type.id() == ID_real)
3737 {
3738 const std::string &value = id2string(expr.get_value());
3739 out << value;
3740 if(value.find('.') == std::string::npos)
3741 out << ".0";
3742 }
3743 else if(expr_type.id()==ID_integer)
3744 {
3745 const auto value = id2string(expr.get_value());
3746
3747 // SMT2 has no negative integer literals
3748 if(has_prefix(value, "-"))
3749 out << "(- " << value.substr(1, std::string::npos) << ')';
3750 else
3751 out << value;
3752 }
3753 else if(expr_type.id() == ID_natural)
3754 {
3755 out << expr.get_value();
3756 }
3757 else if(expr_type.id() == ID_range)
3758 {
3760 const auto size = range_type.get_to() - range_type.get_from() + 1;
3761 const auto width = address_bits(size);
3762 const auto value_int = numeric_cast_v<mp_integer>(expr);
3763 out << "(_ bv" << (value_int - range_type.get_from()) << " " << width
3764 << ")";
3765 }
3766 else
3767 UNEXPECTEDCASE("unknown constant: "+expr_type.id_string());
3768}
3769
3771{
3772 if(expr.type().id() == ID_integer)
3773 {
3774 out << "(mod ";
3775 convert_expr(expr.op0());
3776 out << ' ';
3777 convert_expr(expr.op1());
3778 out << ')';
3779 }
3780 else
3782 "unsupported type for euclidean_mod: " + expr.type().id_string());
3783}
3784
3786{
3787 if(expr.type().id()==ID_unsignedbv ||
3788 expr.type().id()==ID_signedbv)
3789 {
3790 if(expr.type().id()==ID_unsignedbv)
3791 out << "(bvurem ";
3792 else
3793 out << "(bvsrem ";
3794
3795 convert_expr(expr.op0());
3796 out << " ";
3797 convert_expr(expr.op1());
3798 out << ")";
3799 }
3800 else
3801 UNEXPECTEDCASE("unsupported type for mod: "+expr.type().id_string());
3802}
3803
3805{
3806 std::vector<mp_integer> dynamic_objects;
3808
3809 if(dynamic_objects.empty())
3810 out << "false";
3811 else
3812 {
3813 std::size_t pointer_width = boolbv_width(expr.op().type());
3814
3815 out << "(let ((?obj ((_ extract "
3816 << pointer_width-1 << " "
3817 << pointer_width-config.bv_encoding.object_bits << ") ";
3818 convert_expr(expr.op());
3819 out << "))) ";
3820
3821 if(dynamic_objects.size()==1)
3822 {
3823 out << "(= (_ bv" << dynamic_objects.front()
3824 << " " << config.bv_encoding.object_bits << ") ?obj)";
3825 }
3826 else
3827 {
3828 out << "(or";
3829
3830 for(const auto &object : dynamic_objects)
3831 out << " (= (_ bv" << object
3832 << " " << config.bv_encoding.object_bits << ") ?obj)";
3833
3834 out << ")"; // or
3835 }
3836
3837 out << ")"; // let
3838 }
3839}
3840
3842{
3843 const typet &op_type=expr.op0().type();
3844
3845 if(
3846 op_type.id() == ID_unsignedbv || op_type.id() == ID_bv ||
3847 op_type.id() == ID_range)
3848 {
3849 // The range type is encoded in binary
3850 out << "(";
3851 if(expr.id()==ID_le)
3852 out << "bvule";
3853 else if(expr.id()==ID_lt)
3854 out << "bvult";
3855 else if(expr.id()==ID_ge)
3856 out << "bvuge";
3857 else if(expr.id()==ID_gt)
3858 out << "bvugt";
3859
3860 out << " ";
3861 convert_expr(expr.op0());
3862 out << " ";
3863 convert_expr(expr.op1());
3864 out << ")";
3865 }
3866 else if(op_type.id()==ID_signedbv ||
3867 op_type.id()==ID_fixedbv)
3868 {
3869 out << "(";
3870 if(expr.id()==ID_le)
3871 out << "bvsle";
3872 else if(expr.id()==ID_lt)
3873 out << "bvslt";
3874 else if(expr.id()==ID_ge)
3875 out << "bvsge";
3876 else if(expr.id()==ID_gt)
3877 out << "bvsgt";
3878
3879 out << " ";
3880 convert_expr(expr.op0());
3881 out << " ";
3882 convert_expr(expr.op1());
3883 out << ")";
3884 }
3885 else if(op_type.id()==ID_floatbv)
3886 {
3887 if(use_FPA_theory)
3888 {
3889 out << "(";
3890 if(expr.id()==ID_le)
3891 out << "fp.leq";
3892 else if(expr.id()==ID_lt)
3893 out << "fp.lt";
3894 else if(expr.id()==ID_ge)
3895 out << "fp.geq";
3896 else if(expr.id()==ID_gt)
3897 out << "fp.gt";
3898
3899 out << " ";
3900 convert_expr(expr.op0());
3901 out << " ";
3902 convert_expr(expr.op1());
3903 out << ")";
3904 }
3905 else
3906 convert_floatbv(expr);
3907 }
3908 else if(
3909 op_type.id() == ID_rational || op_type.id() == ID_integer ||
3910 op_type.id() == ID_natural || op_type.id() == ID_real)
3911 {
3912 out << "(";
3913 out << expr.id();
3914
3915 out << " ";
3916 convert_expr(expr.op0());
3917 out << " ";
3918 convert_expr(expr.op1());
3919 out << ")";
3920 }
3921 else if(op_type.id() == ID_pointer)
3922 {
3923 const exprt same_object = ::same_object(expr.op0(), expr.op1());
3924
3925 out << "(and ";
3927
3928 out << " (";
3929 if(expr.id() == ID_le)
3930 out << "bvsle";
3931 else if(expr.id() == ID_lt)
3932 out << "bvslt";
3933 else if(expr.id() == ID_ge)
3934 out << "bvsge";
3935 else if(expr.id() == ID_gt)
3936 out << "bvsgt";
3937
3938 out << ' ';
3940 out << ' ';
3942 out << ')';
3943
3944 out << ')';
3945 }
3946 else
3948 "unsupported type for "+expr.id_string()+": "+op_type.id_string());
3949}
3950
3952{
3953 if(
3954 expr.type().id() == ID_rational || expr.type().id() == ID_integer ||
3955 expr.type().id() == ID_natural || expr.type().id() == ID_real)
3956 {
3957 // these are multi-ary in SMT-LIB2
3958 out << "(+";
3959
3960 for(const auto &op : expr.operands())
3961 {
3962 out << ' ';
3963 convert_expr(op);
3964 }
3965
3966 out << ')';
3967 }
3968 else if(
3969 expr.type().id() == ID_unsignedbv || expr.type().id() == ID_signedbv ||
3970 expr.type().id() == ID_fixedbv)
3971 {
3972 // These could be chained, i.e., need not be binary,
3973 // but at least MathSat doesn't like that.
3974 if(expr.operands().size() == 2)
3975 {
3976 out << "(bvadd ";
3977 convert_expr(expr.op0());
3978 out << " ";
3979 convert_expr(expr.op1());
3980 out << ")";
3981 }
3982 else
3983 {
3985 }
3986 }
3987 else if(expr.type().id() == ID_range)
3988 {
3989 auto &range_type = to_range_type(expr.type());
3990
3991 // These could be chained, i.e., need not be binary,
3992 // but at least MathSat doesn't like that.
3993 if(expr.operands().size() == 2)
3994 {
3995 // add: lhs + from + rhs + from - from = lhs + rhs + from
3996 mp_integer from = range_type.get_from();
3997 const auto size = range_type.get_to() - range_type.get_from() + 1;
3998 const auto width = address_bits(size);
3999
4000 out << "(bvadd ";
4001 convert_expr(expr.op0());
4002 out << " (bvadd ";
4003 convert_expr(expr.op1());
4004 out << " (_ bv" << range_type.get_from() << ' ' << width
4005 << ")))"; // bv, bvadd, bvadd
4006 }
4007 else
4008 {
4010 }
4011 }
4012 else if(expr.type().id() == ID_floatbv)
4013 {
4014 // Floating-point additions should have be been converted
4015 // to ID_floatbv_plus during symbolic execution, adding
4016 // the rounding mode. See smt2_convt::convert_floatbv_plus.
4018 }
4019 else if(expr.type().id() == ID_pointer)
4020 {
4021 if(expr.operands().size() == 2)
4022 {
4023 exprt p = expr.op0(), i = expr.op1();
4024
4025 if(p.type().id() != ID_pointer)
4026 p.swap(i);
4027
4029 p.type().id() == ID_pointer,
4030 "one of the operands should have pointer type");
4031
4032 const auto &base_type = to_pointer_type(expr.type()).base_type();
4034 base_type.id() != ID_empty, "no pointer arithmetic over void pointers");
4035
4036 auto element_size_opt = pointer_offset_size(base_type, ns);
4037 CHECK_RETURN(element_size_opt.has_value() && *element_size_opt >= 0);
4039
4040 // First convert the pointer operand
4041 out << "(let ((?pointerop ";
4042 convert_expr(p);
4043 out << ")) ";
4044
4045 // The addition is done on the offset part only.
4046 const std::size_t pointer_width = boolbv_width(p.type());
4047 const std::size_t offset_bits =
4048 pointer_width - config.bv_encoding.object_bits;
4049
4050 out << "(concat ";
4051 out << "((_ extract " << pointer_width - 1 << ' ' << offset_bits
4052 << ") ?pointerop) ";
4053 out << "(bvadd ((_ extract " << offset_bits - 1 << " 0) ?pointerop) ";
4054
4055 if(element_size >= 2)
4056 {
4057 out << "(bvmul ((_ extract " << offset_bits - 1 << " 0) ";
4058 convert_expr(i);
4059 out << ") (_ bv" << element_size << " " << offset_bits << "))";
4060 }
4061 else
4062 {
4063 out << "((_ extract " << offset_bits - 1 << " 0) ";
4064 convert_expr(i);
4065 out << ')'; // extract
4066 }
4067
4068 out << ")))"; // bvadd, concat, let
4069 }
4070 else
4071 {
4073 }
4074 }
4075 else
4076 UNEXPECTEDCASE("unsupported type for +: " + expr.type().id_string());
4077}
4078
4083{
4085
4086 /* CProver uses the x86 numbering of the rounding-mode
4087 * 0 == FE_TONEAREST
4088 * 1 == FE_DOWNWARD
4089 * 2 == FE_UPWARD
4090 * 3 == FE_TOWARDZERO
4091 * These literal values must be used rather than the macros
4092 * the macros from fenv.h to avoid portability problems.
4093 */
4094
4095 if(expr.is_constant())
4096 {
4098
4100
4101 if(value==0)
4102 out << "roundNearestTiesToEven";
4103 else if(value==1)
4104 out << "roundTowardNegative";
4105 else if(value==2)
4106 out << "roundTowardPositive";
4107 else if(value==3)
4108 out << "roundTowardZero";
4109 else if(value == 4)
4110 out << "roundNearestTiesToAway";
4111 else
4113 false,
4114 "Rounding mode should have value 0, 1, 2, 3, or 4",
4115 id2string(cexpr.get_value()));
4116 }
4117 else
4118 {
4119 std::size_t width=to_bitvector_type(expr.type()).get_width();
4120
4121 // Need to make the choice above part of the model
4122 out << "(ite (= (_ bv0 " << width << ") ";
4123 convert_expr(expr);
4124 out << ") roundNearestTiesToEven ";
4125
4126 out << "(ite (= (_ bv1 " << width << ") ";
4127 convert_expr(expr);
4128 out << ") roundTowardNegative ";
4129
4130 out << "(ite (= (_ bv2 " << width << ") ";
4131 convert_expr(expr);
4132 out << ") roundTowardPositive ";
4133
4134 out << "(ite (= (_ bv3 " << width << ") ";
4135 convert_expr(expr);
4136 out << ") roundTowardZero ";
4137
4138 // TODO: add some kind of error checking here
4139 out << "roundNearestTiesToAway";
4140
4141 out << "))))";
4142 }
4143}
4144
4146{
4147 const typet &type=expr.type();
4148
4150 type.id() == ID_floatbv ||
4151 (type.id() == ID_complex &&
4152 to_complex_type(type).subtype().id() == ID_floatbv));
4153
4154 if(use_FPA_theory)
4155 {
4156 if(type.id()==ID_floatbv)
4157 {
4158 out << "(fp.add ";
4160 out << " ";
4161 convert_expr(expr.lhs());
4162 out << " ";
4163 convert_expr(expr.rhs());
4164 out << ")";
4165 }
4166 else if(type.id()==ID_complex)
4167 {
4168 SMT2_TODO("+ for floatbv complex");
4169 }
4170 else
4172 false,
4173 "type should not be one of the unsupported types",
4174 type.id_string());
4175 }
4176 else
4177 convert_floatbv(expr);
4178}
4179
4181{
4182 if(
4183 expr.type().id() == ID_integer || expr.type().id() == ID_natural ||
4184 expr.type().id() == ID_rational || expr.type().id() == ID_real)
4185 {
4186 out << "(- ";
4187 convert_expr(expr.op0());
4188 out << " ";
4189 convert_expr(expr.op1());
4190 out << ")";
4191 }
4192 else if(expr.type().id()==ID_unsignedbv ||
4193 expr.type().id()==ID_signedbv ||
4194 expr.type().id()==ID_fixedbv)
4195 {
4196 if(expr.op0().type().id()==ID_pointer &&
4197 expr.op1().type().id()==ID_pointer)
4198 {
4199 // Pointer difference
4200 const auto &base_type = to_pointer_type(expr.op0().type()).base_type();
4202 base_type.id() != ID_empty, "no pointer arithmetic over void pointers");
4203 auto element_size_opt = pointer_offset_size(base_type, ns);
4204 CHECK_RETURN(element_size_opt.has_value() && *element_size_opt >= 1);
4206
4207 if(element_size >= 2)
4208 out << "(bvsdiv ";
4209
4210 INVARIANT(
4211 boolbv_width(expr.op0().type()) == boolbv_width(expr.type()),
4212 "bitvector width of operand shall be equal to the bitvector width of "
4213 "the expression");
4214
4215 out << "(bvsub ";
4216 convert_expr(expr.op0());
4217 out << " ";
4218 convert_expr(expr.op1());
4219 out << ")";
4220
4221 if(element_size >= 2)
4222 out << " (_ bv" << element_size << " " << boolbv_width(expr.type())
4223 << "))";
4224 }
4225 else
4226 {
4227 out << "(bvsub ";
4228 convert_expr(expr.op0());
4229 out << " ";
4230 convert_expr(expr.op1());
4231 out << ")";
4232 }
4233 }
4234 else if(expr.type().id()==ID_floatbv)
4235 {
4236 // Floating-point subtraction should have be been converted
4237 // to ID_floatbv_minus during symbolic execution, adding
4238 // the rounding mode. See smt2_convt::convert_floatbv_minus.
4240 }
4241 else if(expr.type().id()==ID_pointer)
4242 {
4243 if(
4244 expr.op0().type().id() == ID_pointer &&
4245 (expr.op1().type().id() == ID_unsignedbv ||
4246 expr.op1().type().id() == ID_signedbv))
4247 {
4248 // rewrite p-o to p+(-o)
4249 return convert_plus(
4250 plus_exprt(expr.op0(), unary_minus_exprt(expr.op1())));
4251 }
4252 else
4254 "unsupported operand types for -: " + expr.op0().type().id_string() +
4255 " and " + expr.op1().type().id_string());
4256 }
4257 else if(expr.type().id() == ID_range)
4258 {
4259 auto &range_type = to_range_type(expr.type());
4260
4261 // sub: lhs + from - (rhs + from) - from = lhs - rhs - from
4262 mp_integer from = range_type.get_from();
4263 const auto size = range_type.get_to() - range_type.get_from() + 1;
4264 const auto width = address_bits(size);
4265
4266 out << "(bvsub (bvsub ";
4267 convert_expr(expr.op0());
4268 out << ' ';
4269 convert_expr(expr.op1());
4270 out << ") (_ bv" << range_type.get_from() << ' ' << width
4271 << "))"; // bv, bvsub
4272 }
4273 else
4274 UNEXPECTEDCASE("unsupported type for -: "+expr.type().id_string());
4275}
4276
4278{
4280 expr.type().id() == ID_floatbv,
4281 "type of ieee floating point expression shall be floatbv");
4282
4283 if(use_FPA_theory)
4284 {
4285 out << "(fp.sub ";
4287 out << " ";
4288 convert_expr(expr.lhs());
4289 out << " ";
4290 convert_expr(expr.rhs());
4291 out << ")";
4292 }
4293 else
4294 convert_floatbv(expr);
4295}
4296
4298{
4299 if(expr.type().id()==ID_unsignedbv ||
4300 expr.type().id()==ID_signedbv)
4301 {
4302 if(expr.type().id()==ID_unsignedbv)
4303 out << "(bvudiv ";
4304 else
4305 out << "(bvsdiv ";
4306
4307 convert_expr(expr.op0());
4308 out << " ";
4309 convert_expr(expr.op1());
4310 out << ")";
4311 }
4312 else if(expr.type().id()==ID_fixedbv)
4313 {
4314 fixedbv_spect spec(to_fixedbv_type(expr.type()));
4315 std::size_t fraction_bits=spec.get_fraction_bits();
4316
4317 out << "((_ extract " << spec.width-1 << " 0) ";
4318 out << "(bvsdiv ";
4319
4320 out << "(concat ";
4321 convert_expr(expr.op0());
4322 out << " (_ bv0 " << fraction_bits << ")) ";
4323
4324 out << "((_ sign_extend " << fraction_bits << ") ";
4325 convert_expr(expr.op1());
4326 out << ")";
4327
4328 out << "))";
4329 }
4330 else if(expr.type().id()==ID_floatbv)
4331 {
4332 // Floating-point division should have be been converted
4333 // to ID_floatbv_div during symbolic execution, adding
4334 // the rounding mode. See smt2_convt::convert_floatbv_div.
4336 }
4337 else if(
4338 expr.type().id() == ID_rational || expr.type().id() == ID_integer ||
4339 expr.type().id() == ID_natural || expr.type().id() == ID_real)
4340 {
4341 out << "(/ ";
4342 convert_expr(expr.op0());
4343 out << " ";
4344 convert_expr(expr.op1());
4345 out << ")";
4346 }
4347 else
4348 UNEXPECTEDCASE("unsupported type for /: "+expr.type().id_string());
4349}
4350
4352{
4354 expr.type().id() == ID_floatbv,
4355 "type of ieee floating point expression shall be floatbv");
4356
4357 if(use_FPA_theory)
4358 {
4359 out << "(fp.div ";
4361 out << " ";
4362 convert_expr(expr.lhs());
4363 out << " ";
4364 convert_expr(expr.rhs());
4365 out << ")";
4366 }
4367 else
4368 convert_floatbv(expr);
4369}
4370
4372{
4373 // re-write to binary if needed
4374 if(expr.operands().size()>2)
4375 {
4376 // strip last operand
4377 exprt tmp=expr;
4378 tmp.operands().pop_back();
4379
4380 // recursive call
4381 return convert_mult(mult_exprt(tmp, expr.operands().back()));
4382 }
4383
4384 INVARIANT(
4385 expr.operands().size() == 2,
4386 "expression should have been converted to a variant with two operands");
4387
4388 if(expr.type().id()==ID_unsignedbv ||
4389 expr.type().id()==ID_signedbv)
4390 {
4391 // Note that bvmul is really unsigned,
4392 // but this is irrelevant as we chop-off any extra result
4393 // bits.
4394 out << "(bvmul ";
4395 convert_expr(expr.op0());
4396 out << " ";
4397 convert_expr(expr.op1());
4398 out << ")";
4399 }
4400 else if(expr.type().id()==ID_floatbv)
4401 {
4402 // Floating-point multiplication should have be been converted
4403 // to ID_floatbv_mult during symbolic execution, adding
4404 // the rounding mode. See smt2_convt::convert_floatbv_mult.
4406 }
4407 else if(expr.type().id()==ID_fixedbv)
4408 {
4409 fixedbv_spect spec(to_fixedbv_type(expr.type()));
4410 std::size_t fraction_bits=spec.get_fraction_bits();
4411
4412 out << "((_ extract "
4413 << spec.width+fraction_bits-1 << " "
4414 << fraction_bits << ") ";
4415
4416 out << "(bvmul ";
4417
4418 out << "((_ sign_extend " << fraction_bits << ") ";
4419 convert_expr(expr.op0());
4420 out << ") ";
4421
4422 out << "((_ sign_extend " << fraction_bits << ") ";
4423 convert_expr(expr.op1());
4424 out << ")";
4425
4426 out << "))"; // bvmul, extract
4427 }
4428 else if(
4429 expr.type().id() == ID_rational || expr.type().id() == ID_integer ||
4430 expr.type().id() == ID_natural || expr.type().id() == ID_real)
4431 {
4432 out << "(*";
4433
4434 for(const auto &op : expr.operands())
4435 {
4436 out << " ";
4437 convert_expr(op);
4438 }
4439
4440 out << ")";
4441 }
4442 else
4443 UNEXPECTEDCASE("unsupported type for *: "+expr.type().id_string());
4444}
4445
4447{
4449 expr.type().id() == ID_floatbv,
4450 "type of ieee floating point expression shall be floatbv");
4451
4452 if(use_FPA_theory)
4453 {
4454 out << "(fp.mul ";
4456 out << " ";
4457 convert_expr(expr.lhs());
4458 out << " ";
4459 convert_expr(expr.rhs());
4460 out << ")";
4461 }
4462 else
4463 convert_floatbv(expr);
4464}
4465
4467{
4469 expr.type().id() == ID_floatbv,
4470 "type of ieee floating point expression shall be floatbv");
4471
4472 if(use_FPA_theory)
4473 {
4474 // Note that these do not have a rounding mode
4475 out << "(fp.rem ";
4476 convert_expr(expr.lhs());
4477 out << " ";
4478 convert_expr(expr.rhs());
4479 out << ")";
4480 }
4481 else
4482 {
4483 SMT2_TODO(
4484 "smt2_convt::convert_floatbv_rem to be implemented when not using "
4485 "FPA_theory");
4486 }
4487}
4488
4490{
4491 INVARIANT(
4492 expr.operands().size() == 3,
4493 "with expression should have exactly three operands");
4494
4495 const typet &expr_type = expr.type();
4496
4497 if(expr_type.id()==ID_array)
4498 {
4500
4501 if(use_array_theory(expr))
4502 {
4503 out << "(store ";
4504 convert_expr(expr.old());
4505 out << " ";
4506 convert_expr(typecast_exprt(expr.where(), array_type.index_type()));
4507 out << " ";
4508 convert_expr(expr.new_value());
4509 out << ")";
4510 }
4511 else
4512 {
4513 // fixed-width
4514 std::size_t array_width=boolbv_width(array_type);
4515 std::size_t sub_width = boolbv_width(array_type.element_type());
4516 std::size_t index_width=boolbv_width(expr.where().type());
4517
4518 // We mask out the updated bits with AND,
4519 // and then OR-in the shifted new value.
4520
4521 out << "(let ((distance? ";
4522 out << "(bvmul (_ bv" << sub_width << " " << array_width << ") ";
4523
4524 // SMT2 says that the shift distance needs to be as wide
4525 // as the stuff we are shifting.
4527 {
4528 out << "((_ zero_extend " << array_width-index_width << ") ";
4529 convert_expr(expr.where());
4530 out << ")";
4531 }
4532 else
4533 {
4534 out << "((_ extract " << array_width-1 << " 0) ";
4535 convert_expr(expr.where());
4536 out << ")";
4537 }
4538
4539 out << "))) "; // bvmul, distance?
4540
4541 out << "(bvor ";
4542 out << "(bvand ";
4543 out << "(bvnot ";
4544 out << "(bvshl (_ bv" << power(2, sub_width) - 1 << " " << array_width
4545 << ") ";
4546 out << "distance?)) "; // bvnot, bvlshl
4547 convert_expr(expr.old());
4548 out << ") "; // bvand
4549 out << "(bvshl ";
4550 out << "((_ zero_extend " << array_width-sub_width << ") ";
4551 convert_expr(expr.new_value());
4552 out << ") distance?)))"; // zero_extend, bvshl, bvor, let
4553 }
4554 }
4555 else if(expr_type.id() == ID_struct || expr_type.id() == ID_struct_tag)
4556 {
4557 const struct_typet &struct_type =
4558 expr_type.id() == ID_struct_tag
4559 ? ns.follow_tag(to_struct_tag_type(expr_type))
4561
4562 const exprt &index = expr.where();
4563 const exprt &value = expr.new_value();
4564
4565 const irep_idt &component_name=index.get(ID_component_name);
4566
4567 INVARIANT(
4568 struct_type.has_component(component_name),
4569 "struct should have accessed component");
4570
4571 if(use_datatypes)
4572 {
4573 const std::string &smt_typename = datatype_map.at(expr_type);
4574
4575 out << "(update-" << smt_typename << "." << component_name << " ";
4576 convert_expr(expr.old());
4577 out << " ";
4578 convert_expr(value);
4579 out << ")";
4580 }
4581 else
4582 {
4583 auto convert_operand = [this](const exprt &op)
4584 {
4585 // may need to flatten array-theory arrays in there
4586 if(op.type().id() == ID_array && use_array_theory(op))
4587 flatten_array(op);
4588 else if(op.type().id() == ID_bool)
4589 flatten2bv(op);
4590 else
4591 convert_expr(op);
4592 };
4593
4595
4596 // figure out the offset and width of the member
4597 const boolbv_widtht::membert &m =
4598 boolbv_width.get_member(struct_type, component_name);
4599
4600 if(m.width==struct_width)
4601 {
4602 // the struct is the same as the member, no concat needed
4603 convert_operand(value);
4604 }
4605 else
4606 {
4607 out << "(let ((?withop ";
4608 convert_operand(expr.old());
4609 out << ")) ";
4610
4611 if(m.offset == 0)
4612 {
4613 // the member is at the beginning
4614 out << "(concat "
4615 << "((_ extract " << (struct_width - 1) << " " << m.width
4616 << ") ?withop) ";
4617 convert_operand(value);
4618 out << ")"; // concat
4619 }
4620 else if(m.offset + m.width == struct_width)
4621 {
4622 // the member is at the end
4623 out << "(concat ";
4624 convert_operand(value);
4625 out << " ((_ extract " << (m.offset - 1) << " 0) ?withop))";
4626 }
4627 else
4628 {
4629 // most general case, need two concat-s
4630 out << "(concat (concat "
4631 << "((_ extract " << (struct_width - 1) << " "
4632 << (m.offset + m.width) << ") ?withop) ";
4633 convert_operand(value);
4634 out << ") ((_ extract " << (m.offset - 1) << " 0) ?withop)";
4635 out << ")"; // concat
4636 }
4637
4638 out << ")"; // let ?withop
4639 }
4640 }
4641 }
4642 else if(expr_type.id() == ID_union || expr_type.id() == ID_union_tag)
4643 {
4644 const exprt &value = expr.new_value();
4645
4646 std::size_t total_width = boolbv_width(expr_type);
4647
4648 std::size_t member_width=boolbv_width(value.type());
4649
4650 if(total_width==member_width)
4651 {
4652 flatten2bv(value);
4653 }
4654 else
4655 {
4656 INVARIANT(
4657 total_width > member_width,
4658 "total width should be greater than member_width as member_width is at "
4659 "most as large as total_width and the other case has been handled "
4660 "above");
4661 out << "(concat ";
4662 out << "((_ extract "
4663 << (total_width-1)
4664 << " " << member_width << ") ";
4665 convert_expr(expr.old());
4666 out << ") ";
4667 flatten2bv(value);
4668 out << ")";
4669 }
4670 }
4671 else if(expr_type.id()==ID_bv ||
4672 expr_type.id()==ID_unsignedbv ||
4673 expr_type.id()==ID_signedbv)
4674 {
4675 if(expr.new_value().type().id() == ID_bool)
4676 {
4678 update_bit_exprt(expr.old(), expr.where(), expr.new_value()));
4679 }
4680 else
4681 {
4683 update_bits_exprt(expr.old(), expr.where(), expr.new_value()));
4684 }
4685 }
4686 else
4688 "with expects struct, union, or array type, but got "+
4689 expr.type().id_string());
4690}
4691
4693{
4694 PRECONDITION(expr.operands().size() == 3);
4695
4696 SMT2_TODO("smt2_convt::convert_update to be implemented");
4697}
4698
4700{
4701 return convert_expr(expr.lower());
4702}
4703
4705{
4706 return convert_expr(expr.lower());
4707}
4708
4710{
4711 const typet &array_op_type = expr.array().type();
4712
4713 if(array_op_type.id()==ID_array)
4714 {
4716
4717 if(use_array_theory(expr.array()))
4718 {
4719 if(expr.is_boolean() && !use_array_of_bool)
4720 {
4721 out << "(= ";
4722 out << "(select ";
4723 convert_expr(expr.array());
4724 out << " ";
4725 convert_expr(typecast_exprt(expr.index(), array_type.index_type()));
4726 out << ")";
4727 out << " #b1)";
4728 }
4729 else
4730 {
4731 out << "(select ";
4732 convert_expr(expr.array());
4733 out << " ";
4734 convert_expr(typecast_exprt(expr.index(), array_type.index_type()));
4735 out << ")";
4736 }
4737 }
4738 else
4739 {
4740 // fixed size
4741 std::size_t array_width=boolbv_width(array_type);
4742
4743 unflatten(wheret::BEGIN, array_type.element_type());
4744
4745 std::size_t sub_width = boolbv_width(array_type.element_type());
4746 std::size_t index_width=boolbv_width(expr.index().type());
4747
4748 out << "((_ extract " << sub_width-1 << " 0) ";
4749 out << "(bvlshr ";
4750 convert_expr(expr.array());
4751 out << " ";
4752 out << "(bvmul (_ bv" << sub_width << " " << array_width << ") ";
4753
4754 // SMT2 says that the shift distance must be the same as
4755 // the width of what we shift.
4757 {
4758 out << "((_ zero_extend " << array_width-index_width << ") ";
4759 convert_expr(expr.index());
4760 out << ")"; // zero_extend
4761 }
4762 else
4763 {
4764 out << "((_ extract " << array_width-1 << " 0) ";
4765 convert_expr(expr.index());
4766 out << ")"; // extract
4767 }
4768
4769 out << ")))"; // mult, bvlshr, extract
4770
4771 unflatten(wheret::END, array_type.element_type());
4772 }
4773 }
4774 else
4775 INVARIANT(
4776 false, "index with unsupported array type: " + array_op_type.id_string());
4777}
4778
4780{
4782 const exprt &struct_op=member_expr.struct_op();
4783 const typet &struct_op_type = struct_op.type();
4784 const irep_idt &name=member_expr.get_component_name();
4785
4787 {
4788 const struct_typet &struct_type =
4790 ? ns.follow_tag(to_struct_tag_type(struct_op_type))
4792
4793 INVARIANT(
4794 struct_type.has_component(name), "struct should have accessed component");
4795
4796 if(use_datatypes)
4797 {
4798 const std::string &smt_typename = datatype_map.at(struct_type);
4799
4800 out << "(" << smt_typename << "."
4801 << struct_type.get_component(name).get_name()
4802 << " ";
4803 convert_expr(struct_op);
4804 out << ")";
4805 }
4806 else
4807 {
4808 // we extract
4809 const auto &member_offset = boolbv_width.get_member(struct_type, name);
4810
4811 if(expr.type().id() == ID_bool)
4812 out << "(= ";
4813 out << "((_ extract " << (member_offset.offset + member_offset.width - 1)
4814 << " " << member_offset.offset << ") ";
4815 convert_expr(struct_op);
4816 out << ")";
4817 if(expr.type().id() == ID_bool)
4818 out << " #b1)";
4819 }
4820 }
4821 else if(
4823 {
4824 std::size_t width=boolbv_width(expr.type());
4826 width != 0, "failed to get union member width");
4827
4828 if(use_datatypes)
4829 {
4830 unflatten(wheret::BEGIN, expr.type());
4831
4832 out << "((_ extract " << (width - 1) << " 0) ";
4833 convert_expr(struct_op);
4834 out << ")";
4835
4836 unflatten(wheret::END, expr.type());
4837 }
4838 else
4839 {
4840 out << "((_ extract " << (width - 1) << " 0) ";
4841 convert_expr(struct_op);
4842 out << ")";
4843 }
4844 }
4845 else
4847 "convert_member on an unexpected type "+struct_op_type.id_string());
4848}
4849
4851{
4852 const typet &type = expr.type();
4853
4854 if(type.id()==ID_bool)
4855 {
4856 out << "(ite ";
4857 convert_expr(expr); // this returns a Bool
4858 out << " #b1 #b0)"; // this is a one-bit bit-vector
4859 }
4860 else if(type.id()==ID_array)
4861 {
4862 if(use_array_theory(expr))
4863 {
4864 // concatenate elements
4865 const array_typet &array_type = to_array_type(type);
4866
4867 mp_integer size =
4869
4870 // SMT-LIB 2 concat is binary only
4871 std::size_t n_concat = 0;
4872 for(mp_integer i = size; i > 1; --i)
4873 {
4874 ++n_concat;
4875 out << "(concat ";
4876
4877 flatten2bv(
4878 index_exprt{expr, from_integer(i - 1, array_type.index_type())});
4879
4880 out << " ";
4881 }
4882
4883 flatten2bv(index_exprt{expr, from_integer(0, array_type.index_type())});
4884
4885 out << std::string(n_concat, ')'); // concat
4886 }
4887 else
4888 convert_expr(expr);
4889 }
4890 else if(type.id() == ID_struct || type.id() == ID_struct_tag)
4891 {
4892 if(use_datatypes)
4893 {
4894 // concatenate elements
4895 const struct_typet &struct_type =
4896 type.id() == ID_struct_tag ? ns.follow_tag(to_struct_tag_type(type))
4897 : to_struct_type(type);
4898
4899 const struct_typet::componentst &components=
4900 struct_type.components();
4901
4902 // SMT-LIB 2 concat is binary only
4903 std::size_t n_concat = 0;
4904 for(std::size_t i=components.size(); i>1; i--)
4905 {
4906 if(is_zero_width(components[i - 1].type(), ns))
4907 continue;
4908 else if(i > 2 || !is_zero_width(components[0].type(), ns))
4909 {
4910 ++n_concat;
4911 out << "(concat ";
4912 }
4913
4914 flatten2bv(member_exprt{expr, components[i - 1]});
4915
4916 out << " ";
4917 }
4918
4919 if(!is_zero_width(components[0].type(), ns))
4920 {
4921 flatten2bv(member_exprt{expr, components[0]});
4922 }
4923
4924 out << std::string(n_concat, ')'); // concat
4925 }
4926 else
4927 convert_expr(expr);
4928 }
4929 else if(type.id()==ID_floatbv)
4930 {
4931 INVARIANT(
4933 "floatbv expressions should be flattened when using FPA theory");
4934
4935 convert_expr(expr);
4936 }
4937 else
4938 convert_expr(expr);
4939}
4940
4942 wheret where,
4943 const typet &type,
4944 unsigned nesting)
4945{
4946 if(type.id()==ID_bool)
4947 {
4948 if(where==wheret::BEGIN)
4949 out << "(= "; // produces a bool
4950 else
4951 out << " #b1)";
4952 }
4953 else if(type.id() == ID_array)
4954 {
4956
4957 if(where == wheret::BEGIN)
4958 out << "(let ((?ufop" << nesting << " ";
4959 else
4960 {
4961 out << ")) ";
4962
4963 const array_typet &array_type = to_array_type(type);
4964
4965 std::size_t subtype_width = boolbv_width(array_type.element_type());
4966
4968 array_type.size().is_constant(),
4969 "cannot unflatten arrays of non-constant size");
4970 mp_integer size =
4972
4973 for(mp_integer i = 1; i < size; ++i)
4974 out << "(store ";
4975
4976 out << "((as const ";
4978 out << ") ";
4979 // use element at index 0 as default value
4980 unflatten(wheret::BEGIN, array_type.element_type(), nesting + 1);
4981 out << "((_ extract " << subtype_width - 1 << " "
4982 << "0) ?ufop" << nesting << ")";
4983 unflatten(wheret::END, array_type.element_type(), nesting + 1);
4984 out << ") ";
4985
4986 std::size_t offset = subtype_width;
4987 for(mp_integer i = 1; i < size; ++i, offset += subtype_width)
4988 {
4989 convert_expr(from_integer(i, array_type.index_type()));
4990 out << ' ';
4991 unflatten(wheret::BEGIN, array_type.element_type(), nesting + 1);
4992 out << "((_ extract " << offset + subtype_width - 1 << " " << offset
4993 << ") ?ufop" << nesting << ")";
4994 unflatten(wheret::END, array_type.element_type(), nesting + 1);
4995 out << ")"; // store
4996 }
4997
4998 out << ")"; // let
4999 }
5000 }
5001 else if(type.id() == ID_struct || type.id() == ID_struct_tag)
5002 {
5003 if(use_datatypes)
5004 {
5005 // extract members
5006 if(where==wheret::BEGIN)
5007 out << "(let ((?ufop" << nesting << " ";
5008 else
5009 {
5010 out << ")) ";
5011
5012 const std::string &smt_typename = datatype_map.at(type);
5013
5014 out << "(mk-" << smt_typename;
5015
5016 const struct_typet &struct_type =
5017 type.id() == ID_struct_tag ? ns.follow_tag(to_struct_tag_type(type))
5018 : to_struct_type(type);
5019
5020 const struct_typet::componentst &components=
5021 struct_type.components();
5022
5023 std::size_t offset=0;
5024
5025 std::size_t i=0;
5026 for(struct_typet::componentst::const_iterator
5027 it=components.begin();
5028 it!=components.end();
5029 it++, i++)
5030 {
5031 if(is_zero_width(it->type(), ns))
5032 continue;
5033
5034 std::size_t member_width=boolbv_width(it->type());
5035
5036 out << " ";
5037 unflatten(wheret::BEGIN, it->type(), nesting+1);
5038 out << "((_ extract " << offset+member_width-1 << " "
5039 << offset << ") ?ufop" << nesting << ")";
5040 unflatten(wheret::END, it->type(), nesting+1);
5041 offset+=member_width;
5042 }
5043
5044 out << "))"; // mk-, let
5045 }
5046 }
5047 else
5048 {
5049 // nop, already a bv
5050 }
5051 }
5052 else
5053 {
5054 // nop
5055 }
5056}
5057
5058void smt2_convt::set_to(const exprt &expr, bool value)
5059{
5060 PRECONDITION(expr.is_boolean());
5061
5062 if(expr.id()==ID_and && value)
5063 {
5064 for(const auto &op : expr.operands())
5065 set_to(op, true);
5066 return;
5067 }
5068
5069 if(expr.id()==ID_or && !value)
5070 {
5071 for(const auto &op : expr.operands())
5072 set_to(op, false);
5073 return;
5074 }
5075
5076 if(expr.id()==ID_not)
5077 {
5078 return set_to(to_not_expr(expr).op(), !value);
5079 }
5080
5081 out << "\n";
5082
5083 // special treatment for "set_to(a=b, true)" where
5084 // a is a new symbol
5085
5086 if(expr.id() == ID_equal && value)
5087 {
5089 if(is_zero_width(equal_expr.lhs().type(), ns))
5090 {
5091 // ignore equality checking over expressions with empty (void) type
5092 return;
5093 }
5094
5095 if(equal_expr.lhs().id()==ID_symbol)
5096 {
5097 const irep_idt &identifier=
5098 to_symbol_expr(equal_expr.lhs()).get_identifier();
5099
5100 if(
5101 identifier_map.find(identifier) == identifier_map.end() &&
5102 equal_expr.lhs() != equal_expr.rhs())
5103 {
5104 auto id_entry = identifier_map.insert(
5105 {identifier, identifiert{equal_expr.lhs().type(), false}});
5106 CHECK_RETURN(id_entry.second);
5107
5108 find_symbols(id_entry.first->second.type);
5110
5111 std::string smt2_identifier=convert_identifier(identifier);
5113
5114 out << "; set_to true (equal)\n";
5115
5116 if(equal_expr.lhs().type().id() == ID_mathematical_function)
5117 {
5118 // We avoid define-fun, since it has been reported to cause
5119 // trouble with Z3's parser.
5120 out << "(declare-fun " << smt2_identifier;
5121
5124
5125 out << " (";
5126 bool first = true;
5127
5128 for(auto &t : mathematical_function_type.domain())
5129 {
5130 if(first)
5131 first = false;
5132 else
5133 out << ' ';
5134
5135 convert_type(t);
5136 }
5137
5138 out << ") ";
5140 out << ")\n";
5141
5142 out << "(assert (= " << smt2_identifier << ' ';
5144 out << ')' << ')' << '\n';
5145 }
5146 else
5147 {
5148 out << "(define-fun " << smt2_identifier;
5149 out << " () ";
5150 convert_type(equal_expr.lhs().type());
5151 out << ' ';
5152 if(
5153 equal_expr.lhs().type().id() != ID_array ||
5155 {
5157 }
5158 else
5159 {
5160 unflatten(wheret::BEGIN, equal_expr.lhs().type());
5161
5163
5164 unflatten(wheret::END, equal_expr.lhs().type());
5165 }
5166 out << ')' << '\n';
5167 }
5168
5169 return; // done
5170 }
5171 }
5172 }
5173
5175
5176#if 0
5177 out << "; CONV: "
5178 << format(expr) << "\n";
5179#endif
5180
5181 out << "; set_to " << (value?"true":"false") << "\n"
5182 << "(assert ";
5183 if(!value)
5184 {
5185 out << "(not ";
5186 }
5187 const auto found_literal = defined_expressions.find(expr);
5188 if(!(found_literal == defined_expressions.end()))
5189 {
5190 // This is a converted expression, we can just assert the literal name
5191 // since the expression is already defined
5192 out << found_literal->second;
5193 set_values[found_literal->second] = value;
5194 }
5195 else
5196 {
5198 }
5199 if(!value)
5200 {
5201 out << ")";
5202 }
5203 out << ")\n";
5204 return;
5205}
5206
5214{
5215 exprt lowered_expr = expr;
5216
5217 for(auto it = lowered_expr.depth_begin(), itend = lowered_expr.depth_end();
5218 it != itend;
5219 ++it)
5220 {
5221 if(
5222 it->id() == ID_byte_extract_little_endian ||
5223 it->id() == ID_byte_extract_big_endian)
5224 {
5225 it.mutate() = lower_byte_extract(to_byte_extract_expr(*it), ns);
5226 }
5227 else if(
5228 it->id() == ID_byte_update_little_endian ||
5229 it->id() == ID_byte_update_big_endian)
5230 {
5231 it.mutate() = lower_byte_update(to_byte_update_expr(*it), ns);
5232 }
5233 }
5234
5235 return lowered_expr;
5236}
5237
5246{
5247 // First, replace byte operators, because they may introduce new array
5248 // expressions that must be seen by find_symbols:
5250 INVARIANT(
5252 "lower_byte_operators should remove all byte operators");
5253
5254 // Perform rewrites that may introduce new symbols
5255 for(auto it = lowered_expr.depth_begin(), itend = lowered_expr.depth_end();
5256 it != itend;) // no ++it
5257 {
5258 if(
5259 auto prophecy_r_or_w_ok =
5261 {
5263 it.mutate() = lowered;
5264 it.next_sibling_or_parent();
5265 }
5266 else if(
5269 {
5271 it.mutate() = lowered;
5272 it.next_sibling_or_parent();
5273 }
5274 else
5275 ++it;
5276 }
5277
5278 // Now create symbols for all composite expressions present in lowered_expr:
5280
5281 return lowered_expr;
5282}
5283
5285{
5286 if(is_zero_width(expr.type(), ns))
5287 return;
5288
5289 // recursive call on type
5290 find_symbols(expr.type());
5291
5292 if(expr.id() == ID_exists || expr.id() == ID_forall)
5293 {
5294 std::unordered_map<irep_idt, std::optional<identifiert>> shadowed_syms;
5295
5296 // do not declare the quantified symbol, but record
5297 // as 'bound symbol'
5298 const auto &q_expr = to_quantifier_expr(expr);
5299 for(const auto &symbol : q_expr.variables())
5300 {
5301 const auto identifier = symbol.get_identifier();
5302 auto id_entry =
5303 identifier_map.insert({identifier, identifiert{symbol.type(), true}});
5304 shadowed_syms.insert(
5305 {identifier,
5306 id_entry.second ? std::nullopt
5307 : std::optional{id_entry.first->second}});
5308 }
5309 find_symbols(q_expr.where());
5310 for(const auto &[id, shadowed_val] : shadowed_syms)
5311 {
5312 auto previous_entry = identifier_map.find(id);
5313 if(!shadowed_val.has_value())
5315 else
5316 previous_entry->second = std::move(*shadowed_val);
5317 }
5318 return;
5319 }
5320
5321 // recursive call on operands
5322 for(const auto &op : expr.operands())
5323 find_symbols(op);
5324
5325 if(expr.id()==ID_symbol ||
5326 expr.id()==ID_nondet_symbol)
5327 {
5328 // we don't track function-typed symbols
5329 if(expr.type().id()==ID_code)
5330 return;
5331
5332 irep_idt identifier;
5333
5334 if(expr.id()==ID_symbol)
5335 identifier=to_symbol_expr(expr).get_identifier();
5336 else
5337 identifier="nondet_"+
5338 id2string(to_nondet_symbol_expr(expr).get_identifier());
5339
5340 auto id_entry =
5341 identifier_map.insert({identifier, identifiert{expr.type(), false}});
5342
5343 if(id_entry.second)
5344 {
5345 std::string smt2_identifier=convert_identifier(identifier);
5347
5348 out << "; find_symbols\n";
5349 out << "(declare-fun " << smt2_identifier;
5350
5351 if(expr.type().id() == ID_mathematical_function)
5352 {
5355 out << " (";
5356 bool first = true;
5357
5358 for(auto &type : mathematical_function_type.domain())
5359 {
5360 if(first)
5361 first = false;
5362 else
5363 out << ' ';
5364 convert_type(type);
5365 }
5366
5367 out << ") ";
5369 }
5370 else
5371 {
5372 out << " () ";
5373 convert_type(expr.type());
5374 }
5375
5376 out << ")" << "\n";
5377 }
5378 }
5379 else if(expr.id() == ID_array_of)
5380 {
5381 if(!use_as_const)
5382 {
5383 if(defined_expressions.find(expr) == defined_expressions.end())
5384 {
5385 const auto &array_of = to_array_of_expr(expr);
5386 const auto &array_type = array_of.type();
5387
5388 const irep_idt id =
5389 "array_of." + std::to_string(defined_expressions.size());
5390 out << "; the following is a substitute for lambda i. x\n";
5391 out << "(declare-fun " << id << " () ";
5393 out << ")\n";
5394
5395 if(!is_zero_width(array_type.element_type(), ns))
5396 {
5397 // use a quantifier-based initialization instead of lambda
5398 out << "(assert (forall ((i ";
5399 convert_type(array_type.index_type());
5400 out << ")) (= (select " << id << " i) ";
5401 if(array_type.element_type().id() == ID_bool && !use_array_of_bool)
5402 {
5403 out << "(ite ";
5404 convert_expr(array_of.what());
5405 out << " #b1 #b0)";
5406 }
5407 else
5408 {
5409 convert_expr(array_of.what());
5410 }
5411 out << ")))\n";
5412 }
5413
5414 defined_expressions[expr] = id;
5415 }
5416 }
5417 }
5418 else if(expr.id() == ID_array_comprehension)
5419 {
5421 {
5422 if(defined_expressions.find(expr) == defined_expressions.end())
5423 {
5425 const auto &array_type = array_comprehension.type();
5426 const auto &array_size = array_type.size();
5427
5428 const irep_idt id =
5429 "array_comprehension." + std::to_string(defined_expressions.size());
5430 out << "(declare-fun " << id << " () ";
5432 out << ")\n";
5433
5434 out << "; the following is a substitute for lambda i . x(i)\n";
5435 out << "; universally quantified initialization of the array\n";
5436 out << "(assert (forall ((";
5438 out << " ";
5439 convert_type(array_size.type());
5440 out << ")) (=> (and (bvule (_ bv0 " << boolbv_width(array_size.type())
5441 << ") ";
5443 out << ") (bvult ";
5445 out << " ";
5447 out << ")) (= (select " << id << " ";
5449 out << ") ";
5450 if(array_type.element_type().id() == ID_bool && !use_array_of_bool)
5451 {
5452 out << "(ite ";
5454 out << " #b1 #b0)";
5455 }
5456 else
5457 {
5459 }
5460 out << "))))\n";
5461
5462 defined_expressions[expr] = id;
5463 }
5464 }
5465 }
5466 else if(expr.id()==ID_array)
5467 {
5468 if(defined_expressions.find(expr)==defined_expressions.end())
5469 {
5471
5472 const irep_idt id = "array." + std::to_string(defined_expressions.size());
5473 out << "; the following is a substitute for an array constructor" << "\n";
5474 out << "(declare-fun " << id << " () ";
5476 out << ")" << "\n";
5477
5478 if(!is_zero_width(array_type.element_type(), ns))
5479 {
5480 for(std::size_t i = 0; i < expr.operands().size(); i++)
5481 {
5482 out << "(assert (= (select " << id << " ";
5483 convert_expr(from_integer(i, array_type.index_type()));
5484 out << ") "; // select
5485 if(array_type.element_type().id() == ID_bool && !use_array_of_bool)
5486 {
5487 out << "(ite ";
5488 convert_expr(expr.operands()[i]);
5489 out << " #b1 #b0)";
5490 }
5491 else
5492 {
5493 convert_expr(expr.operands()[i]);
5494 }
5495 out << "))"
5496 << "\n"; // =, assert
5497 }
5498 }
5499
5500 defined_expressions[expr]=id;
5501 }
5502 }
5503 else if(expr.id()==ID_string_constant)
5504 {
5505 if(defined_expressions.find(expr)==defined_expressions.end())
5506 {
5507 // introduce a temporary array.
5508 exprt tmp=to_string_constant(expr).to_array_expr();
5509 const array_typet &array_type=to_array_type(tmp.type());
5510
5511 const irep_idt id =
5512 "string." + std::to_string(defined_expressions.size());
5513 out << "; the following is a substitute for a string" << "\n";
5514 out << "(declare-fun " << id << " () ";
5516 out << ")" << "\n";
5517
5518 for(std::size_t i=0; i<tmp.operands().size(); i++)
5519 {
5520 out << "(assert (= (select " << id << ' ';
5521 convert_expr(from_integer(i, array_type.index_type()));
5522 out << ") "; // select
5523 convert_expr(tmp.operands()[i]);
5524 out << "))" << "\n";
5525 }
5526
5527 defined_expressions[expr]=id;
5528 }
5529 }
5530 else if(
5532 {
5533 if(object_sizes.find(*object_size) == object_sizes.end())
5534 {
5535 const irep_idt id = convert_identifier(
5536 "object_size." + std::to_string(object_sizes.size()));
5537 out << "(declare-fun " << id << " () ";
5539 out << ")"
5540 << "\n";
5541
5543 }
5544 }
5545 // clang-format off
5546 else if(!use_FPA_theory &&
5547 expr.operands().size() >= 1 &&
5548 (expr.id() == ID_floatbv_plus ||
5549 expr.id() == ID_floatbv_minus ||
5550 expr.id() == ID_floatbv_mult ||
5551 expr.id() == ID_floatbv_div ||
5552 expr.id() == ID_floatbv_typecast ||
5553 expr.id() == ID_ieee_float_equal ||
5554 expr.id() == ID_ieee_float_notequal ||
5555 ((expr.id() == ID_lt ||
5556 expr.id() == ID_gt ||
5557 expr.id() == ID_le ||
5558 expr.id() == ID_ge ||
5559 expr.id() == ID_isnan ||
5560 expr.id() == ID_isnormal ||
5561 expr.id() == ID_isfinite ||
5562 expr.id() == ID_isinf ||
5563 expr.id() == ID_sign ||
5564 expr.id() == ID_unary_minus ||
5565 expr.id() == ID_typecast ||
5566 expr.id() == ID_abs) &&
5567 to_multi_ary_expr(expr).op0().type().id() == ID_floatbv)))
5568 // clang-format on
5569 {
5570 irep_idt function =
5571 convert_identifier("float_bv." + expr.id_string() + floatbv_suffix(expr));
5572
5573 if(bvfp_set.insert(function).second)
5574 {
5575 out << "; this is a model for " << expr.id() << " : "
5576 << type2id(to_multi_ary_expr(expr).op0().type()) << " -> "
5577 << type2id(expr.type()) << "\n"
5578 << "(define-fun " << function << " (";
5579
5580 for(std::size_t i = 0; i < expr.operands().size(); i++)
5581 {
5582 if(i!=0)
5583 out << " ";
5584 out << "(op" << i << ' ';
5585 convert_type(expr.operands()[i].type());
5586 out << ')';
5587 }
5588
5589 out << ") ";
5590 convert_type(expr.type()); // return type
5591 out << ' ';
5592
5593 exprt tmp1=expr;
5594 for(std::size_t i = 0; i < tmp1.operands().size(); i++)
5595 tmp1.operands()[i]=
5596 smt2_symbolt("op"+std::to_string(i), tmp1.operands()[i].type());
5597
5599 tmp2=letify(tmp2);
5600 CHECK_RETURN(!tmp2.is_nil());
5601
5603
5604 out << ")\n"; // define-fun
5605 }
5606 }
5607 else if(
5608 use_FPA_theory && expr.id() == ID_typecast &&
5609 to_typecast_expr(expr).op().type().id() == ID_floatbv &&
5610 expr.type().id() == ID_bv)
5611 {
5612 // This is _NOT_ a semantic conversion, but bit-wise.
5613 if(defined_expressions.find(expr) == defined_expressions.end())
5614 {
5615 // This conversion is non-trivial as it requires creating a
5616 // new bit-vector variable and then asserting that it converts
5617 // to the required floating-point number.
5618 const irep_idt id =
5619 "bvfromfloat." + std::to_string(defined_expressions.size());
5620 out << "(declare-fun " << id << " () ";
5621 convert_type(expr.type());
5622 out << ')' << '\n';
5623
5624 const typecast_exprt &tc = to_typecast_expr(expr);
5625 const auto &floatbv_type = to_floatbv_type(tc.op().type());
5626 out << "(assert (= ";
5627 out << "((_ to_fp " << floatbv_type.get_e() << " "
5628 << floatbv_type.get_f() + 1 << ") " << id << ')';
5629 convert_expr(tc.op());
5630 out << ')'; // =
5631 out << ')' << '\n';
5632
5633 defined_expressions[expr] = id;
5634 }
5635 }
5636 else if(expr.id() == ID_initial_state)
5637 {
5638 irep_idt function = "initial-state";
5639
5640 if(state_fkt_declared.insert(function).second)
5641 {
5642 out << "(declare-fun " << function << " (";
5643 convert_type(to_unary_expr(expr).op().type());
5644 out << ") ";
5645 convert_type(expr.type()); // return type
5646 out << ")\n"; // declare-fun
5647 }
5648 }
5649 else if(expr.id() == ID_evaluate)
5650 {
5651 irep_idt function = "evaluate-" + type2id(expr.type());
5652
5653 if(state_fkt_declared.insert(function).second)
5654 {
5655 out << "(declare-fun " << function << " (";
5656 convert_type(to_binary_expr(expr).op0().type());
5657 out << ' ';
5658 convert_type(to_binary_expr(expr).op1().type());
5659 out << ") ";
5660 convert_type(expr.type()); // return type
5661 out << ")\n"; // declare-fun
5662 }
5663 }
5664 else if(
5665 expr.id() == ID_state_is_cstring ||
5666 expr.id() == ID_state_is_dynamic_object ||
5667 expr.id() == ID_state_live_object || expr.id() == ID_state_writeable_object)
5668 {
5669 irep_idt function =
5670 expr.id() == ID_state_is_cstring ? "state-is-cstring"
5671 : expr.id() == ID_state_is_dynamic_object ? "state-is-dynamic-object"
5672 : expr.id() == ID_state_live_object ? "state-live-object"
5673 : "state-writeable-object";
5674
5675 if(state_fkt_declared.insert(function).second)
5676 {
5677 out << "(declare-fun " << function << " (";
5678 convert_type(to_binary_expr(expr).op0().type());
5679 out << ' ';
5680 convert_type(to_binary_expr(expr).op1().type());
5681 out << ") ";
5682 convert_type(expr.type()); // return type
5683 out << ")\n"; // declare-fun
5684 }
5685 }
5686 else if(
5687 expr.id() == ID_state_r_ok || expr.id() == ID_state_w_ok ||
5688 expr.id() == ID_state_rw_ok)
5689 {
5690 irep_idt function = expr.id() == ID_state_r_ok ? "state-r-ok"
5691 : expr.id() == ID_state_w_ok ? "state-w-ok"
5692 : "state-rw-ok";
5693
5694 if(state_fkt_declared.insert(function).second)
5695 {
5696 out << "(declare-fun " << function << " (";
5697 convert_type(to_ternary_expr(expr).op0().type());
5698 out << ' ';
5699 convert_type(to_ternary_expr(expr).op1().type());
5700 out << ' ';
5701 convert_type(to_ternary_expr(expr).op2().type());
5702 out << ") ";
5703 convert_type(expr.type()); // return type
5704 out << ")\n"; // declare-fun
5705 }
5706 }
5707 else if(expr.id() == ID_update_state)
5708 {
5709 irep_idt function =
5710 "update-state-" + type2id(to_multi_ary_expr(expr).op2().type());
5711
5712 if(state_fkt_declared.insert(function).second)
5713 {
5714 out << "(declare-fun " << function << " (";
5715 convert_type(to_multi_ary_expr(expr).op0().type());
5716 out << ' ';
5717 convert_type(to_multi_ary_expr(expr).op1().type());
5718 out << ' ';
5719 convert_type(to_multi_ary_expr(expr).op2().type());
5720 out << ") ";
5721 convert_type(expr.type()); // return type
5722 out << ")\n"; // declare-fun
5723 }
5724 }
5725 else if(expr.id() == ID_enter_scope_state)
5726 {
5727 irep_idt function =
5728 "enter-scope-state-" + type2id(to_binary_expr(expr).op1().type());
5729
5730 if(state_fkt_declared.insert(function).second)
5731 {
5732 out << "(declare-fun " << function << " (";
5733 convert_type(to_binary_expr(expr).op0().type());
5734 out << ' ';
5735 convert_type(to_binary_expr(expr).op1().type());
5736 out << ' ';
5738 out << ") ";
5739 convert_type(expr.type()); // return type
5740 out << ")\n"; // declare-fun
5741 }
5742 }
5743 else if(expr.id() == ID_exit_scope_state)
5744 {
5745 irep_idt function =
5746 "exit-scope-state-" + type2id(to_binary_expr(expr).op1().type());
5747
5748 if(state_fkt_declared.insert(function).second)
5749 {
5750 out << "(declare-fun " << function << " (";
5751 convert_type(to_binary_expr(expr).op0().type());
5752 out << ' ';
5753 convert_type(to_binary_expr(expr).op1().type());
5754 out << ") ";
5755 convert_type(expr.type()); // return type
5756 out << ")\n"; // declare-fun
5757 }
5758 }
5759 else if(expr.id() == ID_allocate)
5760 {
5761 irep_idt function = "allocate";
5762
5763 if(state_fkt_declared.insert(function).second)
5764 {
5765 out << "(declare-fun " << function << " (";
5766 convert_type(to_binary_expr(expr).op0().type());
5767 out << ' ';
5768 convert_type(to_binary_expr(expr).op1().type());
5769 out << ") ";
5770 convert_type(expr.type()); // return type
5771 out << ")\n"; // declare-fun
5772 }
5773 }
5774 else if(expr.id() == ID_reallocate)
5775 {
5776 irep_idt function = "reallocate";
5777
5778 if(state_fkt_declared.insert(function).second)
5779 {
5780 out << "(declare-fun " << function << " (";
5781 convert_type(to_ternary_expr(expr).op0().type());
5782 out << ' ';
5783 convert_type(to_ternary_expr(expr).op1().type());
5784 out << ' ';
5785 convert_type(to_ternary_expr(expr).op2().type());
5786 out << ") ";
5787 convert_type(expr.type()); // return type
5788 out << ")\n"; // declare-fun
5789 }
5790 }
5791 else if(expr.id() == ID_deallocate_state)
5792 {
5793 irep_idt function = "deallocate";
5794
5795 if(state_fkt_declared.insert(function).second)
5796 {
5797 out << "(declare-fun " << function << " (";
5798 convert_type(to_binary_expr(expr).op0().type());
5799 out << ' ';
5800 convert_type(to_binary_expr(expr).op1().type());
5801 out << ") ";
5802 convert_type(expr.type()); // return type
5803 out << ")\n"; // declare-fun
5804 }
5805 }
5806 else if(expr.id() == ID_object_address)
5807 {
5808 irep_idt function = "object-address";
5809
5810 if(state_fkt_declared.insert(function).second)
5811 {
5812 out << "(declare-fun " << function << " (String) ";
5813 convert_type(expr.type()); // return type
5814 out << ")\n"; // declare-fun
5815 }
5816 }
5817 else if(expr.id() == ID_field_address)
5818 {
5819 irep_idt function = "field-address-" + type2id(expr.type());
5820
5821 if(state_fkt_declared.insert(function).second)
5822 {
5823 out << "(declare-fun " << function << " (";
5824 convert_type(to_field_address_expr(expr).op().type());
5825 out << ' ';
5826 out << "String";
5827 out << ") ";
5828 convert_type(expr.type()); // return type
5829 out << ")\n"; // declare-fun
5830 }
5831 }
5832 else if(expr.id() == ID_element_address)
5833 {
5834 irep_idt function = "element-address-" + type2id(expr.type());
5835
5836 if(state_fkt_declared.insert(function).second)
5837 {
5838 out << "(declare-fun " << function << " (";
5839 convert_type(to_element_address_expr(expr).base().type());
5840 out << ' ';
5841 convert_type(to_element_address_expr(expr).index().type());
5842 out << ' '; // repeat, for the element size
5843 convert_type(to_element_address_expr(expr).index().type());
5844 out << ") ";
5845 convert_type(expr.type()); // return type
5846 out << ")\n"; // declare-fun
5847 }
5848 }
5849}
5850
5852{
5853 const typet &type = expr.type();
5854 PRECONDITION(type.id()==ID_array);
5855
5856 // arrays inside structs get flattened, unless we have datatypes
5857 if(expr.id() == ID_with)
5858 return use_array_theory(to_with_expr(expr).old());
5859 else
5860 return use_datatypes || expr.id() != ID_member;
5861}
5862
5864{
5865 if(type.id()==ID_array)
5866 {
5868 CHECK_RETURN(array_type.size().is_not_nil());
5869
5870 // we always use array theory for top-level arrays
5871 const typet &subtype = array_type.element_type();
5872
5873 // Arrays map the index type to the element type.
5874 out << "(Array ";
5875 convert_type(array_type.index_type());
5876 out << " ";
5877
5878 if(subtype.id()==ID_bool && !use_array_of_bool)
5879 out << "(_ BitVec 1)";
5880 else
5881 convert_type(array_type.element_type());
5882
5883 out << ")";
5884 }
5885 else if(type.id()==ID_bool)
5886 {
5887 out << "Bool";
5888 }
5889 else if(type.id() == ID_struct || type.id() == ID_struct_tag)
5890 {
5891 if(use_datatypes)
5892 {
5893 out << datatype_map.at(type);
5894 }
5895 else
5896 {
5897 std::size_t width=boolbv_width(type);
5898
5899 out << "(_ BitVec " << width << ")";
5900 }
5901 }
5902 else if(type.id()==ID_code)
5903 {
5904 // These may appear in structs.
5905 // We replace this by "Bool" in order to keep the same
5906 // member count.
5907 out << "Bool";
5908 }
5909 else if(type.id() == ID_union || type.id() == ID_union_tag)
5910 {
5911 std::size_t width=boolbv_width(type);
5912 const union_typet &union_type = type.id() == ID_union_tag
5913 ? ns.follow_tag(to_union_tag_type(type))
5914 : to_union_type(type);
5916 union_type.components().empty() || width != 0,
5917 "failed to get width of union");
5918
5919 out << "(_ BitVec " << width << ")";
5920 }
5921 else if(type.id()==ID_pointer)
5922 {
5923 out << "(_ BitVec "
5924 << boolbv_width(type) << ")";
5925 }
5926 else if(type.id()==ID_bv ||
5927 type.id()==ID_fixedbv ||
5928 type.id()==ID_unsignedbv ||
5929 type.id()==ID_signedbv ||
5930 type.id()==ID_c_bool)
5931 {
5932 out << "(_ BitVec "
5933 << to_bitvector_type(type).get_width() << ")";
5934 }
5935 else if(type.id()==ID_c_enum)
5936 {
5937 // these have an underlying type
5938 out << "(_ BitVec "
5939 << to_bitvector_type(to_c_enum_type(type).underlying_type()).get_width()
5940 << ")";
5941 }
5942 else if(type.id()==ID_c_enum_tag)
5943 {
5944 convert_type(ns.follow_tag(to_c_enum_tag_type(type)));
5945 }
5946 else if(type.id()==ID_floatbv)
5947 {
5949
5950 if(use_FPA_theory)
5951 out << "(_ FloatingPoint "
5952 << floatbv_type.get_e() << " "
5953 << floatbv_type.get_f() + 1 << ")";
5954 else
5955 out << "(_ BitVec "
5956 << floatbv_type.get_width() << ")";
5957 }
5958 else if(type.id()==ID_rational ||
5959 type.id()==ID_real)
5960 out << "Real";
5961 else if(type.id()==ID_integer)
5962 out << "Int";
5963 else if(type.id() == ID_natural)
5964 out << "Nat";
5965 else if(type.id()==ID_complex)
5966 {
5967 if(use_datatypes)
5968 {
5969 out << datatype_map.at(type);
5970 }
5971 else
5972 {
5973 std::size_t width=boolbv_width(type);
5974
5975 out << "(_ BitVec " << width << ")";
5976 }
5977 }
5978 else if(type.id()==ID_c_bit_field)
5979 {
5981 }
5982 else if(type.id() == ID_state)
5983 {
5984 out << "state";
5985 }
5986 else if(type.id() == ID_range)
5987 {
5988 auto &range_type = to_range_type(type);
5989 mp_integer size = range_type.get_to() - range_type.get_from() + 1;
5990 if(size <= 0)
5991 UNEXPECTEDCASE("unsuppored range type");
5992 out << "(_ BitVec " << address_bits(size) << ")";
5993 }
5994 else
5995 {
5996 UNEXPECTEDCASE("unsupported type: "+type.id_string());
5997 }
5998}
5999
6001{
6002 std::set<irep_idt> recstack;
6004}
6005
6007 const typet &type,
6008 std::set<irep_idt> &recstack)
6009{
6010 if(type.id()==ID_array)
6011 {
6013 find_symbols(array_type.size());
6014 find_symbols_rec(array_type.element_type(), recstack);
6015 }
6016 else if(type.id()==ID_complex)
6017 {
6018 find_symbols_rec(to_complex_type(type).subtype(), recstack);
6019
6020 if(use_datatypes &&
6021 datatype_map.find(type)==datatype_map.end())
6022 {
6023 const std::string smt_typename =
6024 "complex." + std::to_string(datatype_map.size());
6025 datatype_map[type] = smt_typename;
6026
6027 out << "(declare-datatypes ((" << smt_typename << " 0)) "
6028 << "(((mk-" << smt_typename;
6029
6030 out << " (" << smt_typename << ".imag ";
6031 convert_type(to_complex_type(type).subtype());
6032 out << ")";
6033
6034 out << " (" << smt_typename << ".real ";
6035 convert_type(to_complex_type(type).subtype());
6036 out << ")";
6037
6038 out << "))))\n";
6039 }
6040 }
6041 else if(type.id() == ID_struct)
6042 {
6043 // Cater for mutually recursive struct types
6044 bool need_decl=false;
6045 if(use_datatypes &&
6046 datatype_map.find(type)==datatype_map.end())
6047 {
6048 const std::string smt_typename =
6049 "struct." + std::to_string(datatype_map.size());
6050 datatype_map[type] = smt_typename;
6051 need_decl=true;
6052 }
6053
6054 const struct_typet::componentst &components =
6055 to_struct_type(type).components();
6056
6057 for(const auto &component : components)
6059
6060 // Declare the corresponding SMT type if we haven't already.
6061 if(need_decl)
6062 {
6063 const std::string &smt_typename = datatype_map.at(type);
6064
6065 // We're going to create a datatype named something like `struct.0'.
6066 // It's going to have a single constructor named `mk-struct.0' with an
6067 // argument for each member of the struct. The declaration that
6068 // creates this type looks like:
6069 //
6070 // (declare-datatypes ((struct.0 0)) (((mk-struct.0
6071 // (struct.0.component1 type1)
6072 // ...
6073 // (struct.0.componentN typeN)))))
6074 out << "(declare-datatypes ((" << smt_typename << " 0)) "
6075 << "(((mk-" << smt_typename << " ";
6076
6077 for(const auto &component : components)
6078 {
6079 if(is_zero_width(component.type(), ns))
6080 continue;
6081
6082 out << "(" << smt_typename << "." << component.get_name()
6083 << " ";
6084 convert_type(component.type());
6085 out << ") ";
6086 }
6087
6088 out << "))))" << "\n";
6089
6090 // Let's also declare convenience functions to update individual
6091 // members of the struct whil we're at it. The functions are
6092 // named like `update-struct.0.component1'. Their declarations
6093 // look like:
6094 //
6095 // (declare-fun update-struct.0.component1
6096 // ((s struct.0) ; first arg -- the struct to update
6097 // (v type1)) ; second arg -- the value to update
6098 // struct.0 ; the output type
6099 // (mk-struct.0 ; build the new struct...
6100 // v ; the updated value
6101 // (struct.0.component2 s) ; retain the other members
6102 // ...
6103 // (struct.0.componentN s)))
6104
6105 for(struct_union_typet::componentst::const_iterator
6106 it=components.begin();
6107 it!=components.end();
6108 ++it)
6109 {
6110 if(is_zero_width(it->type(), ns))
6111 continue;
6112
6114 out << "(define-fun update-" << smt_typename << "."
6115 << component.get_name() << " "
6116 << "((s " << smt_typename << ") "
6117 << "(v ";
6118 convert_type(component.type());
6119 out << ")) " << smt_typename << " "
6120 << "(mk-" << smt_typename
6121 << " ";
6122
6123 for(struct_union_typet::componentst::const_iterator
6124 it2=components.begin();
6125 it2!=components.end();
6126 ++it2)
6127 {
6128 if(it==it2)
6129 out << "v ";
6130 else if(!is_zero_width(it2->type(), ns))
6131 {
6132 out << "(" << smt_typename << "."
6133 << it2->get_name() << " s) ";
6134 }
6135 }
6136
6137 out << "))" << "\n";
6138 }
6139
6140 out << "\n";
6141 }
6142 }
6143 else if(type.id() == ID_union)
6144 {
6145 const union_typet::componentst &components =
6146 to_union_type(type).components();
6147
6148 for(const auto &component : components)
6150 }
6151 else if(type.id()==ID_code)
6152 {
6153 const code_typet::parameterst &parameters=
6154 to_code_type(type).parameters();
6155 for(const auto &param : parameters)
6157
6158 find_symbols_rec(to_code_type(type).return_type(), recstack);
6159 }
6160 else if(type.id()==ID_pointer)
6161 {
6162 find_symbols_rec(to_pointer_type(type).base_type(), recstack);
6163 }
6164 else if(type.id() == ID_struct_tag)
6165 {
6166 const auto &struct_tag = to_struct_tag_type(type);
6167 const irep_idt &id = struct_tag.get_identifier();
6168
6169 if(recstack.find(id) == recstack.end())
6170 {
6171 const auto &base_struct = ns.follow_tag(struct_tag);
6172 recstack.insert(id);
6175 }
6176 }
6177 else if(type.id() == ID_union_tag)
6178 {
6179 const auto &union_tag = to_union_tag_type(type);
6180 const irep_idt &id = union_tag.get_identifier();
6181
6182 if(recstack.find(id) == recstack.end())
6183 {
6184 recstack.insert(id);
6185 find_symbols_rec(ns.follow_tag(union_tag), recstack);
6186 }
6187 }
6188 else if(type.id() == ID_state)
6189 {
6190 if(datatype_map.find(type) == datatype_map.end())
6191 {
6192 datatype_map[type] = "state";
6193 out << "(declare-sort state 0)\n";
6194 }
6195 }
6196 else if(type.id() == ID_mathematical_function)
6197 {
6198 const auto &mathematical_function_type =
6200 for(auto &d_type : mathematical_function_type.domain())
6202
6204 }
6205}
6206
6208{
6210}
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
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
std::size_t address_bits(const mp_integer &size)
ceil(log2(size))
bool to_integer(const constant_exprt &expr, mp_integer &int_value)
Convert a constant expression expr to an arbitrary-precision integer.
irep_idt integer2bvrep(const mp_integer &src, std::size_t width)
convert an integer to bit-vector representation with given width This uses two's complement for negat...
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 onehot0_exprt & to_onehot0_expr(const exprt &expr)
Cast an exprt to a onehot0_exprt.
const replication_exprt & to_replication_expr(const exprt &expr)
Cast an exprt to a replication_exprt.
const shift_exprt & to_shift_expr(const exprt &expr)
Cast an exprt to a shift_exprt.
const popcount_exprt & to_popcount_expr(const exprt &expr)
Cast an exprt to a popcount_exprt.
const update_bits_exprt & to_update_bits_expr(const exprt &expr)
Cast an exprt to an update_bits_exprt.
const extractbits_exprt & to_extractbits_expr(const exprt &expr)
Cast an exprt to an extractbits_exprt.
const onehot_exprt & to_onehot_expr(const exprt &expr)
Cast an exprt to a onehot_exprt.
bool can_cast_expr< minus_overflow_exprt >(const exprt &base)
const find_first_set_exprt & to_find_first_set_expr(const exprt &expr)
Cast an exprt to a find_first_set_exprt.
bool can_cast_expr< overflow_result_exprt >(const exprt &base)
const update_bit_exprt & to_update_bit_expr(const exprt &expr)
Cast an exprt to an update_bit_exprt.
const bitnot_exprt & to_bitnot_expr(const exprt &expr)
Cast an exprt to a bitnot_exprt.
const bswap_exprt & to_bswap_expr(const exprt &expr)
Cast an exprt to a bswap_exprt.
const count_leading_zeros_exprt & to_count_leading_zeros_expr(const exprt &expr)
Cast an exprt to a count_leading_zeros_exprt.
const bitreverse_exprt & to_bitreverse_expr(const exprt &expr)
Cast an exprt to a bitreverse_exprt.
const extractbit_exprt & to_extractbit_expr(const exprt &expr)
Cast an exprt to an extractbit_exprt.
const zero_extend_exprt & to_zero_extend_expr(const exprt &expr)
Cast an exprt to a zero_extend_exprt.
const count_trailing_zeros_exprt & to_count_trailing_zeros_expr(const exprt &expr)
Cast an exprt to a count_trailing_zeros_exprt.
const bv_typet & to_bv_type(const typet &type)
Cast a typet to a bv_typet.
const fixedbv_typet & to_fixedbv_type(const typet &type)
Cast a typet to a fixedbv_typet.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
const unsignedbv_typet & to_unsignedbv_type(const typet &type)
Cast a typet to an unsignedbv_typet.
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
bool has_byte_operator(const exprt &src)
Return true iff src or one of its operands contain a byte extract or byte update expression.
Expression classes for byte-level operators.
const byte_update_exprt & to_byte_update_expr(const exprt &expr)
exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
Rewrite a byte extract expression to more fundamental operations.
const byte_extract_exprt & to_byte_extract_expr(const exprt &expr)
exprt lower_byte_update(const byte_update_exprt &src, const namespacet &ns)
Rewrite a byte update expression to more fundamental operations.
typet c_bit_field_replacement_type(const c_bit_field_typet &src, const namespacet &ns)
pointer_typet pointer_type(const typet &subtype)
Definition c_types.cpp:235
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
Definition c_types.h:80
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition c_types.h:335
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
Definition c_types.h:377
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition c_types.h:184
const c_bool_typet & to_c_bool_type(const typet &type)
Cast a typet to a c_bool_typet.
Definition c_types.h:128
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition c_types.h:224
Absolute value.
Definition std_expr.h:443
Operator to return the address of an object.
virtual void clear()
Reset the abstract state.
Definition ai.h:265
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Represents real numbers as roots (zeros) of a polynomial with rational coefficients.
Thrown when an unexpected error occurs during the analysis (e.g., when the SAT solver returns an erro...
Pointer-typed bitvector constant annotated with the pointer expression that the bitvector is the nume...
Array constructor from list of elements.
Definition std_expr.h:1640
Arrays with given size.
Definition std_types.h:807
const exprt & size() const
Definition std_types.h:840
const typet & element_type() const
The type of the elements of the array.
Definition std_types.h:827
A base class for binary expressions.
Definition std_expr.h:639
exprt & lhs()
Definition std_expr.h:669
exprt & rhs()
Definition std_expr.h:679
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:763
Bit-wise negation of bit-vectors.
The Boolean type.
Definition std_types.h:36
const membert & get_member(const struct_typet &type, const irep_idt &member) const
The byte swap expression.
std::vector< parametert > parameterst
Definition std_types.h:586
struct configt::bv_encodingt bv_encoding
A constant literal expression.
Definition std_expr.h:3145
const irep_idt & get_value() const
Definition std_expr.h:3153
bool is_null_pointer() const
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
Definition std_expr.cpp:170
resultt
Result of running the decision procedure.
Division.
Definition std_expr.h:1176
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Equality.
Definition std_expr.h:1385
Boute's Euclidean definition of Modulo – to match SMT-LIB2.
Definition std_expr.h:1315
Base class for all expressions.
Definition expr.h:57
std::vector< exprt > operandst
Definition expr.h:59
bool has_operands() const
Return true if there is at least one operand.
Definition expr.h:92
bool is_boolean() const
Return whether the expression represents a Boolean.
Definition expr.h:229
exprt & op0()
Definition expr.h:134
exprt & op1()
Definition expr.h:137
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:213
typet & type()
Return the type of the expression.
Definition expr.h:85
void visit_post(std::function< void(exprt &)>)
These are post-order traversal visitors, i.e., the visitor is executed on a node after its children h...
Definition expr.cpp:119
operandst & operands()
Definition expr.h:95
Extracts a single bit of a bit-vector operand.
Extracts a sub-range of a bit-vector operand.
The Boolean constant false.
Definition std_expr.h:3273
std::size_t integer_bits
Definition fixedbv.h:22
std::size_t width
Definition fixedbv.h:22
std::size_t get_fraction_bits() const
Definition fixedbv.h:35
Fixed-width bit-vector with signed fixed-point interpretation.
Round a floating-point number to an integral value considering the given rounding mode.
Semantic type conversion from/to floating-point formats.
Fixed-width bit-vector with IEEE floating-point interpretation.
IEEE floating-point operations These have two data operands (op0 and op1) and one rounding mode (op2)...
std::size_t f
Definition ieee_float.h:26
std::size_t width() const
Definition ieee_float.h:50
An IEEE 754 floating-point value, including specificiation.
Definition ieee_float.h:117
static ieee_float_valuet minus_infinity(const ieee_float_spect &_spec)
Definition ieee_float.h:209
bool is_NaN() const
Definition ieee_float.h:259
static ieee_float_valuet one(const floatbv_typet &)
ieee_float_spect spec
Definition ieee_float.h:119
mp_integer pack() const
bool get_sign() const
Definition ieee_float.h:254
static ieee_float_valuet zero(const floatbv_typet &type)
Definition ieee_float.h:172
static ieee_float_valuet NaN(const ieee_float_spect &_spec)
Definition ieee_float.h:195
static ieee_float_valuet plus_infinity(const ieee_float_spect &_spec)
Definition ieee_float.h:202
bool is_infinity() const
Definition ieee_float.h:260
The trinary if-then-else operator.
Definition std_expr.h:2529
Boolean implication.
Definition std_expr.h:2252
Array index operator.
Definition std_expr.h:1489
exprt & index()
Definition std_expr.h:1529
exprt & array()
Definition std_expr.h:1519
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition irep.h:364
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition irep.cpp:482
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:44
const std::string & id_string() const
Definition irep.h:391
subt & get_sub()
Definition irep.h:448
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
bool is_nil() const
Definition irep.h:368
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:3405
bool is_true() const
Definition literal.h:156
bool sign() const
Definition literal.h:88
var_not var_no() const
Definition literal.h:83
bool is_false() const
Definition literal.h:161
Extract member of struct or union.
Definition std_expr.h:2999
Binary minus.
Definition std_expr.h:1075
Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
Definition std_expr.h:1247
Binary multiplication Associativity is not specified.
Definition std_expr.h:1121
exprt & op1()
Definition std_expr.h:947
exprt & op0()
Definition std_expr.h:941
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition namespace.cpp:49
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
The NIL expression.
Definition std_expr.h:3282
Boolean negation.
Definition std_expr.h:2486
Disequality.
Definition std_expr.h:1444
Expression for finding the size (in bytes) of the object a pointer points to.
The plus expression Associativity is not specified.
Definition std_expr.h:1011
const mp_integer & get_invalid_object() const
numberingt< exprt, irep_hash > objects
exprt pointer_expr(const pointert &pointer, const pointer_typet &type) const
Convert an (object,offset) pair to an expression.
void get_dynamic_objects(std::vector< mp_integer > &objects) const
mp_integer add_object(const exprt &expr)
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
A base class for quantifier expressions.
Unbounded, signed rational numbers.
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:597
void convert_relation(const binary_relation_exprt &)
bool use_lambda_for_array
Definition smt2_conv.h:72
void convert_type(const typet &)
void unflatten(wheret, const typet &, unsigned nesting=0)
bool use_array_theory(const exprt &)
void find_symbols(const exprt &expr)
std::size_t number_of_solver_calls
Definition smt2_conv.h:111
void convert_typecast(const typecast_exprt &expr)
void write_footer()
Writes the end of the SMT file to the smt_convt::out stream.
tvt l_get(literalt l) const
void convert_floatbv_rem(const binary_exprt &expr)
std::unordered_map< irep_idt, irept > current_bindings
Definition smt2_conv.h:200
bool use_FPA_theory
Definition smt2_conv.h:67
resultt dec_solve(const exprt &) override
Implementation of the decision procedure.
std::set< irep_idt > bvfp_set
Definition smt2_conv.h:206
void convert_address_of_rec(const exprt &expr, const pointer_typet &result_type)
void push() override
Unimplemented.
void convert_is_dynamic_object(const unary_exprt &)
void convert_literal(const literalt)
void convert_floatbv_div(const ieee_float_op_exprt &expr)
void convert_string_literal(const std::string &)
std::size_t get_number_of_solver_calls() const override
Return the number of incremental solver calls.
const namespacet & ns
Definition smt2_conv.h:100
void convert_floatbv_mult(const ieee_float_op_exprt &expr)
boolbv_widtht boolbv_width
Definition smt2_conv.h:109
void convert_constant(const constant_exprt &expr)
std::string floatbv_suffix(const exprt &) const
void flatten2bv(const exprt &)
std::string notes
Definition smt2_conv.h:102
void convert_div(const div_exprt &expr)
std::ostream & out
Definition smt2_conv.h:101
exprt lower_byte_operators(const exprt &expr)
Lower byte_update and byte_extract operations within expr.
std::string type2id(const typet &) const
bool emit_set_logic
Definition smt2_conv.h:73
void convert_rounding_mode_FPA(const exprt &expr)
Converting a constant or symbolic rounding mode to SMT-LIB.
void convert_floatbv_typecast(const floatbv_typecast_exprt &expr)
struct_exprt parse_struct(const irept &s, const struct_typet &type)
std::string logic
Definition smt2_conv.h:102
void convert_mult(const mult_exprt &expr)
void convert_update_bit(const update_bit_exprt &)
exprt prepare_for_convert_expr(const exprt &expr)
Perform steps necessary before an expression is passed to convert_expr.
exprt get(const exprt &expr) const override
Return expr with variables replaced by values from satisfying assignment if available.
std::string decision_procedure_text() const override
Return a textual description of the decision procedure.
void convert_floatbv_minus(const ieee_float_op_exprt &expr)
bool use_check_sat_assuming
Definition smt2_conv.h:70
std::map< object_size_exprt, irep_idt > object_sizes
Definition smt2_conv.h:287
void define_object_size(const irep_idt &id, const object_size_exprt &expr)
bool use_datatypes
Definition smt2_conv.h:71
datatype_mapt datatype_map
Definition smt2_conv.h:272
void convert_mod(const mod_exprt &expr)
static std::string convert_identifier(const irep_idt &identifier)
void convert_floatbv_plus(const ieee_float_op_exprt &expr)
void convert_struct(const struct_exprt &expr)
std::unordered_map< irep_idt, bool > set_values
The values which boolean identifiers have been smt2_convt::set_to or in other words those which are a...
Definition smt2_conv.h:285
smt2_convt(const namespacet &_ns, const std::string &_benchmark, const std::string &_notes, const std::string &_logic, solvert _solver, std::ostream &_out)
Definition smt2_conv.cpp:59
void convert_member(const member_exprt &expr)
void convert_euclidean_mod(const euclidean_mod_exprt &expr)
void convert_index(const index_exprt &expr)
converterst converters
Definition smt2_conv.h:106
pointer_logict pointer_logic
Definition smt2_conv.h:240
exprt handle(const exprt &expr) override
Generate a handle, which is an expression that has the same value as the argument in any model that i...
void print_assignment(std::ostream &out) const override
Print satisfying assignment to out.
void walk_array_tree(std::unordered_map< int64_t, exprt > *operands_map, const irept &src, const array_typet &type)
This function walks the SMT output and populates a map with index/value pairs for the array.
void convert_floatbv_round_to_integral(const floatbv_round_to_integral_exprt &)
void set_to(const exprt &expr, bool value) override
For a Boolean expression expr, add the constraint 'expr' if value is true, otherwise add 'not expr'.
bool use_as_const
Definition smt2_conv.h:69
exprt parse_rec(const irept &s, const typet &type)
void convert_union(const union_exprt &expr)
exprt parse_union(const irept &s, const union_typet &type)
exprt parse_array(const irept &s, const array_typet &type)
This function is for parsing array output from SMT solvers when "(get-value |???|)" returns an array ...
std::vector< bool > boolean_assignment
Definition smt2_conv.h:294
void flatten_array(const exprt &)
produce a flat bit-vector for a given array of fixed size
void convert_with(const with_exprt &expr)
letifyt letify
Definition smt2_conv.h:177
bool use_array_of_bool
Definition smt2_conv.h:68
std::vector< literalt > assumptions
Definition smt2_conv.h:108
void convert_plus(const plus_exprt &expr)
defined_expressionst defined_expressions
Definition smt2_conv.h:281
void pop() override
Currently, only implements a single stack element (no nested contexts)
void convert_update_bits(const update_bits_exprt &)
void find_symbols_rec(const typet &type, std::set< irep_idt > &recstack)
void convert_update(const update_exprt &)
void write_header()
std::set< irep_idt > state_fkt_declared
Definition smt2_conv.h:210
solvert solver
Definition smt2_conv.h:103
identifier_mapt identifier_map
Definition smt2_conv.h:265
void convert_minus(const minus_exprt &expr)
void convert_expr(const exprt &)
constant_exprt parse_literal(const irept &, const typet &type)
const smt2_symbolt & to_smt2_symbol(const exprt &expr)
Definition smt2_conv.h:225
std::size_t no_boolean_variables
Definition smt2_conv.h:293
smt2_identifierst smt2_identifiers
Definition smt2_conv.h:290
void convert_floatbv(const exprt &expr)
literalt convert(const exprt &expr)
Struct constructor from list of elements.
Definition std_expr.h:1896
Structure type, corresponds to C style structs.
Definition std_types.h:231
const irep_idt & get_name() const
Definition std_types.h:79
const componentst & components() const
Definition std_types.h:147
std::vector< componentt > componentst
Definition std_types.h:140
The Boolean constant true.
Definition std_expr.h:3264
Definition threeval.h:20
Semantic type conversion.
Definition std_expr.h:2092
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:2100
The type of an expression, extends irept.
Definition type.h:29
Generic base class for unary expressions.
Definition std_expr.h:362
const exprt & op() const
Definition std_expr.h:392
The unary minus expression.
Definition std_expr.h:485
Union constructor from single element.
Definition std_expr.h:1789
The union type.
Definition c_types.h:147
Fixed-width bit-vector with unsigned binary interpretation.
Replaces a sub-range of a bit-vector operand.
exprt lower() const
A lowering to masking, shifting, or.
Replaces a sub-range of a bit-vector operand.
exprt lower() const
A lowering to masking, shifting, or.
Operator to update elements in structs and arrays.
Definition std_expr.h:2810
Operator to update elements in structs and arrays.
Definition std_expr.h:2630
exprt & new_value()
Definition std_expr.h:2660
exprt & where()
Definition std_expr.h:2650
exprt & old()
Definition std_expr.h:2640
bool has_prefix(const std::string &s, const std::string &prefix)
Definition converter.cpp:13
int isdigit(int c)
Definition ctype.c:24
Forward depth-first search iterators These iterators' copy operations are expensive,...
exprt make_binary(const exprt &expr)
splits an expression with >=3 operands into nested binary expressions
Definition expr_util.cpp:38
Deprecated expression utility functions.
exprt float_bv(const exprt &src)
Definition float_bv.h:188
API to expression classes for floating-point arithmetic.
const ieee_float_op_exprt & to_ieee_float_op_expr(const exprt &expr)
Cast an exprt to an ieee_float_op_exprt.
const floatbv_round_to_integral_exprt & to_floatbv_round_to_integral_expr(const exprt &expr)
Cast an exprt to a floatbv_round_to_integral_exprt.
const isnormal_exprt & to_isnormal_expr(const exprt &expr)
Cast an exprt to a isnormal_exprt.
const isinf_exprt & to_isinf_expr(const exprt &expr)
Cast an exprt to a isinf_exprt.
const isfinite_exprt & to_isfinite_expr(const exprt &expr)
Cast an exprt to a isfinite_exprt.
const isnan_exprt & to_isnan_expr(const exprt &expr)
Cast an exprt to a isnan_exprt.
const floatbv_typecast_exprt & to_floatbv_typecast_expr(const exprt &expr)
Cast an exprt to a floatbv_typecast_exprt.
static format_containert< T > format(const T &o)
Definition format.h:37
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
static std::string binary(const constant_exprt &src)
exprt to_expr(const namespacet &ns, const irep_idt &identifier, const std::string &src)
bool is_true(const literalt &l)
Definition literal.h:198
literalt const_literal(bool value)
Definition literal.h:188
literalt pos(literalt a)
Definition literal.h:194
const literal_exprt & to_literal_expr(const exprt &expr)
Cast a generic exprt to a literal_exprt.
double pow(double x, double y)
Definition math.c:3049
API to expression classes for 'mathematical' expressions.
const quantifier_exprt & to_quantifier_expr(const exprt &expr)
Cast an exprt to a quantifier_exprt.
const function_application_exprt & to_function_application_expr(const exprt &expr)
Cast an exprt to a function_application_exprt.
const mathematical_function_typet & to_mathematical_function_type(const typet &type)
Cast a typet to a mathematical_function_typet.
const mp_integer string2integer(const std::string &n, unsigned base)
Definition mp_arith.cpp:54
mp_integer bitwise_or(const mp_integer &a, const mp_integer &b)
bitwise 'or' of two nonnegative integers
Definition mp_arith.cpp:215
const std::string integer2binary(const mp_integer &n, std::size_t width)
Definition mp_arith.cpp:64
const element_address_exprt & to_element_address_expr(const exprt &expr)
Cast an exprt to an element_address_exprt.
const object_address_exprt & to_object_address_expr(const exprt &expr)
Cast an exprt to an object_address_exprt.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
const pointer_offset_exprt & to_pointer_offset_expr(const exprt &expr)
Cast an exprt to a pointer_offset_exprt.
const pointer_object_exprt & to_pointer_object_expr(const exprt &expr)
Cast an exprt to a pointer_object_exprt.
const field_address_exprt & to_field_address_expr(const exprt &expr)
Cast an exprt to an field_address_exprt.
std::optional< mp_integer > pointer_offset_size(const typet &type, const namespacet &ns)
Compute the size of a type in bytes, rounding up to full bytes.
std::optional< exprt > size_of_expr(const typet &type, const namespacet &ns)
std::optional< mp_integer > member_offset(const struct_typet &type, const irep_idt &member, const namespacet &ns)
Pointer Logic.
exprt pointer_offset(const exprt &pointer)
exprt object_size(const exprt &pointer)
exprt same_object(const exprt &p1, const exprt &p2)
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
bool to_rational(const exprt &expr, rationalt &rational_value)
constant_exprt from_rational(const rationalt &a)
exprt simplify_expr(exprt src, const namespacet &ns)
static bool has_quantifier(const exprt &expr)
#define SMT2_TODO(S)
Definition smt2_conv.cpp:57
static bool is_zero_width(const typet &type, const namespacet &ns)
Returns true iff type has effective width of zero bits.
static bool is_smt2_simple_identifier(const std::string &identifier)
#define UNEXPECTEDCASE(S)
Definition smt2_conv.cpp:54
bool is_smt2_simple_symbol_character(char ch)
void solver(std::vector< framet > &frames, const std::unordered_set< symbol_exprt, irep_hash > &address_taken, const solver_optionst &solver_options, const namespacet &ns, std::vector< propertyt > &properties, std::size_t property_index)
Definition solver.cpp:44
#define CHECK_RETURN(CONDITION)
Definition invariant.h:495
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define UNIMPLEMENTED
Definition invariant.h:558
#define INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Same as invariant, with one or more diagnostics attached Diagnostics can be of any type that has a sp...
Definition invariant.h:437
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
#define CHECK_RETURN_WITH_DIAGNOSTICS(CONDITION,...)
Definition invariant.h:496
#define DATA_INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Definition invariant.h:535
#define UNREACHABLE_BECAUSE(REASON)
Definition invariant.h:526
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition std_expr.cpp:291
API to expression classes.
const struct_exprt & to_struct_expr(const exprt &expr)
Cast an exprt to a struct_exprt.
Definition std_expr.h:1919
const array_of_exprt & to_array_of_expr(const exprt &expr)
Cast an exprt to an array_of_exprt.
Definition std_expr.h:1622
const binary_relation_exprt & to_binary_relation_expr(const exprt &expr)
Cast an exprt to a binary_relation_exprt.
Definition std_expr.h:896
const unary_plus_exprt & to_unary_plus_expr(const exprt &expr)
Cast an exprt to a unary_plus_exprt.
Definition std_expr.h:557
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1557
const mod_exprt & to_mod_expr(const exprt &expr)
Cast an exprt to a mod_exprt.
Definition std_expr.h:1296
const mult_exprt & to_mult_expr(const exprt &expr)
Cast an exprt to a mult_exprt.
Definition std_expr.h:1156
const array_comprehension_exprt & to_array_comprehension_expr(const exprt &expr)
Cast an exprt to a array_comprehension_exprt.
Definition std_expr.h:3805
const ternary_exprt & to_ternary_expr(const exprt &expr)
Cast an exprt to a ternary_exprt.
Definition std_expr.h:117
const named_term_exprt & to_named_term_expr(const exprt &expr)
Cast an exprt to a named_term_exprt.
Definition std_expr.h:3987
const cond_exprt & to_cond_expr(const exprt &expr)
Cast an exprt to a cond_exprt.
Definition std_expr.h:3591
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2126
const div_exprt & to_div_expr(const exprt &expr)
Cast an exprt to a div_exprt.
Definition std_expr.h:1225
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition std_expr.h:716
const plus_exprt & to_plus_expr(const exprt &expr)
Cast an exprt to a plus_exprt.
Definition std_expr.h:1055
const notequal_exprt & to_notequal_expr(const exprt &expr)
Cast an exprt to an notequal_exprt.
Definition std_expr.h:1469
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:427
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition std_expr.h:996
const let_exprt & to_let_expr(const exprt &expr)
Cast an exprt to a let_exprt.
Definition std_expr.h:3529
const abs_exprt & to_abs_expr(const exprt &expr)
Cast an exprt to a abs_exprt.
Definition std_expr.h:467
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition std_expr.h:2609
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:3091
const minus_exprt & to_minus_expr(const exprt &expr)
Cast an exprt to a minus_exprt.
Definition std_expr.h:1100
const union_exprt & to_union_expr(const exprt &expr)
Cast an exprt to a union_exprt.
Definition std_expr.h:1835
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3216
const not_exprt & to_not_expr(const exprt &expr)
Cast an exprt to an not_exprt.
Definition std_expr.h:2511
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:273
const with_exprt & to_with_expr(const exprt &expr)
Cast an exprt to a with_exprt.
Definition std_expr.h:2688
const implies_exprt & to_implies_expr(const exprt &expr)
Cast an exprt to a implies_exprt.
Definition std_expr.h:2277
const update_exprt & to_update_expr(const exprt &expr)
Cast an exprt to an update_exprt.
Definition std_expr.h:2893
const unary_minus_exprt & to_unary_minus_expr(const exprt &expr)
Cast an exprt to a unary_minus_exprt.
Definition std_expr.h:515
const equal_exprt & to_equal_expr(const exprt &expr)
Cast an exprt to an equal_exprt.
Definition std_expr.h:1426
const nondet_symbol_exprt & to_nondet_symbol_expr(const exprt &expr)
Cast an exprt to a nondet_symbol_exprt.
Definition std_expr.h:344
const sign_exprt & to_sign_expr(const exprt &expr)
Cast an exprt to a sign_exprt.
Definition std_expr.h:622
const euclidean_mod_exprt & to_euclidean_mod_expr(const exprt &expr)
Cast an exprt to a euclidean_mod_exprt.
Definition std_expr.h:1364
const range_typet & to_range_type(const typet &type)
Cast a typet to a range_typet.
Definition std_types.h:1040
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:308
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition std_types.h:518
const complex_typet & to_complex_type(const typet &type)
Cast a typet to a complex_typet.
Definition std_types.h:1158
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition std_types.h:214
std::size_t unsafe_string2size_t(const std::string &str, int base)
const string_constantt & to_string_constant(const exprt &expr)
static bool failed(bool error_indicator)
#define size_type
Definition unistd.c:186