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