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