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