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_integer_range_type(type).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_integer_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_reduction_and_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_reduction_nand_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_reduction_or_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_reduction_nor_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_reduction_xor_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_reduction_xnor_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_width = address_bits(dest_range_type.size());
3251 if(src_type.id() == ID_range)
3252 {
3254 const auto src_width = address_bits(src_range_type.size());
3255 if(src_width < dest_width)
3256 {
3257 out << "((_ zero_extend " << dest_width - src_width << ") ";
3258 convert_expr(src);
3259 out << ')'; // zero_extend
3260 }
3261 else if(src_width > dest_width)
3262 {
3263 out << "((_ extract " << dest_width - 1 << " 0) ";
3264 convert_expr(src);
3265 out << ')'; // extract
3266 }
3267 else // src_width == dest_width
3268 {
3269 convert_expr(src);
3270 }
3271 }
3272 else
3273 SMT2_TODO("typecast from " + src_type.id_string() + " to range");
3274 }
3275 else if(dest_type.id()==ID_floatbv)
3276 {
3277 // Typecast from integer to floating-point should have be been
3278 // converted to ID_floatbv_typecast during symbolic execution,
3279 // adding the rounding mode. See
3280 // smt2_convt::convert_floatbv_typecast.
3281 // The exception is bool and c_bool to float.
3283
3284 if(src_type.id()==ID_bool)
3285 {
3286 out << "(ite ";
3287 convert_expr(src);
3288 out << ' ';
3290 out << ' ';
3292 out << ')';
3293 }
3294 else if(src_type.id()==ID_c_bool)
3295 {
3296 // turn into proper bool
3297 const typecast_exprt tmp(src, bool_typet());
3299 }
3300 else if(src_type.id() == ID_bv)
3301 {
3302 if(to_bv_type(src_type).get_width() != dest_floatbv_type.get_width())
3303 {
3304 UNEXPECTEDCASE("Typecast bv -> float with wrong width");
3305 }
3306
3307 if(use_FPA_theory)
3308 {
3309 out << "((_ to_fp " << dest_floatbv_type.get_e() << " "
3310 << dest_floatbv_type.get_f() + 1 << ") ";
3311 convert_expr(src);
3312 out << ')';
3313 }
3314 else
3315 convert_expr(src);
3316 }
3317 else
3318 UNEXPECTEDCASE("Unknown typecast "+src_type.id_string()+" -> float");
3319 }
3320 else if(dest_type.id() == ID_integer || dest_type.id() == ID_natural)
3321 {
3322 if(src_type.id()==ID_bool)
3323 {
3324 out << "(ite ";
3325 convert_expr(src);
3326 out <<" 1 0)";
3327 }
3328 else
3329 UNEXPECTEDCASE("Unknown typecast "+src_type.id_string()+" -> integer");
3330 }
3331 else if(dest_type.id()==ID_c_bit_field)
3332 {
3333 std::size_t from_width=boolbv_width(src_type);
3334 std::size_t to_width=boolbv_width(dest_type);
3335
3336 if(from_width==to_width)
3337 convert_expr(src); // ignore
3338 else
3339 {
3343 }
3344 }
3345 else if(dest_type.id() == ID_rational)
3346 {
3347 if(src_type.id() == ID_signedbv)
3348 {
3349 // TODO: negative numbers
3350 out << "(/ ";
3351 convert_expr(src);
3352 out << " 1)";
3353 }
3354 else
3356 "Unknown typecast " + src_type.id_string() + " -> rational");
3357 }
3358 else
3360 "TODO typecast8 "+src_type.id_string()+" -> "+dest_type.id_string());
3361}
3362
3364{
3365 const exprt &src=expr.op();
3366 // const exprt &rounding_mode=expr.rounding_mode();
3367 const typet &src_type=src.type();
3368 const typet &dest_type=expr.type();
3369
3370 if(dest_type.id()==ID_floatbv)
3371 {
3372 if(src_type.id()==ID_floatbv)
3373 {
3374 // float to float
3375
3376 /* ISO 9899:1999
3377 * 6.3.1.5 Real floating types
3378 * 1 When a float is promoted to double or long double, or a
3379 * double is promoted to long double, its value is unchanged.
3380 *
3381 * 2 When a double is demoted to float, a long double is
3382 * demoted to double or float, or a value being represented in
3383 * greater precision and range than required by its semantic
3384 * type (see 6.3.1.8) is explicitly converted to its semantic
3385 * type, if the value being converted can be represented
3386 * exactly in the new type, it is unchanged. If the value
3387 * being converted is in the range of values that can be
3388 * represented but cannot be represented exactly, the result
3389 * is either the nearest higher or nearest lower representable
3390 * value, chosen in an implementation-defined manner. If the
3391 * value being converted is outside the range of values that
3392 * can be represented, the behavior is undefined.
3393 */
3394
3396
3397 if(use_FPA_theory)
3398 {
3399 out << "((_ to_fp " << dst.get_e() << " "
3400 << dst.get_f() + 1 << ") ";
3402 out << " ";
3403 convert_expr(src);
3404 out << ")";
3405 }
3406 else
3407 convert_floatbv(expr);
3408 }
3409 else if(src_type.id()==ID_unsignedbv)
3410 {
3411 // unsigned to float
3412
3413 /* ISO 9899:1999
3414 * 6.3.1.4 Real floating and integer
3415 * 2 When a value of integer type is converted to a real
3416 * floating type, if the value being converted can be
3417 * represented exactly in the new type, it is unchanged. If the
3418 * value being converted is in the range of values that can be
3419 * represented but cannot be represented exactly, the result is
3420 * either the nearest higher or nearest lower representable
3421 * value, chosen in an implementation-defined manner. If the
3422 * value being converted is outside the range of values that can
3423 * be represented, the behavior is undefined.
3424 */
3425
3427
3428 if(use_FPA_theory)
3429 {
3430 out << "((_ to_fp_unsigned " << dst.get_e() << " "
3431 << dst.get_f() + 1 << ") ";
3433 out << " ";
3434 convert_expr(src);
3435 out << ")";
3436 }
3437 else
3438 convert_floatbv(expr);
3439 }
3440 else if(src_type.id()==ID_signedbv)
3441 {
3442 // signed to float
3443
3445
3446 if(use_FPA_theory)
3447 {
3448 out << "((_ to_fp " << dst.get_e() << " "
3449 << dst.get_f() + 1 << ") ";
3451 out << " ";
3452 convert_expr(src);
3453 out << ")";
3454 }
3455 else
3456 convert_floatbv(expr);
3457 }
3458 else if(src_type.id()==ID_c_enum_tag)
3459 {
3460 // enum to float
3461
3462 // We first convert to 'underlying type'
3464 tmp.op() = typecast_exprt(
3465 src, ns.follow_tag(to_c_enum_tag_type(src_type)).underlying_type());
3467 }
3468 else
3470 "TODO typecast11 "+src_type.id_string()+" -> "+dest_type.id_string());
3471 }
3472 else if(dest_type.id()==ID_signedbv)
3473 {
3474 if(use_FPA_theory)
3475 {
3476 std::size_t dest_width=to_signedbv_type(dest_type).get_width();
3477 out << "((_ fp.to_sbv " << dest_width << ") ";
3479 out << " ";
3480 convert_expr(src);
3481 out << ")";
3482 }
3483 else
3484 convert_floatbv(expr);
3485 }
3486 else if(dest_type.id()==ID_unsignedbv)
3487 {
3488 if(use_FPA_theory)
3489 {
3490 std::size_t dest_width=to_unsignedbv_type(dest_type).get_width();
3491 out << "((_ fp.to_ubv " << dest_width << ") ";
3493 out << " ";
3494 convert_expr(src);
3495 out << ")";
3496 }
3497 else
3498 convert_floatbv(expr);
3499 }
3500 else
3501 {
3503 "TODO typecast12 "+src_type.id_string()+" -> "+dest_type.id_string());
3504 }
3505}
3506
3509{
3510 PRECONDITION(expr.type().id() == ID_floatbv);
3511
3512 if(use_FPA_theory)
3513 {
3514 out << "(fp.roundToIntegral ";
3516 out << ' ';
3517 convert_expr(expr.op());
3518 out << ")";
3519 }
3520 else
3521 UNEXPECTEDCASE("TODO floatbv_round_to_integral without FPA");
3522}
3523
3525{
3526 const struct_typet &struct_type =
3527 expr.type().id() == ID_struct_tag
3528 ? ns.follow_tag(to_struct_tag_type(expr.type()))
3529 : to_struct_type(expr.type());
3530
3531 const struct_typet::componentst &components=
3532 struct_type.components();
3533
3535 components.size() == expr.operands().size(),
3536 "number of struct components as indicated by the struct type shall be equal"
3537 "to the number of operands of the struct expression");
3538
3539 DATA_INVARIANT(!components.empty(), "struct shall have struct components");
3540
3541 if(use_datatypes)
3542 {
3543 const std::string &smt_typename = datatype_map.at(struct_type);
3544
3545 // use the constructor for the Z3 datatype
3546 out << "(mk-" << smt_typename;
3547
3548 std::size_t i=0;
3549 for(struct_typet::componentst::const_iterator
3550 it=components.begin();
3551 it!=components.end();
3552 it++, i++)
3553 {
3554 if(is_zero_width(it->type(), ns))
3555 continue;
3556 out << " ";
3557 convert_expr(expr.operands()[i]);
3558 }
3559
3560 out << ")";
3561 }
3562 else
3563 {
3564 auto convert_operand = [this](const exprt &op) {
3565 // may need to flatten array-theory arrays in there
3566 if(op.type().id() == ID_array && use_array_theory(op))
3567 flatten_array(op);
3568 else if(op.type().id() == ID_bool)
3569 flatten2bv(op);
3570 else
3571 convert_expr(op);
3572 };
3573
3574 // SMT-LIB 2 concat is binary only
3575 std::size_t n_concat = 0;
3576 for(std::size_t i = components.size(); i > 1; i--)
3577 {
3578 if(is_zero_width(components[i - 1].type(), ns))
3579 continue;
3580 else if(i > 2 || !is_zero_width(components[0].type(), ns))
3581 {
3582 ++n_concat;
3583 out << "(concat ";
3584 }
3585
3586 convert_operand(expr.operands()[i - 1]);
3587
3588 out << " ";
3589 }
3590
3591 if(!is_zero_width(components[0].type(), ns))
3592 convert_operand(expr.op0());
3593
3594 out << std::string(n_concat, ')');
3595 }
3596}
3597
3600{
3601 const array_typet &array_type = to_array_type(expr.type());
3602 const auto &size_expr = array_type.size();
3603 PRECONDITION(size_expr.is_constant());
3604
3606 CHECK_RETURN_WITH_DIAGNOSTICS(size != 0, "can't convert zero-sized array");
3607
3608 out << "(let ((?far ";
3609 convert_expr(expr);
3610 out << ")) ";
3611
3612 for(mp_integer i=size; i!=0; --i)
3613 {
3614 if(i!=1)
3615 out << "(concat ";
3616 out << "(select ?far ";
3617 convert_expr(from_integer(i - 1, array_type.index_type()));
3618 out << ")";
3619 if(i!=1)
3620 out << " ";
3621 }
3622
3623 // close the many parentheses
3624 for(mp_integer i=size; i>1; --i)
3625 out << ")";
3626
3627 out << ")"; // let
3628}
3629
3631{
3632 const exprt &op=expr.op();
3633
3634 std::size_t total_width = boolbv_width(expr.type());
3635
3636 std::size_t member_width=boolbv_width(op.type());
3637
3638 if(total_width==member_width)
3639 {
3640 flatten2bv(op);
3641 }
3642 else
3643 {
3644 // we will pad with zeros, but non-det would be better
3645 INVARIANT(
3646 total_width > member_width,
3647 "total_width should be greater than member_width as member_width can be"
3648 "at most as large as total_width and the other case has been handled "
3649 "above");
3650 out << "(concat ";
3651 out << "(_ bv0 "
3652 << (total_width-member_width) << ") ";
3653 flatten2bv(op);
3654 out << ")";
3655 }
3656}
3657
3659{
3660 const typet &expr_type=expr.type();
3661
3662 if(expr_type.id()==ID_unsignedbv ||
3663 expr_type.id()==ID_signedbv ||
3664 expr_type.id()==ID_bv ||
3665 expr_type.id()==ID_c_enum ||
3666 expr_type.id()==ID_c_enum_tag ||
3667 expr_type.id()==ID_c_bool ||
3669 {
3670 const std::size_t width = boolbv_width(expr_type);
3671
3672 const mp_integer value = bvrep2integer(expr.get_value(), width, false);
3673
3674 out << "(_ bv" << value
3675 << " " << width << ")";
3676 }
3677 else if(expr_type.id()==ID_fixedbv)
3678 {
3680
3681 const mp_integer v = bvrep2integer(expr.get_value(), spec.width, false);
3682
3683 out << "(_ bv" << v << " " << spec.width << ")";
3684 }
3685 else if(expr_type.id()==ID_floatbv)
3686 {
3689
3690 if(use_FPA_theory)
3691 {
3692 /* CBMC stores floating point literals in the most
3693 computationally useful form; biased exponents and
3694 significands including the hidden bit. Thus some encoding
3695 is needed to get to IEEE-754 style representations. */
3696
3698 size_t e=floatbv_type.get_e();
3699 size_t f=floatbv_type.get_f()+1;
3700
3701 /* Should be sufficient, but not currently supported by mathsat */
3702 #if 0
3703 mp_integer binary = v.pack();
3704
3705 out << "((_ to_fp " << e << " " << f << ")"
3706 << " #b" << integer2binary(v.pack(), v.spec.width()) << ")";
3707 #endif
3708
3709 if(v.is_NaN())
3710 {
3711 out << "(_ NaN " << e << " " << f << ")";
3712 }
3713 else if(v.is_infinity())
3714 {
3715 if(v.get_sign())
3716 out << "(_ -oo " << e << " " << f << ")";
3717 else
3718 out << "(_ +oo " << e << " " << f << ")";
3719 }
3720 else
3721 {
3722 // Zero, normal or subnormal
3723
3724 mp_integer binary = v.pack();
3725 std::string binaryString(integer2binary(v.pack(), v.spec.width()));
3726
3727 out << "(fp "
3728 << "#b" << binaryString.substr(0, 1) << " "
3729 << "#b" << binaryString.substr(1, e) << " "
3730 << "#b" << binaryString.substr(1+e, f-1) << ")";
3731 }
3732 }
3733 else
3734 {
3735 // produce corresponding bit-vector
3736 const ieee_float_spect spec(floatbv_type);
3737 const mp_integer v = bvrep2integer(expr.get_value(), spec.width(), false);
3738 out << "(_ bv" << v << " " << spec.width() << ")";
3739 }
3740 }
3741 else if(expr_type.id()==ID_pointer)
3742 {
3743 if(expr.is_null_pointer())
3744 {
3745 out << "(_ bv0 " << boolbv_width(expr_type)
3746 << ")";
3747 }
3748 else
3749 {
3750 // just treat the pointer as a bit vector
3751 const std::size_t width = boolbv_width(expr_type);
3752
3753 const mp_integer value = bvrep2integer(expr.get_value(), width, false);
3754
3755 out << "(_ bv" << value << " " << width << ")";
3756 }
3757 }
3758 else if(expr_type.id()==ID_bool)
3759 {
3760 if(expr == true)
3761 out << "true";
3762 else if(expr == false)
3763 out << "false";
3764 else
3765 UNEXPECTEDCASE("unknown Boolean constant");
3766 }
3767 else if(expr_type.id()==ID_array)
3768 {
3769 defined_expressionst::const_iterator it=defined_expressions.find(expr);
3770 CHECK_RETURN(it != defined_expressions.end());
3771 out << it->second;
3772 }
3773 else if(expr_type.id()==ID_rational)
3774 {
3775 std::string value=id2string(expr.get_value());
3776 const bool negative = has_prefix(value, "-");
3777
3778 if(negative)
3779 {
3780 out << "(- ";
3781 value = value.substr(1);
3782 }
3783
3784 size_t pos=value.find("/");
3785
3786 if(pos==std::string::npos)
3787 out << value << ".0";
3788 else
3789 {
3790 out << "(/ " << value.substr(0, pos) << ".0 "
3791 << value.substr(pos+1) << ".0)";
3792 }
3793
3794 if(negative)
3795 out << ')';
3796 }
3797 else if(expr_type.id() == ID_real)
3798 {
3799 const std::string &value = id2string(expr.get_value());
3800 out << value;
3801 if(value.find('.') == std::string::npos)
3802 out << ".0";
3803 }
3804 else if(expr_type.id()==ID_integer)
3805 {
3806 const auto value = id2string(expr.get_value());
3807
3808 // SMT2 has no negative integer literals
3809 if(has_prefix(value, "-"))
3810 out << "(- " << value.substr(1, std::string::npos) << ')';
3811 else
3812 out << value;
3813 }
3814 else if(expr_type.id() == ID_natural)
3815 {
3816 out << expr.get_value();
3817 }
3818 else if(expr_type.id() == ID_range)
3819 {
3821 const auto width = address_bits(range_type.size());
3822 const auto value_int = numeric_cast_v<mp_integer>(expr);
3823 out << "(_ bv" << (value_int - range_type.from()) << " " << width << ")";
3824 }
3825 else
3826 UNEXPECTEDCASE("unknown constant: "+expr_type.id_string());
3827}
3828
3830{
3831 if(expr.type().id() == ID_integer)
3832 {
3833 out << "(mod ";
3834 convert_expr(expr.op0());
3835 out << ' ';
3836 convert_expr(expr.op1());
3837 out << ')';
3838 }
3839 else
3841 "unsupported type for euclidean_mod: " + expr.type().id_string());
3842}
3843
3845{
3846 if(expr.type().id()==ID_unsignedbv ||
3847 expr.type().id()==ID_signedbv)
3848 {
3849 if(expr.type().id()==ID_unsignedbv)
3850 out << "(bvurem ";
3851 else
3852 out << "(bvsrem ";
3853
3854 convert_expr(expr.op0());
3855 out << " ";
3856 convert_expr(expr.op1());
3857 out << ")";
3858 }
3859 else
3860 UNEXPECTEDCASE("unsupported type for mod: "+expr.type().id_string());
3861}
3862
3864{
3865 std::vector<mp_integer> dynamic_objects;
3867
3868 if(dynamic_objects.empty())
3869 out << "false";
3870 else
3871 {
3872 std::size_t pointer_width = boolbv_width(expr.op().type());
3873
3874 out << "(let ((?obj ((_ extract "
3875 << pointer_width-1 << " "
3876 << pointer_width-config.bv_encoding.object_bits << ") ";
3877 convert_expr(expr.op());
3878 out << "))) ";
3879
3880 if(dynamic_objects.size()==1)
3881 {
3882 out << "(= (_ bv" << dynamic_objects.front()
3883 << " " << config.bv_encoding.object_bits << ") ?obj)";
3884 }
3885 else
3886 {
3887 out << "(or";
3888
3889 for(const auto &object : dynamic_objects)
3890 out << " (= (_ bv" << object
3891 << " " << config.bv_encoding.object_bits << ") ?obj)";
3892
3893 out << ")"; // or
3894 }
3895
3896 out << ")"; // let
3897 }
3898}
3899
3901{
3902 const typet &op_type=expr.op0().type();
3903
3904 if(
3905 op_type.id() == ID_unsignedbv || op_type.id() == ID_bv ||
3906 op_type.id() == ID_range)
3907 {
3908 // The range type is encoded in binary
3909 out << "(";
3910 if(expr.id()==ID_le)
3911 out << "bvule";
3912 else if(expr.id()==ID_lt)
3913 out << "bvult";
3914 else if(expr.id()==ID_ge)
3915 out << "bvuge";
3916 else if(expr.id()==ID_gt)
3917 out << "bvugt";
3918
3919 out << " ";
3920 convert_expr(expr.op0());
3921 out << " ";
3922 convert_expr(expr.op1());
3923 out << ")";
3924 }
3925 else if(op_type.id()==ID_signedbv ||
3926 op_type.id()==ID_fixedbv)
3927 {
3928 out << "(";
3929 if(expr.id()==ID_le)
3930 out << "bvsle";
3931 else if(expr.id()==ID_lt)
3932 out << "bvslt";
3933 else if(expr.id()==ID_ge)
3934 out << "bvsge";
3935 else if(expr.id()==ID_gt)
3936 out << "bvsgt";
3937
3938 out << " ";
3939 convert_expr(expr.op0());
3940 out << " ";
3941 convert_expr(expr.op1());
3942 out << ")";
3943 }
3944 else if(op_type.id()==ID_floatbv)
3945 {
3946 if(use_FPA_theory)
3947 {
3948 out << "(";
3949 if(expr.id()==ID_le)
3950 out << "fp.leq";
3951 else if(expr.id()==ID_lt)
3952 out << "fp.lt";
3953 else if(expr.id()==ID_ge)
3954 out << "fp.geq";
3955 else if(expr.id()==ID_gt)
3956 out << "fp.gt";
3957
3958 out << " ";
3959 convert_expr(expr.op0());
3960 out << " ";
3961 convert_expr(expr.op1());
3962 out << ")";
3963 }
3964 else
3965 convert_floatbv(expr);
3966 }
3967 else if(
3968 op_type.id() == ID_rational || op_type.id() == ID_integer ||
3969 op_type.id() == ID_natural || op_type.id() == ID_real)
3970 {
3971 out << "(";
3972 out << expr.id();
3973
3974 out << " ";
3975 convert_expr(expr.op0());
3976 out << " ";
3977 convert_expr(expr.op1());
3978 out << ")";
3979 }
3980 else if(op_type.id() == ID_pointer)
3981 {
3982 const exprt same_object = ::same_object(expr.op0(), expr.op1());
3983
3984 out << "(and ";
3986
3987 out << " (";
3988 if(expr.id() == ID_le)
3989 out << "bvsle";
3990 else if(expr.id() == ID_lt)
3991 out << "bvslt";
3992 else if(expr.id() == ID_ge)
3993 out << "bvsge";
3994 else if(expr.id() == ID_gt)
3995 out << "bvsgt";
3996
3997 out << ' ';
3999 out << ' ';
4001 out << ')';
4002
4003 out << ')';
4004 }
4005 else
4007 "unsupported type for "+expr.id_string()+": "+op_type.id_string());
4008}
4009
4011{
4012 if(
4013 expr.type().id() == ID_rational || expr.type().id() == ID_integer ||
4014 expr.type().id() == ID_natural || expr.type().id() == ID_real)
4015 {
4016 // these are multi-ary in SMT-LIB2
4017 out << "(+";
4018
4019 for(const auto &op : expr.operands())
4020 {
4021 out << ' ';
4022 convert_expr(op);
4023 }
4024
4025 out << ')';
4026 }
4027 else if(
4028 expr.type().id() == ID_unsignedbv || expr.type().id() == ID_signedbv ||
4029 expr.type().id() == ID_fixedbv)
4030 {
4031 // These could be chained, i.e., need not be binary,
4032 // but at least MathSat doesn't like that.
4033 if(expr.operands().size() == 2)
4034 {
4035 out << "(bvadd ";
4036 convert_expr(expr.op0());
4037 out << " ";
4038 convert_expr(expr.op1());
4039 out << ")";
4040 }
4041 else
4042 {
4044 }
4045 }
4046 else if(expr.type().id() == ID_range)
4047 {
4048 auto &range_type = to_integer_range_type(expr.type());
4049
4050 // These could be chained, i.e., need not be binary,
4051 // but at least MathSat doesn't like that.
4052 if(expr.operands().size() == 2)
4053 {
4054 // add: lhs + from + rhs + from - from = lhs + rhs + from
4055 const auto width = address_bits(range_type.size());
4056
4057 out << "(bvadd ";
4058 convert_expr(expr.op0());
4059 out << " (bvadd ";
4060 convert_expr(expr.op1());
4061 out << " (_ bv" << range_type.from() << ' ' << width
4062 << ")))"; // bv, bvadd, bvadd
4063 }
4064 else
4065 {
4067 }
4068 }
4069 else if(expr.type().id() == ID_floatbv)
4070 {
4071 // Floating-point additions should have be been converted
4072 // to ID_floatbv_plus during symbolic execution, adding
4073 // the rounding mode. See smt2_convt::convert_floatbv_plus.
4075 }
4076 else if(expr.type().id() == ID_pointer)
4077 {
4078 if(expr.operands().size() == 2)
4079 {
4080 exprt p = expr.op0(), i = expr.op1();
4081
4082 if(p.type().id() != ID_pointer)
4083 p.swap(i);
4084
4086 p.type().id() == ID_pointer,
4087 "one of the operands should have pointer type");
4088
4089 const auto &base_type = to_pointer_type(expr.type()).base_type();
4091 base_type.id() != ID_empty, "no pointer arithmetic over void pointers");
4092
4093 auto element_size_opt = pointer_offset_size(base_type, ns);
4094 CHECK_RETURN(element_size_opt.has_value() && *element_size_opt >= 0);
4096
4097 // First convert the pointer operand
4098 out << "(let ((?pointerop ";
4099 convert_expr(p);
4100 out << ")) ";
4101
4102 // The addition is done on the offset part only.
4103 const std::size_t pointer_width = boolbv_width(p.type());
4104 const std::size_t offset_bits =
4105 pointer_width - config.bv_encoding.object_bits;
4106
4107 out << "(concat ";
4108 out << "((_ extract " << pointer_width - 1 << ' ' << offset_bits
4109 << ") ?pointerop) ";
4110 out << "(bvadd ((_ extract " << offset_bits - 1 << " 0) ?pointerop) ";
4111
4112 if(element_size >= 2)
4113 {
4114 out << "(bvmul ((_ extract " << offset_bits - 1 << " 0) ";
4115 convert_expr(i);
4116 out << ") (_ bv" << element_size << " " << offset_bits << "))";
4117 }
4118 else
4119 {
4120 out << "((_ extract " << offset_bits - 1 << " 0) ";
4121 convert_expr(i);
4122 out << ')'; // extract
4123 }
4124
4125 out << ")))"; // bvadd, concat, let
4126 }
4127 else
4128 {
4130 }
4131 }
4132 else
4133 UNEXPECTEDCASE("unsupported type for +: " + expr.type().id_string());
4134}
4135
4140{
4142
4143 /* CProver uses the x86 numbering of the rounding-mode
4144 * 0 == FE_TONEAREST
4145 * 1 == FE_DOWNWARD
4146 * 2 == FE_UPWARD
4147 * 3 == FE_TOWARDZERO
4148 * These literal values must be used rather than the macros
4149 * the macros from fenv.h to avoid portability problems.
4150 */
4151
4152 if(expr.is_constant())
4153 {
4155
4157
4158 if(value==0)
4159 out << "roundNearestTiesToEven";
4160 else if(value==1)
4161 out << "roundTowardNegative";
4162 else if(value==2)
4163 out << "roundTowardPositive";
4164 else if(value==3)
4165 out << "roundTowardZero";
4166 else if(value == 4)
4167 out << "roundNearestTiesToAway";
4168 else
4170 false,
4171 "Rounding mode should have value 0, 1, 2, 3, or 4",
4172 id2string(cexpr.get_value()));
4173 }
4174 else
4175 {
4176 std::size_t width=to_bitvector_type(expr.type()).get_width();
4177
4178 // Need to make the choice above part of the model
4179 out << "(ite (= (_ bv0 " << width << ") ";
4180 convert_expr(expr);
4181 out << ") roundNearestTiesToEven ";
4182
4183 out << "(ite (= (_ bv1 " << width << ") ";
4184 convert_expr(expr);
4185 out << ") roundTowardNegative ";
4186
4187 out << "(ite (= (_ bv2 " << width << ") ";
4188 convert_expr(expr);
4189 out << ") roundTowardPositive ";
4190
4191 out << "(ite (= (_ bv3 " << width << ") ";
4192 convert_expr(expr);
4193 out << ") roundTowardZero ";
4194
4195 // TODO: add some kind of error checking here
4196 out << "roundNearestTiesToAway";
4197
4198 out << "))))";
4199 }
4200}
4201
4203{
4204 const typet &type=expr.type();
4205
4207 type.id() == ID_floatbv ||
4208 (type.id() == ID_complex &&
4209 to_complex_type(type).subtype().id() == ID_floatbv));
4210
4211 if(use_FPA_theory)
4212 {
4213 if(type.id()==ID_floatbv)
4214 {
4215 out << "(fp.add ";
4217 out << " ";
4218 convert_expr(expr.lhs());
4219 out << " ";
4220 convert_expr(expr.rhs());
4221 out << ")";
4222 }
4223 else if(type.id()==ID_complex)
4224 {
4225 SMT2_TODO("+ for floatbv complex");
4226 }
4227 else
4229 false,
4230 "type should not be one of the unsupported types",
4231 type.id_string());
4232 }
4233 else
4234 convert_floatbv(expr);
4235}
4236
4238{
4239 if(
4240 expr.type().id() == ID_integer || expr.type().id() == ID_natural ||
4241 expr.type().id() == ID_rational || expr.type().id() == ID_real)
4242 {
4243 out << "(- ";
4244 convert_expr(expr.op0());
4245 out << " ";
4246 convert_expr(expr.op1());
4247 out << ")";
4248 }
4249 else if(expr.type().id()==ID_unsignedbv ||
4250 expr.type().id()==ID_signedbv ||
4251 expr.type().id()==ID_fixedbv)
4252 {
4253 if(expr.op0().type().id()==ID_pointer &&
4254 expr.op1().type().id()==ID_pointer)
4255 {
4256 // Pointer difference
4257 const auto &base_type = to_pointer_type(expr.op0().type()).base_type();
4259 base_type.id() != ID_empty, "no pointer arithmetic over void pointers");
4260 auto element_size_opt = pointer_offset_size(base_type, ns);
4261 CHECK_RETURN(element_size_opt.has_value() && *element_size_opt >= 1);
4263
4264 if(element_size >= 2)
4265 out << "(bvsdiv ";
4266
4267 INVARIANT(
4268 boolbv_width(expr.op0().type()) == boolbv_width(expr.type()),
4269 "bitvector width of operand shall be equal to the bitvector width of "
4270 "the expression");
4271
4272 out << "(bvsub ";
4273 convert_expr(expr.op0());
4274 out << " ";
4275 convert_expr(expr.op1());
4276 out << ")";
4277
4278 if(element_size >= 2)
4279 out << " (_ bv" << element_size << " " << boolbv_width(expr.type())
4280 << "))";
4281 }
4282 else
4283 {
4284 out << "(bvsub ";
4285 convert_expr(expr.op0());
4286 out << " ";
4287 convert_expr(expr.op1());
4288 out << ")";
4289 }
4290 }
4291 else if(expr.type().id()==ID_floatbv)
4292 {
4293 // Floating-point subtraction should have be been converted
4294 // to ID_floatbv_minus during symbolic execution, adding
4295 // the rounding mode. See smt2_convt::convert_floatbv_minus.
4297 }
4298 else if(expr.type().id()==ID_pointer)
4299 {
4300 if(
4301 expr.op0().type().id() == ID_pointer &&
4302 (expr.op1().type().id() == ID_unsignedbv ||
4303 expr.op1().type().id() == ID_signedbv))
4304 {
4305 // rewrite p-o to p+(-o)
4306 return convert_plus(
4307 plus_exprt(expr.op0(), unary_minus_exprt(expr.op1())));
4308 }
4309 else
4311 "unsupported operand types for -: " + expr.op0().type().id_string() +
4312 " and " + expr.op1().type().id_string());
4313 }
4314 else if(expr.type().id() == ID_range)
4315 {
4316 auto &range_type = to_integer_range_type(expr.type());
4317
4318 // sub: lhs + from - (rhs + from) - from = lhs - rhs - from
4319 const auto width = address_bits(range_type.size());
4320
4321 out << "(bvsub (bvsub ";
4322 convert_expr(expr.op0());
4323 out << ' ';
4324 convert_expr(expr.op1());
4325 out << ") (_ bv" << range_type.from() << ' ' << width << "))"; // bv, bvsub
4326 }
4327 else
4328 UNEXPECTEDCASE("unsupported type for -: "+expr.type().id_string());
4329}
4330
4332{
4334 expr.type().id() == ID_floatbv,
4335 "type of ieee floating point expression shall be floatbv");
4336
4337 if(use_FPA_theory)
4338 {
4339 out << "(fp.sub ";
4341 out << " ";
4342 convert_expr(expr.lhs());
4343 out << " ";
4344 convert_expr(expr.rhs());
4345 out << ")";
4346 }
4347 else
4348 convert_floatbv(expr);
4349}
4350
4352{
4353 if(expr.type().id()==ID_unsignedbv ||
4354 expr.type().id()==ID_signedbv)
4355 {
4356 if(expr.type().id()==ID_unsignedbv)
4357 out << "(bvudiv ";
4358 else
4359 out << "(bvsdiv ";
4360
4361 convert_expr(expr.op0());
4362 out << " ";
4363 convert_expr(expr.op1());
4364 out << ")";
4365 }
4366 else if(expr.type().id()==ID_fixedbv)
4367 {
4368 fixedbv_spect spec(to_fixedbv_type(expr.type()));
4369 std::size_t fraction_bits=spec.get_fraction_bits();
4370
4371 out << "((_ extract " << spec.width-1 << " 0) ";
4372 out << "(bvsdiv ";
4373
4374 out << "(concat ";
4375 convert_expr(expr.op0());
4376 out << " (_ bv0 " << fraction_bits << ")) ";
4377
4378 out << "((_ sign_extend " << fraction_bits << ") ";
4379 convert_expr(expr.op1());
4380 out << ")";
4381
4382 out << "))";
4383 }
4384 else if(expr.type().id()==ID_floatbv)
4385 {
4386 // Floating-point division should have be been converted
4387 // to ID_floatbv_div during symbolic execution, adding
4388 // the rounding mode. See smt2_convt::convert_floatbv_div.
4390 }
4391 else if(
4392 expr.type().id() == ID_rational || expr.type().id() == ID_integer ||
4393 expr.type().id() == ID_natural || expr.type().id() == ID_real)
4394 {
4395 out << "(/ ";
4396 convert_expr(expr.op0());
4397 out << " ";
4398 convert_expr(expr.op1());
4399 out << ")";
4400 }
4401 else
4402 UNEXPECTEDCASE("unsupported type for /: "+expr.type().id_string());
4403}
4404
4406{
4408 expr.type().id() == ID_floatbv,
4409 "type of ieee floating point expression shall be floatbv");
4410
4411 if(use_FPA_theory)
4412 {
4413 out << "(fp.div ";
4415 out << " ";
4416 convert_expr(expr.lhs());
4417 out << " ";
4418 convert_expr(expr.rhs());
4419 out << ")";
4420 }
4421 else
4422 convert_floatbv(expr);
4423}
4424
4426{
4427 // re-write to binary if needed
4428 if(expr.operands().size()>2)
4429 {
4430 // strip last operand
4431 exprt tmp=expr;
4432 tmp.operands().pop_back();
4433
4434 // recursive call
4435 return convert_mult(mult_exprt(tmp, expr.operands().back()));
4436 }
4437
4438 INVARIANT(
4439 expr.operands().size() == 2,
4440 "expression should have been converted to a variant with two operands");
4441
4442 if(expr.type().id()==ID_unsignedbv ||
4443 expr.type().id()==ID_signedbv)
4444 {
4445 // Note that bvmul is really unsigned,
4446 // but this is irrelevant as we chop-off any extra result
4447 // bits.
4448 out << "(bvmul ";
4449 convert_expr(expr.op0());
4450 out << " ";
4451 convert_expr(expr.op1());
4452 out << ")";
4453 }
4454 else if(expr.type().id()==ID_floatbv)
4455 {
4456 // Floating-point multiplication should have be been converted
4457 // to ID_floatbv_mult during symbolic execution, adding
4458 // the rounding mode. See smt2_convt::convert_floatbv_mult.
4460 }
4461 else if(expr.type().id()==ID_fixedbv)
4462 {
4463 fixedbv_spect spec(to_fixedbv_type(expr.type()));
4464 std::size_t fraction_bits=spec.get_fraction_bits();
4465
4466 out << "((_ extract "
4467 << spec.width+fraction_bits-1 << " "
4468 << fraction_bits << ") ";
4469
4470 out << "(bvmul ";
4471
4472 out << "((_ sign_extend " << fraction_bits << ") ";
4473 convert_expr(expr.op0());
4474 out << ") ";
4475
4476 out << "((_ sign_extend " << fraction_bits << ") ";
4477 convert_expr(expr.op1());
4478 out << ")";
4479
4480 out << "))"; // bvmul, extract
4481 }
4482 else if(
4483 expr.type().id() == ID_rational || expr.type().id() == ID_integer ||
4484 expr.type().id() == ID_natural || expr.type().id() == ID_real)
4485 {
4486 out << "(*";
4487
4488 for(const auto &op : expr.operands())
4489 {
4490 out << " ";
4491 convert_expr(op);
4492 }
4493
4494 out << ")";
4495 }
4496 else
4497 UNEXPECTEDCASE("unsupported type for *: "+expr.type().id_string());
4498}
4499
4501{
4503 expr.type().id() == ID_floatbv,
4504 "type of ieee floating point expression shall be floatbv");
4505
4506 if(use_FPA_theory)
4507 {
4508 out << "(fp.mul ";
4510 out << " ";
4511 convert_expr(expr.lhs());
4512 out << " ";
4513 convert_expr(expr.rhs());
4514 out << ")";
4515 }
4516 else
4517 convert_floatbv(expr);
4518}
4519
4521{
4523 expr.type().id() == ID_floatbv,
4524 "type of ieee floating point expression shall be floatbv");
4525
4526 if(use_FPA_theory)
4527 {
4528 // Note that these do not have a rounding mode
4529 out << "(fp.rem ";
4530 convert_expr(expr.lhs());
4531 out << " ";
4532 convert_expr(expr.rhs());
4533 out << ")";
4534 }
4535 else
4536 {
4537 SMT2_TODO(
4538 "smt2_convt::convert_floatbv_rem to be implemented when not using "
4539 "FPA_theory");
4540 }
4541}
4542
4544{
4546 expr.type().id() == ID_floatbv,
4547 "type of ieee floating point expression shall be floatbv");
4548
4549 if(use_FPA_theory)
4550 {
4551 out << "(fp.fma ";
4553 out << " ";
4555 out << " ";
4557 out << " ";
4558 convert_expr(expr.op_add());
4559 out << ")";
4560 }
4561 else
4562 convert_floatbv(expr);
4563}
4564
4566{
4567 INVARIANT(
4568 expr.operands().size() == 3,
4569 "with expression should have exactly three operands");
4570
4571 const typet &expr_type = expr.type();
4572
4573 if(expr_type.id()==ID_array)
4574 {
4576
4577 if(use_array_theory(expr))
4578 {
4579 out << "(store ";
4580 convert_expr(expr.old());
4581 out << " ";
4582 convert_expr(typecast_exprt(expr.where(), array_type.index_type()));
4583 out << " ";
4584 convert_expr(expr.new_value());
4585 out << ")";
4586 }
4587 else
4588 {
4589 // fixed-width
4590 std::size_t array_width=boolbv_width(array_type);
4591 std::size_t sub_width = boolbv_width(array_type.element_type());
4592 std::size_t index_width=boolbv_width(expr.where().type());
4593
4594 // We mask out the updated bits with AND,
4595 // and then OR-in the shifted new value.
4596
4597 out << "(let ((distance? ";
4598 out << "(bvmul (_ bv" << sub_width << " " << array_width << ") ";
4599
4600 // SMT2 says that the shift distance needs to be as wide
4601 // as the stuff we are shifting.
4603 {
4604 out << "((_ zero_extend " << array_width-index_width << ") ";
4605 convert_expr(expr.where());
4606 out << ")";
4607 }
4608 else
4609 {
4610 out << "((_ extract " << array_width-1 << " 0) ";
4611 convert_expr(expr.where());
4612 out << ")";
4613 }
4614
4615 out << "))) "; // bvmul, distance?
4616
4617 out << "(bvor ";
4618 out << "(bvand ";
4619 out << "(bvnot ";
4620 out << "(bvshl (_ bv" << power(2, sub_width) - 1 << " " << array_width
4621 << ") ";
4622 out << "distance?)) "; // bvnot, bvlshl
4623 convert_expr(expr.old());
4624 out << ") "; // bvand
4625 out << "(bvshl ";
4626 out << "((_ zero_extend " << array_width-sub_width << ") ";
4627 convert_expr(expr.new_value());
4628 out << ") distance?)))"; // zero_extend, bvshl, bvor, let
4629 }
4630 }
4631 else if(expr_type.id() == ID_struct || expr_type.id() == ID_struct_tag)
4632 {
4633 const struct_typet &struct_type =
4634 expr_type.id() == ID_struct_tag
4635 ? ns.follow_tag(to_struct_tag_type(expr_type))
4637
4638 const exprt &index = expr.where();
4639 const exprt &value = expr.new_value();
4640
4641 const irep_idt &component_name=index.get(ID_component_name);
4642
4643 INVARIANT(
4644 struct_type.has_component(component_name),
4645 "struct should have accessed component");
4646
4647 if(use_datatypes)
4648 {
4649 const std::string &smt_typename = datatype_map.at(expr_type);
4650
4651 out << "(update-" << smt_typename << "." << component_name << " ";
4652 convert_expr(expr.old());
4653 out << " ";
4654 convert_expr(value);
4655 out << ")";
4656 }
4657 else
4658 {
4659 auto convert_operand = [this](const exprt &op)
4660 {
4661 // may need to flatten array-theory arrays in there
4662 if(op.type().id() == ID_array && use_array_theory(op))
4663 flatten_array(op);
4664 else if(op.type().id() == ID_bool)
4665 flatten2bv(op);
4666 else
4667 convert_expr(op);
4668 };
4669
4671
4672 // figure out the offset and width of the member
4673 const boolbv_widtht::membert &m =
4674 boolbv_width.get_member(struct_type, component_name);
4675
4676 if(m.width==struct_width)
4677 {
4678 // the struct is the same as the member, no concat needed
4679 convert_operand(value);
4680 }
4681 else
4682 {
4683 out << "(let ((?withop ";
4684 convert_operand(expr.old());
4685 out << ")) ";
4686
4687 if(m.offset == 0)
4688 {
4689 // the member is at the beginning
4690 out << "(concat "
4691 << "((_ extract " << (struct_width - 1) << " " << m.width
4692 << ") ?withop) ";
4693 convert_operand(value);
4694 out << ")"; // concat
4695 }
4696 else if(m.offset + m.width == struct_width)
4697 {
4698 // the member is at the end
4699 out << "(concat ";
4700 convert_operand(value);
4701 out << " ((_ extract " << (m.offset - 1) << " 0) ?withop))";
4702 }
4703 else
4704 {
4705 // most general case, need two concat-s
4706 out << "(concat (concat "
4707 << "((_ extract " << (struct_width - 1) << " "
4708 << (m.offset + m.width) << ") ?withop) ";
4709 convert_operand(value);
4710 out << ") ((_ extract " << (m.offset - 1) << " 0) ?withop)";
4711 out << ")"; // concat
4712 }
4713
4714 out << ")"; // let ?withop
4715 }
4716 }
4717 }
4718 else if(expr_type.id() == ID_union || expr_type.id() == ID_union_tag)
4719 {
4720 const exprt &value = expr.new_value();
4721
4722 std::size_t total_width = boolbv_width(expr_type);
4723
4724 std::size_t member_width=boolbv_width(value.type());
4725
4726 if(total_width==member_width)
4727 {
4728 flatten2bv(value);
4729 }
4730 else
4731 {
4732 INVARIANT(
4733 total_width > member_width,
4734 "total width should be greater than member_width as member_width is at "
4735 "most as large as total_width and the other case has been handled "
4736 "above");
4737 out << "(concat ";
4738 out << "((_ extract "
4739 << (total_width-1)
4740 << " " << member_width << ") ";
4741 convert_expr(expr.old());
4742 out << ") ";
4743 flatten2bv(value);
4744 out << ")";
4745 }
4746 }
4747 else if(expr_type.id()==ID_bv ||
4748 expr_type.id()==ID_unsignedbv ||
4749 expr_type.id()==ID_signedbv)
4750 {
4751 if(expr.new_value().type().id() == ID_bool)
4752 {
4754 update_bit_exprt(expr.old(), expr.where(), expr.new_value()));
4755 }
4756 else
4757 {
4759 update_bits_exprt(expr.old(), expr.where(), expr.new_value()));
4760 }
4761 }
4762 else
4764 "with expects struct, union, or array type, but got "+
4765 expr.type().id_string());
4766}
4767
4769{
4770 PRECONDITION(expr.operands().size() == 3);
4771
4772 SMT2_TODO("smt2_convt::convert_update to be implemented");
4773}
4774
4776{
4777 return convert_expr(expr.lower());
4778}
4779
4781{
4782 return convert_expr(expr.lower());
4783}
4784
4786{
4787 const typet &array_op_type = expr.array().type();
4788
4789 if(array_op_type.id()==ID_array)
4790 {
4792
4793 if(use_array_theory(expr.array()))
4794 {
4795 if(expr.is_boolean() && !use_array_of_bool)
4796 {
4797 out << "(= ";
4798 out << "(select ";
4799 convert_expr(expr.array());
4800 out << " ";
4801 convert_expr(typecast_exprt(expr.index(), array_type.index_type()));
4802 out << ")";
4803 out << " #b1)";
4804 }
4805 else
4806 {
4807 out << "(select ";
4808 convert_expr(expr.array());
4809 out << " ";
4810 convert_expr(typecast_exprt(expr.index(), array_type.index_type()));
4811 out << ")";
4812 }
4813 }
4814 else
4815 {
4816 // fixed size
4817 std::size_t array_width=boolbv_width(array_type);
4818
4819 unflatten(wheret::BEGIN, array_type.element_type());
4820
4821 std::size_t sub_width = boolbv_width(array_type.element_type());
4822 std::size_t index_width=boolbv_width(expr.index().type());
4823
4824 out << "((_ extract " << sub_width-1 << " 0) ";
4825 out << "(bvlshr ";
4826 convert_expr(expr.array());
4827 out << " ";
4828 out << "(bvmul (_ bv" << sub_width << " " << array_width << ") ";
4829
4830 // SMT2 says that the shift distance must be the same as
4831 // the width of what we shift.
4833 {
4834 out << "((_ zero_extend " << array_width-index_width << ") ";
4835 convert_expr(expr.index());
4836 out << ")"; // zero_extend
4837 }
4838 else
4839 {
4840 out << "((_ extract " << array_width-1 << " 0) ";
4841 convert_expr(expr.index());
4842 out << ")"; // extract
4843 }
4844
4845 out << ")))"; // mult, bvlshr, extract
4846
4847 unflatten(wheret::END, array_type.element_type());
4848 }
4849 }
4850 else
4851 INVARIANT(
4852 false, "index with unsupported array type: " + array_op_type.id_string());
4853}
4854
4856{
4858 const exprt &struct_op=member_expr.struct_op();
4859 const typet &struct_op_type = struct_op.type();
4860 const irep_idt &name=member_expr.get_component_name();
4861
4863 {
4864 const struct_typet &struct_type =
4866 ? ns.follow_tag(to_struct_tag_type(struct_op_type))
4868
4869 INVARIANT(
4870 struct_type.has_component(name), "struct should have accessed component");
4871
4872 if(use_datatypes)
4873 {
4874 const std::string &smt_typename = datatype_map.at(struct_type);
4875
4876 out << "(" << smt_typename << "."
4877 << struct_type.get_component(name).get_name()
4878 << " ";
4879 convert_expr(struct_op);
4880 out << ")";
4881 }
4882 else
4883 {
4884 // we extract
4885 const auto &member_offset = boolbv_width.get_member(struct_type, name);
4886
4887 if(expr.type().id() == ID_bool)
4888 out << "(= ";
4889 out << "((_ extract " << (member_offset.offset + member_offset.width - 1)
4890 << " " << member_offset.offset << ") ";
4891 convert_expr(struct_op);
4892 out << ")";
4893 if(expr.type().id() == ID_bool)
4894 out << " #b1)";
4895 }
4896 }
4897 else if(
4899 {
4900 std::size_t width=boolbv_width(expr.type());
4902 width != 0, "failed to get union member width");
4903
4904 if(use_datatypes)
4905 {
4906 unflatten(wheret::BEGIN, expr.type());
4907
4908 out << "((_ extract " << (width - 1) << " 0) ";
4909 convert_expr(struct_op);
4910 out << ")";
4911
4912 unflatten(wheret::END, expr.type());
4913 }
4914 else
4915 {
4916 out << "((_ extract " << (width - 1) << " 0) ";
4917 convert_expr(struct_op);
4918 out << ")";
4919 }
4920 }
4921 else
4923 "convert_member on an unexpected type "+struct_op_type.id_string());
4924}
4925
4927{
4928 const typet &type = expr.type();
4929
4930 if(type.id()==ID_bool)
4931 {
4932 out << "(ite ";
4933 convert_expr(expr); // this returns a Bool
4934 out << " #b1 #b0)"; // this is a one-bit bit-vector
4935 }
4936 else if(type.id()==ID_array)
4937 {
4938 if(use_array_theory(expr))
4939 {
4940 // concatenate elements
4941 const array_typet &array_type = to_array_type(type);
4942
4943 mp_integer size =
4945
4946 // SMT-LIB 2 concat is binary only
4947 std::size_t n_concat = 0;
4948 for(mp_integer i = size; i > 1; --i)
4949 {
4950 ++n_concat;
4951 out << "(concat ";
4952
4953 flatten2bv(
4954 index_exprt{expr, from_integer(i - 1, array_type.index_type())});
4955
4956 out << " ";
4957 }
4958
4959 flatten2bv(index_exprt{expr, from_integer(0, array_type.index_type())});
4960
4961 out << std::string(n_concat, ')'); // concat
4962 }
4963 else
4964 convert_expr(expr);
4965 }
4966 else if(type.id() == ID_struct || type.id() == ID_struct_tag)
4967 {
4968 if(use_datatypes)
4969 {
4970 // concatenate elements
4971 const struct_typet &struct_type =
4972 type.id() == ID_struct_tag ? ns.follow_tag(to_struct_tag_type(type))
4973 : to_struct_type(type);
4974
4975 const struct_typet::componentst &components=
4976 struct_type.components();
4977
4978 // SMT-LIB 2 concat is binary only
4979 std::size_t n_concat = 0;
4980 for(std::size_t i=components.size(); i>1; i--)
4981 {
4982 if(is_zero_width(components[i - 1].type(), ns))
4983 continue;
4984 else if(i > 2 || !is_zero_width(components[0].type(), ns))
4985 {
4986 ++n_concat;
4987 out << "(concat ";
4988 }
4989
4990 flatten2bv(member_exprt{expr, components[i - 1]});
4991
4992 out << " ";
4993 }
4994
4995 if(!is_zero_width(components[0].type(), ns))
4996 {
4997 flatten2bv(member_exprt{expr, components[0]});
4998 }
4999
5000 out << std::string(n_concat, ')'); // concat
5001 }
5002 else
5003 convert_expr(expr);
5004 }
5005 else if(type.id()==ID_floatbv)
5006 {
5007 INVARIANT(
5009 "floatbv expressions should be flattened when using FPA theory");
5010
5011 convert_expr(expr);
5012 }
5013 else
5014 convert_expr(expr);
5015}
5016
5018 wheret where,
5019 const typet &type,
5020 unsigned nesting)
5021{
5022 if(type.id()==ID_bool)
5023 {
5024 if(where==wheret::BEGIN)
5025 out << "(= "; // produces a bool
5026 else
5027 out << " #b1)";
5028 }
5029 else if(type.id() == ID_array)
5030 {
5032
5033 if(where == wheret::BEGIN)
5034 out << "(let ((?ufop" << nesting << " ";
5035 else
5036 {
5037 out << ")) ";
5038
5039 const array_typet &array_type = to_array_type(type);
5040
5041 std::size_t subtype_width = boolbv_width(array_type.element_type());
5042
5044 array_type.size().is_constant(),
5045 "cannot unflatten arrays of non-constant size");
5046 mp_integer size =
5048
5049 for(mp_integer i = 1; i < size; ++i)
5050 out << "(store ";
5051
5052 out << "((as const ";
5054 out << ") ";
5055 // use element at index 0 as default value
5056 unflatten(wheret::BEGIN, array_type.element_type(), nesting + 1);
5057 out << "((_ extract " << subtype_width - 1 << " "
5058 << "0) ?ufop" << nesting << ")";
5059 unflatten(wheret::END, array_type.element_type(), nesting + 1);
5060 out << ") ";
5061
5062 std::size_t offset = subtype_width;
5063 for(mp_integer i = 1; i < size; ++i, offset += subtype_width)
5064 {
5065 convert_expr(from_integer(i, array_type.index_type()));
5066 out << ' ';
5067 unflatten(wheret::BEGIN, array_type.element_type(), nesting + 1);
5068 out << "((_ extract " << offset + subtype_width - 1 << " " << offset
5069 << ") ?ufop" << nesting << ")";
5070 unflatten(wheret::END, array_type.element_type(), nesting + 1);
5071 out << ")"; // store
5072 }
5073
5074 out << ")"; // let
5075 }
5076 }
5077 else if(type.id() == ID_struct || type.id() == ID_struct_tag)
5078 {
5079 if(use_datatypes)
5080 {
5081 // extract members
5082 if(where==wheret::BEGIN)
5083 out << "(let ((?ufop" << nesting << " ";
5084 else
5085 {
5086 out << ")) ";
5087
5088 const std::string &smt_typename = datatype_map.at(type);
5089
5090 out << "(mk-" << smt_typename;
5091
5092 const struct_typet &struct_type =
5093 type.id() == ID_struct_tag ? ns.follow_tag(to_struct_tag_type(type))
5094 : to_struct_type(type);
5095
5096 const struct_typet::componentst &components=
5097 struct_type.components();
5098
5099 std::size_t offset=0;
5100
5101 std::size_t i=0;
5102 for(struct_typet::componentst::const_iterator
5103 it=components.begin();
5104 it!=components.end();
5105 it++, i++)
5106 {
5107 if(is_zero_width(it->type(), ns))
5108 continue;
5109
5110 std::size_t member_width=boolbv_width(it->type());
5111
5112 out << " ";
5113 unflatten(wheret::BEGIN, it->type(), nesting+1);
5114 out << "((_ extract " << offset+member_width-1 << " "
5115 << offset << ") ?ufop" << nesting << ")";
5116 unflatten(wheret::END, it->type(), nesting+1);
5117 offset+=member_width;
5118 }
5119
5120 out << "))"; // mk-, let
5121 }
5122 }
5123 else
5124 {
5125 // nop, already a bv
5126 }
5127 }
5128 else
5129 {
5130 // nop
5131 }
5132}
5133
5134void smt2_convt::set_to(const exprt &expr, bool value)
5135{
5136 PRECONDITION(expr.is_boolean());
5137
5138 if(expr.id()==ID_and && value)
5139 {
5140 for(const auto &op : expr.operands())
5141 set_to(op, true);
5142 return;
5143 }
5144
5145 if(expr.id()==ID_or && !value)
5146 {
5147 for(const auto &op : expr.operands())
5148 set_to(op, false);
5149 return;
5150 }
5151
5152 if(expr.id()==ID_not)
5153 {
5154 return set_to(to_not_expr(expr).op(), !value);
5155 }
5156
5157 out << "\n";
5158
5159 // special treatment for "set_to(a=b, true)" where
5160 // a is a new symbol
5161
5162 if(expr.id() == ID_equal && value)
5163 {
5165 if(is_zero_width(equal_expr.lhs().type(), ns))
5166 {
5167 // ignore equality checking over expressions with empty (void) type
5168 return;
5169 }
5170
5171 if(equal_expr.lhs().id()==ID_symbol)
5172 {
5173 const irep_idt &identifier =
5174 to_symbol_expr(equal_expr.lhs()).identifier();
5175
5176 if(
5177 identifier_map.find(identifier) == identifier_map.end() &&
5178 equal_expr.lhs() != equal_expr.rhs())
5179 {
5180 auto id_entry = identifier_map.insert(
5181 {identifier, identifiert{equal_expr.lhs().type(), false}});
5182 CHECK_RETURN(id_entry.second);
5183
5184 find_symbols(id_entry.first->second.type);
5186
5187 std::string smt2_identifier=convert_identifier(identifier);
5189
5190 out << "; set_to true (equal)\n";
5191
5192 if(equal_expr.lhs().type().id() == ID_mathematical_function)
5193 {
5194 // We avoid define-fun, since it has been reported to cause
5195 // trouble with Z3's parser.
5196 out << "(declare-fun " << smt2_identifier;
5197
5200
5201 out << " (";
5202 bool first = true;
5203
5204 for(auto &t : mathematical_function_type.domain())
5205 {
5206 if(first)
5207 first = false;
5208 else
5209 out << ' ';
5210
5211 convert_type(t);
5212 }
5213
5214 out << ") ";
5216 out << ")\n";
5217
5218 out << "(assert (= " << smt2_identifier << ' ';
5220 out << ')' << ')' << '\n';
5221 }
5222 else
5223 {
5224 out << "(define-fun " << smt2_identifier;
5225 out << " () ";
5226 convert_type(equal_expr.lhs().type());
5227 out << ' ';
5228 if(
5229 equal_expr.lhs().type().id() != ID_array ||
5231 {
5233 }
5234 else
5235 {
5236 unflatten(wheret::BEGIN, equal_expr.lhs().type());
5237
5239
5240 unflatten(wheret::END, equal_expr.lhs().type());
5241 }
5242 out << ')' << '\n';
5243 }
5244
5245 return; // done
5246 }
5247 }
5248 }
5249
5251
5252#if 0
5253 out << "; CONV: "
5254 << format(expr) << "\n";
5255#endif
5256
5257 out << "; set_to " << (value?"true":"false") << "\n"
5258 << "(assert ";
5259 if(!value)
5260 {
5261 out << "(not ";
5262 }
5263 const auto found_literal = defined_expressions.find(expr);
5264 if(!(found_literal == defined_expressions.end()))
5265 {
5266 // This is a converted expression, we can just assert the literal name
5267 // since the expression is already defined
5268 out << found_literal->second;
5269 set_values[found_literal->second] = value;
5270 }
5271 else
5272 {
5274 }
5275 if(!value)
5276 {
5277 out << ")";
5278 }
5279 out << ")\n";
5280 return;
5281}
5282
5290{
5291 exprt lowered_expr = expr;
5292
5293 for(auto it = lowered_expr.depth_begin(), itend = lowered_expr.depth_end();
5294 it != itend;
5295 ++it)
5296 {
5297 if(
5298 it->id() == ID_byte_extract_little_endian ||
5299 it->id() == ID_byte_extract_big_endian)
5300 {
5301 it.mutate() = lower_byte_extract(to_byte_extract_expr(*it), ns);
5302 }
5303 else if(
5304 it->id() == ID_byte_update_little_endian ||
5305 it->id() == ID_byte_update_big_endian)
5306 {
5307 it.mutate() = lower_byte_update(to_byte_update_expr(*it), ns);
5308 }
5309 }
5310
5311 return lowered_expr;
5312}
5313
5322{
5323 // First, replace byte operators, because they may introduce new array
5324 // expressions that must be seen by find_symbols:
5326 INVARIANT(
5328 "lower_byte_operators should remove all byte operators");
5329
5330 // Perform rewrites that may introduce new symbols
5331 for(auto it = lowered_expr.depth_begin(), itend = lowered_expr.depth_end();
5332 it != itend;) // no ++it
5333 {
5334 if(
5335 auto prophecy_r_or_w_ok =
5337 {
5339 it.mutate() = lowered;
5340 it.next_sibling_or_parent();
5341 }
5342 else if(
5345 {
5347 it.mutate() = lowered;
5348 it.next_sibling_or_parent();
5349 }
5350 else
5351 ++it;
5352 }
5353
5354 // Now create symbols for all composite expressions present in lowered_expr:
5356
5357 return lowered_expr;
5358}
5359
5370{
5371 if(is_zero_width(expr.type(), ns))
5372 return;
5373
5374 // recursive call on type
5375 find_symbols(expr.type());
5376
5377 if(expr.id() == ID_exists || expr.id() == ID_forall)
5378 {
5379 std::unordered_map<irep_idt, std::optional<identifiert>> shadowed_syms;
5380
5381 // do not declare the quantified symbol, but record
5382 // as 'bound symbol'
5383 const auto &q_expr = to_quantifier_expr(expr);
5384 for(const auto &symbol : q_expr.variables())
5385 {
5386 const auto identifier = symbol.identifier();
5387 auto id_entry =
5388 identifier_map.insert({identifier, identifiert{symbol.type(), true}});
5389 shadowed_syms.insert(
5390 {identifier,
5391 id_entry.second ? std::nullopt
5392 : std::optional{id_entry.first->second}});
5393 }
5394 find_symbols(q_expr.where());
5395 for(const auto &[id, shadowed_val] : shadowed_syms)
5396 {
5397 auto previous_entry = identifier_map.find(id);
5398 if(!shadowed_val.has_value())
5400 else
5401 previous_entry->second = std::move(*shadowed_val);
5402 }
5403 return;
5404 }
5405
5406 // recursive call on operands
5407 for(const auto &op : expr.operands())
5408 find_symbols(op);
5409
5410 if(expr.id()==ID_symbol ||
5411 expr.id()==ID_nondet_symbol)
5412 {
5413 // we don't track function-typed symbols
5414 if(expr.type().id()==ID_code)
5415 return;
5416
5417 irep_idt identifier;
5418
5419 if(expr.id()==ID_symbol)
5420 identifier = to_symbol_expr(expr).identifier();
5421 else
5422 identifier="nondet_"+
5423 id2string(to_nondet_symbol_expr(expr).get_identifier());
5424
5425 auto id_entry =
5426 identifier_map.insert({identifier, identifiert{expr.type(), false}});
5427
5428 if(id_entry.second)
5429 {
5430 std::string smt2_identifier=convert_identifier(identifier);
5432
5433 out << "; find_symbols\n";
5434 out << "(declare-fun " << smt2_identifier;
5435
5436 if(expr.type().id() == ID_mathematical_function)
5437 {
5440 out << " (";
5441 bool first = true;
5442
5443 for(auto &type : mathematical_function_type.domain())
5444 {
5445 if(first)
5446 first = false;
5447 else
5448 out << ' ';
5449 convert_type(type);
5450 }
5451
5452 out << ") ";
5454 }
5455 else
5456 {
5457 out << " () ";
5458 convert_type(expr.type());
5459 }
5460
5461 out << ')' << '\n';
5462
5463 // We need an additional constraint for range-typed symbols,
5464 // or otherwise we get satisfying assignments with values
5465 // outside of the range when the size of the range isn't
5466 // a power of two.
5467 if(expr.type().id() == ID_range)
5468 {
5469 auto &range_type = to_integer_range_type(expr.type());
5470 if(!is_power_of_two(range_type.size()))
5471 {
5472 out << "(assert (bvule " << smt2_identifier << ' ';
5474 out << "))\n"; // bvule, assert
5475 }
5476 }
5477 }
5478 }
5479 else if(expr.id() == ID_array_of)
5480 {
5481 if(!use_as_const)
5482 {
5483 if(defined_expressions.find(expr) == defined_expressions.end())
5484 {
5485 const auto &array_of = to_array_of_expr(expr);
5486 const auto &array_type = array_of.type();
5487
5488 const irep_idt id =
5489 "array_of." + std::to_string(defined_expressions.size());
5490 out << "; the following is a substitute for lambda i. x\n";
5491 out << "(declare-fun " << id << " () ";
5493 out << ")\n";
5494
5495 if(!is_zero_width(array_type.element_type(), ns))
5496 {
5497 // use a quantifier-based initialization instead of lambda
5498 out << "(assert (forall ((i ";
5499 convert_type(array_type.index_type());
5500 out << ")) (= (select " << id << " i) ";
5501 if(array_type.element_type().id() == ID_bool && !use_array_of_bool)
5502 {
5503 out << "(ite ";
5504 convert_expr(array_of.what());
5505 out << " #b1 #b0)";
5506 }
5507 else
5508 {
5509 convert_expr(array_of.what());
5510 }
5511 out << ")))\n";
5512 }
5513
5514 defined_expressions[expr] = id;
5515 }
5516 }
5517 }
5518 else if(expr.id() == ID_array_comprehension)
5519 {
5521 {
5522 if(defined_expressions.find(expr) == defined_expressions.end())
5523 {
5525 const auto &array_type = array_comprehension.type();
5526 const auto &array_size = array_type.size();
5527
5528 const irep_idt id =
5529 "array_comprehension." + std::to_string(defined_expressions.size());
5530 out << "(declare-fun " << id << " () ";
5532 out << ")\n";
5533
5534 out << "; the following is a substitute for lambda i . x(i)\n";
5535 out << "; universally quantified initialization of the array\n";
5536 out << "(assert (forall ((";
5538 out << " ";
5539 convert_type(array_size.type());
5540 out << ")) (=> (and (bvule (_ bv0 " << boolbv_width(array_size.type())
5541 << ") ";
5543 out << ") (bvult ";
5545 out << " ";
5547 out << ")) (= (select " << id << " ";
5549 out << ") ";
5550 if(array_type.element_type().id() == ID_bool && !use_array_of_bool)
5551 {
5552 out << "(ite ";
5554 out << " #b1 #b0)";
5555 }
5556 else
5557 {
5559 }
5560 out << "))))\n";
5561
5562 defined_expressions[expr] = id;
5563 }
5564 }
5565 }
5566 else if(expr.id()==ID_array)
5567 {
5568 if(defined_expressions.find(expr)==defined_expressions.end())
5569 {
5571
5572 const irep_idt id = "array." + std::to_string(defined_expressions.size());
5573 out << "; the following is a substitute for an array constructor" << "\n";
5574 out << "(declare-fun " << id << " () ";
5576 out << ")" << "\n";
5577
5578 if(!is_zero_width(array_type.element_type(), ns))
5579 {
5580 for(std::size_t i = 0; i < expr.operands().size(); i++)
5581 {
5582 out << "(assert (= (select " << id << " ";
5583 convert_expr(from_integer(i, array_type.index_type()));
5584 out << ") "; // select
5585 if(array_type.element_type().id() == ID_bool && !use_array_of_bool)
5586 {
5587 out << "(ite ";
5588 convert_expr(expr.operands()[i]);
5589 out << " #b1 #b0)";
5590 }
5591 else
5592 {
5593 convert_expr(expr.operands()[i]);
5594 }
5595 out << "))"
5596 << "\n"; // =, assert
5597 }
5598 }
5599
5600 defined_expressions[expr]=id;
5601 }
5602 }
5603 else if(expr.id()==ID_string_constant)
5604 {
5605 if(defined_expressions.find(expr)==defined_expressions.end())
5606 {
5607 // introduce a temporary array.
5608 exprt tmp=to_string_constant(expr).to_array_expr();
5609 const array_typet &array_type=to_array_type(tmp.type());
5610
5611 const irep_idt id =
5612 "string." + std::to_string(defined_expressions.size());
5613 out << "; the following is a substitute for a string" << "\n";
5614 out << "(declare-fun " << id << " () ";
5616 out << ")" << "\n";
5617
5618 for(std::size_t i=0; i<tmp.operands().size(); i++)
5619 {
5620 out << "(assert (= (select " << id << ' ';
5621 convert_expr(from_integer(i, array_type.index_type()));
5622 out << ") "; // select
5623 convert_expr(tmp.operands()[i]);
5624 out << "))" << "\n";
5625 }
5626
5627 defined_expressions[expr]=id;
5628 }
5629 }
5630 else if(
5632 {
5633 if(object_sizes.find(*object_size) == object_sizes.end())
5634 {
5635 const irep_idt id = convert_identifier(
5636 "object_size." + std::to_string(object_sizes.size()));
5637 out << "(declare-fun " << id << " () ";
5639 out << ")"
5640 << "\n";
5641
5643 }
5644 }
5645 // clang-format off
5646 else if(!use_FPA_theory &&
5647 expr.operands().size() >= 1 &&
5648 (expr.id() == ID_floatbv_plus ||
5649 expr.id() == ID_floatbv_minus ||
5650 expr.id() == ID_floatbv_mult ||
5651 expr.id() == ID_floatbv_div ||
5652 expr.id() == ID_floatbv_fma ||
5653 expr.id() == ID_floatbv_typecast ||
5654 expr.id() == ID_ieee_float_equal ||
5655 expr.id() == ID_ieee_float_notequal ||
5656 ((expr.id() == ID_lt ||
5657 expr.id() == ID_gt ||
5658 expr.id() == ID_le ||
5659 expr.id() == ID_ge ||
5660 expr.id() == ID_isnan ||
5661 expr.id() == ID_isnormal ||
5662 expr.id() == ID_isfinite ||
5663 expr.id() == ID_isinf ||
5664 expr.id() == ID_sign ||
5665 expr.id() == ID_unary_minus ||
5666 expr.id() == ID_typecast ||
5667 expr.id() == ID_abs) &&
5668 to_multi_ary_expr(expr).op0().type().id() == ID_floatbv)))
5669 // clang-format on
5670 {
5671 irep_idt function =
5672 convert_identifier("float_bv." + expr.id_string() + floatbv_suffix(expr));
5673
5674 if(bvfp_set.insert(function).second)
5675 {
5676 out << "; this is a model for " << expr.id() << " : "
5677 << type2id(to_multi_ary_expr(expr).op0().type()) << " -> "
5678 << type2id(expr.type()) << "\n"
5679 << "(define-fun " << function << " (";
5680
5681 for(std::size_t i = 0; i < expr.operands().size(); i++)
5682 {
5683 if(i!=0)
5684 out << " ";
5685 out << "(op" << i << ' ';
5686 convert_type(expr.operands()[i].type());
5687 out << ')';
5688 }
5689
5690 out << ") ";
5691 convert_type(expr.type()); // return type
5692 out << ' ';
5693
5694 exprt tmp1=expr;
5695 for(std::size_t i = 0; i < tmp1.operands().size(); i++)
5696 tmp1.operands()[i]=
5697 smt2_symbolt("op"+std::to_string(i), tmp1.operands()[i].type());
5698
5700 tmp2=letify(tmp2);
5701 CHECK_RETURN(!tmp2.is_nil());
5702
5704
5705 out << ")\n"; // define-fun
5706 }
5707 }
5708 else if(
5709 use_FPA_theory && expr.id() == ID_typecast &&
5710 to_typecast_expr(expr).op().type().id() == ID_floatbv &&
5711 expr.type().id() == ID_bv)
5712 {
5713 // This is _NOT_ a semantic conversion, but bit-wise.
5714 if(defined_expressions.find(expr) == defined_expressions.end())
5715 {
5716 // This conversion is non-trivial as it requires creating a
5717 // new bit-vector variable and then asserting that it converts
5718 // to the required floating-point number.
5719 const irep_idt id =
5720 "bvfromfloat." + std::to_string(defined_expressions.size());
5721 out << "(declare-fun " << id << " () ";
5722 convert_type(expr.type());
5723 out << ')' << '\n';
5724
5725 const typecast_exprt &tc = to_typecast_expr(expr);
5726 const auto &floatbv_type = to_floatbv_type(tc.op().type());
5727 out << "(assert (= ";
5728 out << "((_ to_fp " << floatbv_type.get_e() << " "
5729 << floatbv_type.get_f() + 1 << ") " << id << ')';
5730 convert_expr(tc.op());
5731 out << ')'; // =
5732 out << ')' << '\n';
5733
5734 defined_expressions[expr] = id;
5735 }
5736 }
5737 else if(expr.id() == ID_initial_state)
5738 {
5739 irep_idt function = "initial-state";
5740
5741 if(state_fkt_declared.insert(function).second)
5742 {
5743 out << "(declare-fun " << function << " (";
5744 convert_type(to_unary_expr(expr).op().type());
5745 out << ") ";
5746 convert_type(expr.type()); // return type
5747 out << ")\n"; // declare-fun
5748 }
5749 }
5750 else if(expr.id() == ID_evaluate)
5751 {
5752 irep_idt function = "evaluate-" + type2id(expr.type());
5753
5754 if(state_fkt_declared.insert(function).second)
5755 {
5756 out << "(declare-fun " << function << " (";
5757 convert_type(to_binary_expr(expr).op0().type());
5758 out << ' ';
5759 convert_type(to_binary_expr(expr).op1().type());
5760 out << ") ";
5761 convert_type(expr.type()); // return type
5762 out << ")\n"; // declare-fun
5763 }
5764 }
5765 else if(
5766 expr.id() == ID_state_is_cstring ||
5767 expr.id() == ID_state_is_dynamic_object ||
5768 expr.id() == ID_state_live_object || expr.id() == ID_state_writeable_object)
5769 {
5770 irep_idt function =
5771 expr.id() == ID_state_is_cstring ? "state-is-cstring"
5772 : expr.id() == ID_state_is_dynamic_object ? "state-is-dynamic-object"
5773 : expr.id() == ID_state_live_object ? "state-live-object"
5774 : "state-writeable-object";
5775
5776 if(state_fkt_declared.insert(function).second)
5777 {
5778 out << "(declare-fun " << function << " (";
5779 convert_type(to_binary_expr(expr).op0().type());
5780 out << ' ';
5781 convert_type(to_binary_expr(expr).op1().type());
5782 out << ") ";
5783 convert_type(expr.type()); // return type
5784 out << ")\n"; // declare-fun
5785 }
5786 }
5787 else if(
5788 expr.id() == ID_state_r_ok || expr.id() == ID_state_w_ok ||
5789 expr.id() == ID_state_rw_ok)
5790 {
5791 irep_idt function = expr.id() == ID_state_r_ok ? "state-r-ok"
5792 : expr.id() == ID_state_w_ok ? "state-w-ok"
5793 : "state-rw-ok";
5794
5795 if(state_fkt_declared.insert(function).second)
5796 {
5797 out << "(declare-fun " << function << " (";
5798 convert_type(to_ternary_expr(expr).op0().type());
5799 out << ' ';
5800 convert_type(to_ternary_expr(expr).op1().type());
5801 out << ' ';
5802 convert_type(to_ternary_expr(expr).op2().type());
5803 out << ") ";
5804 convert_type(expr.type()); // return type
5805 out << ")\n"; // declare-fun
5806 }
5807 }
5808 else if(expr.id() == ID_update_state)
5809 {
5810 irep_idt function =
5811 "update-state-" + type2id(to_multi_ary_expr(expr).op2().type());
5812
5813 if(state_fkt_declared.insert(function).second)
5814 {
5815 out << "(declare-fun " << function << " (";
5816 convert_type(to_multi_ary_expr(expr).op0().type());
5817 out << ' ';
5818 convert_type(to_multi_ary_expr(expr).op1().type());
5819 out << ' ';
5820 convert_type(to_multi_ary_expr(expr).op2().type());
5821 out << ") ";
5822 convert_type(expr.type()); // return type
5823 out << ")\n"; // declare-fun
5824 }
5825 }
5826 else if(expr.id() == ID_enter_scope_state)
5827 {
5828 irep_idt function =
5829 "enter-scope-state-" + type2id(to_binary_expr(expr).op1().type());
5830
5831 if(state_fkt_declared.insert(function).second)
5832 {
5833 out << "(declare-fun " << function << " (";
5834 convert_type(to_binary_expr(expr).op0().type());
5835 out << ' ';
5836 convert_type(to_binary_expr(expr).op1().type());
5837 out << ' ';
5839 out << ") ";
5840 convert_type(expr.type()); // return type
5841 out << ")\n"; // declare-fun
5842 }
5843 }
5844 else if(expr.id() == ID_exit_scope_state)
5845 {
5846 irep_idt function =
5847 "exit-scope-state-" + type2id(to_binary_expr(expr).op1().type());
5848
5849 if(state_fkt_declared.insert(function).second)
5850 {
5851 out << "(declare-fun " << function << " (";
5852 convert_type(to_binary_expr(expr).op0().type());
5853 out << ' ';
5854 convert_type(to_binary_expr(expr).op1().type());
5855 out << ") ";
5856 convert_type(expr.type()); // return type
5857 out << ")\n"; // declare-fun
5858 }
5859 }
5860 else if(expr.id() == ID_allocate)
5861 {
5862 irep_idt function = "allocate";
5863
5864 if(state_fkt_declared.insert(function).second)
5865 {
5866 out << "(declare-fun " << function << " (";
5867 convert_type(to_binary_expr(expr).op0().type());
5868 out << ' ';
5869 convert_type(to_binary_expr(expr).op1().type());
5870 out << ") ";
5871 convert_type(expr.type()); // return type
5872 out << ")\n"; // declare-fun
5873 }
5874 }
5875 else if(expr.id() == ID_reallocate)
5876 {
5877 irep_idt function = "reallocate";
5878
5879 if(state_fkt_declared.insert(function).second)
5880 {
5881 out << "(declare-fun " << function << " (";
5882 convert_type(to_ternary_expr(expr).op0().type());
5883 out << ' ';
5884 convert_type(to_ternary_expr(expr).op1().type());
5885 out << ' ';
5886 convert_type(to_ternary_expr(expr).op2().type());
5887 out << ") ";
5888 convert_type(expr.type()); // return type
5889 out << ")\n"; // declare-fun
5890 }
5891 }
5892 else if(expr.id() == ID_deallocate_state)
5893 {
5894 irep_idt function = "deallocate";
5895
5896 if(state_fkt_declared.insert(function).second)
5897 {
5898 out << "(declare-fun " << function << " (";
5899 convert_type(to_binary_expr(expr).op0().type());
5900 out << ' ';
5901 convert_type(to_binary_expr(expr).op1().type());
5902 out << ") ";
5903 convert_type(expr.type()); // return type
5904 out << ")\n"; // declare-fun
5905 }
5906 }
5907 else if(expr.id() == ID_object_address)
5908 {
5909 irep_idt function = "object-address";
5910
5911 if(state_fkt_declared.insert(function).second)
5912 {
5913 out << "(declare-fun " << function << " (String) ";
5914 convert_type(expr.type()); // return type
5915 out << ")\n"; // declare-fun
5916 }
5917 }
5918 else if(expr.id() == ID_field_address)
5919 {
5920 irep_idt function = "field-address-" + type2id(expr.type());
5921
5922 if(state_fkt_declared.insert(function).second)
5923 {
5924 out << "(declare-fun " << function << " (";
5925 convert_type(to_field_address_expr(expr).op().type());
5926 out << ' ';
5927 out << "String";
5928 out << ") ";
5929 convert_type(expr.type()); // return type
5930 out << ")\n"; // declare-fun
5931 }
5932 }
5933 else if(expr.id() == ID_element_address)
5934 {
5935 irep_idt function = "element-address-" + type2id(expr.type());
5936
5937 if(state_fkt_declared.insert(function).second)
5938 {
5939 out << "(declare-fun " << function << " (";
5940 convert_type(to_element_address_expr(expr).base().type());
5941 out << ' ';
5942 convert_type(to_element_address_expr(expr).index().type());
5943 out << ' '; // repeat, for the element size
5944 convert_type(to_element_address_expr(expr).index().type());
5945 out << ") ";
5946 convert_type(expr.type()); // return type
5947 out << ")\n"; // declare-fun
5948 }
5949 }
5950}
5951
5953{
5954 const typet &type = expr.type();
5955 PRECONDITION(type.id()==ID_array);
5956
5957 // arrays inside structs get flattened, unless we have datatypes
5958 if(expr.id() == ID_with)
5959 return use_array_theory(to_with_expr(expr).old());
5960 else if(expr.id() == ID_if)
5961 {
5962 // For an array-typed if-then-else, the SMT sort produced by
5963 // convert_expr (see the ID_if branch above) is determined by the
5964 // sorts chosen for its two operands:
5965 // - if both branches are bit-vector-encoded, i.e. neither uses array
5966 // theory (typically because both are array-typed members of a
5967 // struct that has been flattened to a bit-vector), the resulting
5968 // ite is a bit-vector;
5969 // - if both branches use array theory, the ite is an SMT array;
5970 // - if exactly one branch uses array theory, the ID_if handler in
5971 // convert_expr unflattens the bit-vector branch back to an SMT
5972 // array (see the wheret::BEGIN/wheret::END unflatten calls), so
5973 // the ite is again an SMT array.
5974 // The ite therefore "uses array theory" iff at least one branch
5975 // does. Without this clause, the fall-through below would
5976 // unconditionally return true for ID_if (since ID_if != ID_member),
5977 // which is wrong in the symmetric bit-vector case: callers like
5978 // convert_index, convert_with, flatten2bv, and the array-typed
5979 // define-fun path would then emit array-theory operators -- e.g.
5980 // (select <ite> ...) or (store <ite> ...) -- on a bit-vector
5981 // operand, producing ill-typed SMT-LIB 2 that is rejected by
5982 // conforming solvers (cf. issue #9008). The asymmetric case was
5983 // already handled, for ID_with branches, in the ID_if conversion
5984 // logic of convert_expr; the present clause makes use_array_theory
5985 // consistent with that conversion in all four combinations.
5986 const if_exprt &if_expr = to_if_expr(expr);
5987 return use_array_theory(if_expr.true_case()) ||
5988 use_array_theory(if_expr.false_case());
5989 }
5990 else
5991 return use_datatypes || expr.id() != ID_member;
5992}
5993
5995{
5996 if(type.id()==ID_array)
5997 {
5999 CHECK_RETURN(array_type.size().is_not_nil());
6000
6001 // we always use array theory for top-level arrays
6002 const typet &subtype = array_type.element_type();
6003
6004 // Arrays map the index type to the element type.
6005 out << "(Array ";
6006 convert_type(array_type.index_type());
6007 out << " ";
6008
6009 if(subtype.id()==ID_bool && !use_array_of_bool)
6010 out << "(_ BitVec 1)";
6011 else
6012 convert_type(array_type.element_type());
6013
6014 out << ")";
6015 }
6016 else if(type.id()==ID_bool)
6017 {
6018 out << "Bool";
6019 }
6020 else if(type.id() == ID_struct || type.id() == ID_struct_tag)
6021 {
6022 if(use_datatypes)
6023 {
6024 out << datatype_map.at(type);
6025 }
6026 else
6027 {
6028 std::size_t width=boolbv_width(type);
6029
6030 out << "(_ BitVec " << width << ")";
6031 }
6032 }
6033 else if(type.id()==ID_code)
6034 {
6035 // These may appear in structs.
6036 // We replace this by "Bool" in order to keep the same
6037 // member count.
6038 out << "Bool";
6039 }
6040 else if(type.id() == ID_union || type.id() == ID_union_tag)
6041 {
6042 std::size_t width=boolbv_width(type);
6043 const union_typet &union_type = type.id() == ID_union_tag
6044 ? ns.follow_tag(to_union_tag_type(type))
6045 : to_union_type(type);
6047 union_type.components().empty() || width != 0,
6048 "failed to get width of union");
6049
6050 out << "(_ BitVec " << width << ")";
6051 }
6052 else if(type.id()==ID_pointer)
6053 {
6054 out << "(_ BitVec "
6055 << boolbv_width(type) << ")";
6056 }
6057 else if(type.id()==ID_bv ||
6058 type.id()==ID_fixedbv ||
6059 type.id()==ID_unsignedbv ||
6060 type.id()==ID_signedbv ||
6061 type.id()==ID_c_bool)
6062 {
6063 out << "(_ BitVec "
6064 << to_bitvector_type(type).get_width() << ")";
6065 }
6066 else if(type.id()==ID_c_enum)
6067 {
6068 // these have an underlying type
6069 out << "(_ BitVec "
6070 << to_bitvector_type(to_c_enum_type(type).underlying_type()).get_width()
6071 << ")";
6072 }
6073 else if(type.id()==ID_c_enum_tag)
6074 {
6075 convert_type(ns.follow_tag(to_c_enum_tag_type(type)));
6076 }
6077 else if(type.id()==ID_floatbv)
6078 {
6080
6081 if(use_FPA_theory)
6082 out << "(_ FloatingPoint "
6083 << floatbv_type.get_e() << " "
6084 << floatbv_type.get_f() + 1 << ")";
6085 else
6086 out << "(_ BitVec "
6087 << floatbv_type.get_width() << ")";
6088 }
6089 else if(type.id()==ID_rational ||
6090 type.id()==ID_real)
6091 out << "Real";
6092 else if(type.id()==ID_integer)
6093 out << "Int";
6094 else if(type.id() == ID_natural)
6095 out << "Nat";
6096 else if(type.id()==ID_complex)
6097 {
6098 if(use_datatypes)
6099 {
6100 out << datatype_map.at(type);
6101 }
6102 else
6103 {
6104 std::size_t width=boolbv_width(type);
6105
6106 out << "(_ BitVec " << width << ")";
6107 }
6108 }
6109 else if(type.id()==ID_c_bit_field)
6110 {
6112 }
6113 else if(type.id() == ID_state)
6114 {
6115 out << "state";
6116 }
6117 else if(type.id() == ID_range)
6118 {
6119 auto &range_type = to_integer_range_type(type);
6120 if(range_type.empty())
6121 UNEXPECTEDCASE("unsupported range type");
6122 out << "(_ BitVec " << address_bits(range_type.size()) << ")";
6123 }
6124 else
6125 {
6126 UNEXPECTEDCASE("unsupported type: "+type.id_string());
6127 }
6128}
6129
6131{
6132 std::set<irep_idt> recstack;
6134}
6135
6137 const typet &type,
6138 std::set<irep_idt> &recstack)
6139{
6140 if(type.id()==ID_array)
6141 {
6143 find_symbols(array_type.size());
6144 find_symbols_rec(array_type.element_type(), recstack);
6145 }
6146 else if(type.id()==ID_complex)
6147 {
6148 find_symbols_rec(to_complex_type(type).subtype(), recstack);
6149
6150 if(use_datatypes &&
6151 datatype_map.find(type)==datatype_map.end())
6152 {
6153 const std::string smt_typename =
6154 "complex." + std::to_string(datatype_map.size());
6155 datatype_map[type] = smt_typename;
6156
6157 out << "(declare-datatypes ((" << smt_typename << " 0)) "
6158 << "(((mk-" << smt_typename;
6159
6160 out << " (" << smt_typename << ".imag ";
6161 convert_type(to_complex_type(type).subtype());
6162 out << ")";
6163
6164 out << " (" << smt_typename << ".real ";
6165 convert_type(to_complex_type(type).subtype());
6166 out << ")";
6167
6168 out << "))))\n";
6169 }
6170 }
6171 else if(type.id() == ID_struct)
6172 {
6173 // Cater for mutually recursive struct types
6174 bool need_decl=false;
6175 if(use_datatypes &&
6176 datatype_map.find(type)==datatype_map.end())
6177 {
6178 const std::string smt_typename =
6179 "struct." + std::to_string(datatype_map.size());
6180 datatype_map[type] = smt_typename;
6181 need_decl=true;
6182 }
6183
6184 const struct_typet::componentst &components =
6185 to_struct_type(type).components();
6186
6187 for(const auto &component : components)
6189
6190 // Declare the corresponding SMT type if we haven't already.
6191 if(need_decl)
6192 {
6193 const std::string &smt_typename = datatype_map.at(type);
6194
6195 // We're going to create a datatype named something like `struct.0'.
6196 // It's going to have a single constructor named `mk-struct.0' with an
6197 // argument for each member of the struct. The declaration that
6198 // creates this type looks like:
6199 //
6200 // (declare-datatypes ((struct.0 0)) (((mk-struct.0
6201 // (struct.0.component1 type1)
6202 // ...
6203 // (struct.0.componentN typeN)))))
6204 out << "(declare-datatypes ((" << smt_typename << " 0)) "
6205 << "(((mk-" << smt_typename << " ";
6206
6207 for(const auto &component : components)
6208 {
6209 if(is_zero_width(component.type(), ns))
6210 continue;
6211
6212 out << "(" << smt_typename << "." << component.get_name()
6213 << " ";
6214 convert_type(component.type());
6215 out << ") ";
6216 }
6217
6218 out << "))))" << "\n";
6219
6220 // Let's also declare convenience functions to update individual
6221 // members of the struct whil we're at it. The functions are
6222 // named like `update-struct.0.component1'. Their declarations
6223 // look like:
6224 //
6225 // (declare-fun update-struct.0.component1
6226 // ((s struct.0) ; first arg -- the struct to update
6227 // (v type1)) ; second arg -- the value to update
6228 // struct.0 ; the output type
6229 // (mk-struct.0 ; build the new struct...
6230 // v ; the updated value
6231 // (struct.0.component2 s) ; retain the other members
6232 // ...
6233 // (struct.0.componentN s)))
6234
6235 for(struct_union_typet::componentst::const_iterator
6236 it=components.begin();
6237 it!=components.end();
6238 ++it)
6239 {
6240 if(is_zero_width(it->type(), ns))
6241 continue;
6242
6244 out << "(define-fun update-" << smt_typename << "."
6245 << component.get_name() << " "
6246 << "((s " << smt_typename << ") "
6247 << "(v ";
6248 convert_type(component.type());
6249 out << ")) " << smt_typename << " "
6250 << "(mk-" << smt_typename
6251 << " ";
6252
6253 for(struct_union_typet::componentst::const_iterator
6254 it2=components.begin();
6255 it2!=components.end();
6256 ++it2)
6257 {
6258 if(it==it2)
6259 out << "v ";
6260 else if(!is_zero_width(it2->type(), ns))
6261 {
6262 out << "(" << smt_typename << "."
6263 << it2->get_name() << " s) ";
6264 }
6265 }
6266
6267 out << "))" << "\n";
6268 }
6269
6270 out << "\n";
6271 }
6272 }
6273 else if(type.id() == ID_union)
6274 {
6275 const union_typet::componentst &components =
6276 to_union_type(type).components();
6277
6278 for(const auto &component : components)
6280 }
6281 else if(type.id()==ID_code)
6282 {
6283 const code_typet::parameterst &parameters=
6284 to_code_type(type).parameters();
6285 for(const auto &param : parameters)
6287
6288 find_symbols_rec(to_code_type(type).return_type(), recstack);
6289 }
6290 else if(type.id()==ID_pointer)
6291 {
6292 find_symbols_rec(to_pointer_type(type).base_type(), recstack);
6293 }
6294 else if(type.id() == ID_struct_tag)
6295 {
6296 const auto &struct_tag = to_struct_tag_type(type);
6297 const irep_idt &id = struct_tag.get_identifier();
6298
6299 if(recstack.find(id) == recstack.end())
6300 {
6301 const auto &base_struct = ns.follow_tag(struct_tag);
6302 recstack.insert(id);
6305 }
6306 }
6307 else if(type.id() == ID_union_tag)
6308 {
6309 const auto &union_tag = to_union_tag_type(type);
6310 const irep_idt &id = union_tag.get_identifier();
6311
6312 if(recstack.find(id) == recstack.end())
6313 {
6314 recstack.insert(id);
6315 find_symbols_rec(ns.follow_tag(union_tag), recstack);
6316 }
6317 }
6318 else if(type.id() == ID_state)
6319 {
6320 if(datatype_map.find(type) == datatype_map.end())
6321 {
6322 datatype_map[type] = "state";
6323 out << "(declare-sort state 0)\n";
6324 }
6325 }
6326 else if(type.id() == ID_mathematical_function)
6327 {
6328 const auto &mathematical_function_type =
6330 for(auto &d_type : mathematical_function_type.domain())
6332
6334 }
6335}
6336
6338{
6340}
configt config
Definition config.cpp:25
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
std::size_t address_bits(const mp_integer &size)
ceil(log2(size))
bool to_integer(const constant_exprt &expr, mp_integer &int_value)
Convert a constant expression expr to an arbitrary-precision integer.
bool is_power_of_two(const mp_integer &n)
irep_idt integer2bvrep(const mp_integer &src, std::size_t width)
convert an integer to bit-vector representation with given width This uses two's complement for negat...
mp_integer power(const mp_integer &base, const mp_integer &exponent)
A multi-precision implementation of the power operator.
API to expression classes for bitvectors.
const onehot0_exprt & to_onehot0_expr(const exprt &expr)
Cast an exprt to a onehot0_exprt.
const replication_exprt & to_replication_expr(const exprt &expr)
Cast an exprt to a replication_exprt.
const reduction_xnor_exprt & to_reduction_xnor_expr(const exprt &expr)
Cast an exprt to a reduction_xnor_exprt.
const reduction_nand_exprt & to_reduction_nand_expr(const exprt &expr)
Cast an exprt to a reduction_nand_exprt.
const shift_exprt & to_shift_expr(const exprt &expr)
Cast an exprt to a shift_exprt.
const reduction_and_exprt & to_reduction_and_expr(const exprt &expr)
Cast an exprt to a reduction_and_exprt.
const reduction_or_exprt & to_reduction_or_expr(const exprt &expr)
Cast an exprt to a reduction_or_exprt.
const popcount_exprt & to_popcount_expr(const exprt &expr)
Cast an exprt to a popcount_exprt.
const update_bits_exprt & to_update_bits_expr(const exprt &expr)
Cast an exprt to an update_bits_exprt.
const extractbits_exprt & to_extractbits_expr(const exprt &expr)
Cast an exprt to an extractbits_exprt.
const onehot_exprt & to_onehot_expr(const exprt &expr)
Cast an exprt to a onehot_exprt.
bool can_cast_expr< minus_overflow_exprt >(const exprt &base)
const find_first_set_exprt & to_find_first_set_expr(const exprt &expr)
Cast an exprt to a find_first_set_exprt.
bool can_cast_expr< overflow_result_exprt >(const exprt &base)
const update_bit_exprt & to_update_bit_expr(const exprt &expr)
Cast an exprt to an update_bit_exprt.
const bitnot_exprt & to_bitnot_expr(const exprt &expr)
Cast an exprt to a bitnot_exprt.
const bswap_exprt & to_bswap_expr(const exprt &expr)
Cast an exprt to a bswap_exprt.
const count_leading_zeros_exprt & to_count_leading_zeros_expr(const exprt &expr)
Cast an exprt to a count_leading_zeros_exprt.
const reduction_xor_exprt & to_reduction_xor_expr(const exprt &expr)
Cast an exprt to a reduction_xor_exprt.
const bitreverse_exprt & to_bitreverse_expr(const exprt &expr)
Cast an exprt to a bitreverse_exprt.
const extractbit_exprt & to_extractbit_expr(const exprt &expr)
Cast an exprt to an extractbit_exprt.
const reduction_nor_exprt & to_reduction_nor_expr(const exprt &expr)
Cast an exprt to a reduction_nor_exprt.
const zero_extend_exprt & to_zero_extend_expr(const exprt &expr)
Cast an exprt to a zero_extend_exprt.
const count_trailing_zeros_exprt & to_count_trailing_zeros_expr(const exprt &expr)
Cast an exprt to a count_trailing_zeros_exprt.
const bv_typet & to_bv_type(const typet &type)
Cast a typet to a bv_typet.
const fixedbv_typet & to_fixedbv_type(const typet &type)
Cast a typet to a fixedbv_typet.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
const unsignedbv_typet & to_unsignedbv_type(const typet &type)
Cast a typet to an unsignedbv_typet.
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
bool has_byte_operator(const exprt &src)
Return true iff src or one of its operands contain a byte extract or byte update expression.
Expression classes for byte-level operators.
const byte_update_exprt & to_byte_update_expr(const exprt &expr)
exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
Rewrite a byte extract expression to more fundamental operations.
const byte_extract_exprt & to_byte_extract_expr(const exprt &expr)
exprt lower_byte_update(const byte_update_exprt &src, const namespacet &ns)
Rewrite a byte update expression to more fundamental operations.
typet c_bit_field_replacement_type(const c_bit_field_typet &src, const namespacet &ns)
pointer_typet pointer_type(const typet &subtype)
Definition c_types.cpp:235
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
Definition c_types.h:80
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition c_types.h:335
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
Definition c_types.h:377
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition c_types.h:184
const c_bool_typet & to_c_bool_type(const typet &type)
Cast a typet to a c_bool_typet.
Definition c_types.h:128
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition c_types.h:224
Absolute value.
Definition std_expr.h:440
Operator to return the address of an object.
virtual void clear()
Reset the abstract state.
Definition ai.h:269
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
Represents real numbers as roots (zeros) of a polynomial with rational coefficients.
Thrown when an unexpected error occurs during the analysis (e.g., when the SAT solver returns an erro...
Pointer-typed bitvector constant annotated with the pointer expression that the bitvector is the nume...
Array constructor from list of elements.
Definition std_expr.h:1570
Arrays with given size.
Definition std_types.h:806
const exprt & size() const
Definition std_types.h:839
const typet & element_type() const
The type of the elements of the array.
Definition std_types.h:826
A base class for binary expressions.
Definition std_expr.h:649
exprt & lhs()
Definition std_expr.h:679
exprt & rhs()
Definition std_expr.h:689
exprt & op0()
Definition expr.h:134
exprt & op1()
Definition expr.h:137
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition std_expr.h:784
Bit-wise negation of bit-vectors.
The Boolean type.
Definition std_types.h:35
const membert & get_member(const struct_typet &type, const irep_idt &member) const
The byte swap expression.
std::vector< parametert > parameterst
Definition std_types.h:585
struct configt::bv_encodingt bv_encoding
A constant literal expression.
Definition std_expr.h:3007
const irep_idt & get_value() const
Definition std_expr.h:3015
bool is_null_pointer() const
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
Definition std_expr.cpp:170
resultt
Result of running the decision procedure.
Division.
Definition std_expr.h:1152
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Equality.
Definition std_expr.h:1339
Boute's Euclidean definition of Modulo – to match SMT-LIB2.
Definition std_expr.h:1277
Base class for all expressions.
Definition expr.h:57
std::vector< exprt > operandst
Definition expr.h:59
bool has_operands() const
Return true if there is at least one operand.
Definition expr.h:92
bool is_boolean() const
Return whether the expression represents a Boolean.
Definition expr.h:229
exprt & op0()
Definition expr.h:134
exprt & op1()
Definition expr.h:137
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:213
typet & type()
Return the type of the expression.
Definition expr.h:85
void visit_post(std::function< void(exprt &)>)
These are post-order traversal visitors, i.e., the visitor is executed on a node after its children h...
Definition expr.cpp:119
operandst & operands()
Definition expr.h:95
Extracts a single bit of a bit-vector operand.
Extracts a sub-range of a bit-vector operand.
The Boolean constant false.
Definition std_expr.h:3135
std::size_t integer_bits
Definition fixedbv.h:22
std::size_t width
Definition fixedbv.h:22
std::size_t get_fraction_bits() const
Definition fixedbv.h:35
Fixed-width bit-vector with signed fixed-point interpretation.
Fused multiply-add expression: round(op0 * op1 + op2) with a single rounding.
exprt & op_multiply_lhs()
exprt & op_multiply_rhs()
exprt & rounding_mode()
Round a floating-point number to an integral value considering the given rounding mode.
Semantic type conversion from/to floating-point formats.
Fixed-width bit-vector with IEEE floating-point interpretation.
IEEE floating-point operations These have two data operands (op0 and op1) and one rounding mode (op2)...
std::size_t f
Definition ieee_float.h:26
std::size_t width() const
Definition ieee_float.h:50
An IEEE 754 floating-point value, including specificiation.
Definition ieee_float.h:117
static ieee_float_valuet minus_infinity(const ieee_float_spect &_spec)
Definition ieee_float.h:209
bool is_NaN() const
Definition ieee_float.h:259
static ieee_float_valuet one(const floatbv_typet &)
ieee_float_spect spec
Definition ieee_float.h:119
mp_integer pack() const
bool get_sign() const
Definition ieee_float.h:254
static ieee_float_valuet zero(const floatbv_typet &type)
Definition ieee_float.h:172
static ieee_float_valuet NaN(const ieee_float_spect &_spec)
Definition ieee_float.h:195
static ieee_float_valuet plus_infinity(const ieee_float_spect &_spec)
Definition ieee_float.h:202
bool is_infinity() const
Definition ieee_float.h:260
The trinary if-then-else operator.
Definition std_expr.h:2426
Boolean implication.
Definition std_expr.h:2154
Array index operator.
Definition std_expr.h:1431
exprt & index()
Definition std_expr.h:1471
exprt & array()
Definition std_expr.h:1461
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition irep.h:364
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition irep.cpp:482
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:44
const std::string & id_string() const
Definition irep.h:391
subt & get_sub()
Definition irep.h:448
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
bool is_nil() const
Definition irep.h:368
Evaluates to true if the operand is finite.
Evaluates to true if the operand is infinite.
Evaluates to true if the operand is NaN.
Evaluates to true if the operand is a normal number.
A let expression.
Definition std_expr.h:3259
bool is_true() const
Definition literal.h:156
bool sign() const
Definition literal.h:88
var_not var_no() const
Definition literal.h:83
bool is_false() const
Definition literal.h:161
Extract member of struct or union.
Definition std_expr.h:2866
Binary minus.
Definition std_expr.h:1065
Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
Definition std_expr.h:1216
Binary multiplication Associativity is not specified.
Definition std_expr.h:1104
exprt & op1()
Definition std_expr.h:942
exprt & op0()
Definition std_expr.h:936
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.
Boolean reduction: true iff every bit of the operand is 1.
Boolean reduction: true iff any bit of the operand is 1.
Boolean reduction: XOR (parity) of all bits in the operand.
Bit-vector replication.
A base class for shift and rotate operators.
Sign of an expression Predicate is true if _op is negative, false otherwise.
Definition std_expr.h:612
void convert_relation(const binary_relation_exprt &)
bool use_lambda_for_array
Definition smt2_conv.h:71
void convert_type(const typet &)
void unflatten(wheret, const typet &, unsigned nesting=0)
bool use_array_theory(const exprt &)
void find_symbols(const exprt &expr)
Find and declare symbols used in an expression This function traverses the expression tree and create...
std::size_t number_of_solver_calls
Definition smt2_conv.h:110
void convert_typecast(const typecast_exprt &expr)
void write_footer()
Writes the end of the SMT file to the smt_convt::out stream.
tvt l_get(literalt l) const
void convert_floatbv_rem(const binary_exprt &expr)
std::unordered_map< irep_idt, irept > current_bindings
Definition smt2_conv.h:200
bool use_FPA_theory
Definition smt2_conv.h:66
resultt dec_solve(const exprt &) override
Implementation of the decision procedure.
std::set< irep_idt > bvfp_set
Definition smt2_conv.h:206
void convert_address_of_rec(const exprt &expr, const pointer_typet &result_type)
void push() override
Unimplemented.
void convert_is_dynamic_object(const unary_exprt &)
void convert_literal(const literalt)
void convert_floatbv_div(const ieee_float_op_exprt &expr)
void convert_string_literal(const std::string &)
std::size_t get_number_of_solver_calls() const override
Return the number of incremental solver calls.
const namespacet & ns
Definition smt2_conv.h:99
void convert_floatbv_mult(const ieee_float_op_exprt &expr)
boolbv_widtht boolbv_width
Definition smt2_conv.h:108
void convert_constant(const constant_exprt &expr)
std::string floatbv_suffix(const exprt &) const
void flatten2bv(const exprt &)
std::string notes
Definition smt2_conv.h:101
void convert_floatbv_fma(const floatbv_fma_exprt &expr)
void convert_div(const div_exprt &expr)
std::ostream & out
Definition smt2_conv.h:100
exprt lower_byte_operators(const exprt &expr)
Lower byte_update and byte_extract operations within expr.
std::string type2id(const typet &) const
bool emit_set_logic
Definition smt2_conv.h:72
void convert_rounding_mode_FPA(const exprt &expr)
Converting a constant or symbolic rounding mode to SMT-LIB.
void convert_floatbv_typecast(const floatbv_typecast_exprt &expr)
struct_exprt parse_struct(const irept &s, const struct_typet &type)
std::string logic
Definition smt2_conv.h:101
void convert_mult(const mult_exprt &expr)
void convert_update_bit(const update_bit_exprt &)
exprt prepare_for_convert_expr(const exprt &expr)
Perform steps necessary before an expression is passed to convert_expr.
exprt get(const exprt &expr) const override
Return expr with variables replaced by values from satisfying assignment if available.
std::string decision_procedure_text() const override
Return a textual description of the decision procedure.
void convert_floatbv_minus(const ieee_float_op_exprt &expr)
bool use_check_sat_assuming
Definition smt2_conv.h:69
std::map< object_size_exprt, irep_idt > object_sizes
Definition smt2_conv.h:287
void define_object_size(const irep_idt &id, const object_size_exprt &expr)
bool use_datatypes
Definition smt2_conv.h:70
datatype_mapt datatype_map
Definition smt2_conv.h:272
void convert_mod(const mod_exprt &expr)
static std::string convert_identifier(const irep_idt &identifier)
void convert_floatbv_plus(const ieee_float_op_exprt &expr)
void convert_struct(const struct_exprt &expr)
std::unordered_map< irep_idt, bool > set_values
The values which boolean identifiers have been smt2_convt::set_to or in other words those which are a...
Definition smt2_conv.h:285
smt2_convt(const namespacet &_ns, const std::string &_benchmark, const std::string &_notes, const std::string &_logic, solvert _solver, std::ostream &_out)
Definition smt2_conv.cpp:59
void convert_member(const member_exprt &expr)
void convert_euclidean_mod(const euclidean_mod_exprt &expr)
void convert_index(const index_exprt &expr)
converterst converters
Definition smt2_conv.h:105
pointer_logict pointer_logic
Definition smt2_conv.h:240
exprt handle(const exprt &expr) override
Generate a handle, which is an expression that has the same value as the argument in any model that i...
void print_assignment(std::ostream &out) const override
Print satisfying assignment to out.
void walk_array_tree(std::unordered_map< int64_t, exprt > *operands_map, const irept &src, const array_typet &type)
This function walks the SMT output and populates a map with index/value pairs for the array.
void convert_floatbv_round_to_integral(const floatbv_round_to_integral_exprt &)
void set_to(const exprt &expr, bool value) override
For a Boolean expression expr, add the constraint 'expr' if value is true, otherwise add 'not expr'.
bool use_as_const
Definition smt2_conv.h:68
exprt parse_rec(const irept &s, const typet &type)
void convert_union(const union_exprt &expr)
exprt parse_union(const irept &s, const union_typet &type)
exprt parse_array(const irept &s, const array_typet &type)
This function is for parsing array output from SMT solvers when "(get-value |???|)" returns an array ...
std::vector< bool > boolean_assignment
Definition smt2_conv.h:294
void flatten_array(const exprt &)
produce a flat bit-vector for a given array of fixed size
void convert_with(const with_exprt &expr)
letifyt letify
Definition smt2_conv.h:177
bool use_array_of_bool
Definition smt2_conv.h:67
std::vector< literalt > assumptions
Definition smt2_conv.h:107
void convert_plus(const plus_exprt &expr)
defined_expressionst defined_expressions
Definition smt2_conv.h:281
void pop() override
Currently, only implements a single stack element (no nested contexts)
void convert_update_bits(const update_bits_exprt &)
void find_symbols_rec(const typet &type, std::set< irep_idt > &recstack)
void convert_update(const update_exprt &)
void write_header()
std::set< irep_idt > state_fkt_declared
Definition smt2_conv.h:210
solvert solver
Definition smt2_conv.h:102
identifier_mapt identifier_map
Definition smt2_conv.h:265
void convert_minus(const minus_exprt &expr)
void convert_expr(const exprt &)
constant_exprt parse_literal(const irept &, const typet &type)
const smt2_symbolt & to_smt2_symbol(const exprt &expr)
Definition smt2_conv.h:225
std::size_t no_boolean_variables
Definition smt2_conv.h:293
smt2_identifierst smt2_identifiers
Definition smt2_conv.h:290
void convert_floatbv(const exprt &expr)
literalt convert(const exprt &expr)
Struct constructor from list of elements.
Definition std_expr.h:1820
Structure type, corresponds to C style structs.
Definition std_types.h:230
const irep_idt & get_name() const
Definition std_types.h:78
const componentst & components() const
Definition std_types.h:146
std::vector< componentt > componentst
Definition std_types.h:139
The Boolean constant true.
Definition std_expr.h:3126
Definition threeval.h:20
Semantic type conversion.
Definition std_expr.h:1995
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:2003
The type of an expression, extends irept.
Definition type.h:29
Generic base class for unary expressions.
Definition std_expr.h:364
const exprt & op() const
Definition std_expr.h:394
The unary minus expression.
Definition std_expr.h:477
Union constructor from single element.
Definition std_expr.h:1724
The union type.
Definition c_types.h:147
Fixed-width bit-vector with unsigned binary interpretation.
Replaces a sub-range of a bit-vector operand.
exprt lower() const
A lowering to masking, shifting, or.
Replaces a sub-range of a bit-vector operand.
exprt lower() const
A lowering to masking, shifting, or.
Operator to update elements in structs and arrays.
Definition std_expr.h:2679
Operator to update elements in structs and arrays.
Definition std_expr.h:2520
exprt & new_value()
Definition std_expr.h:2550
exprt & where()
Definition std_expr.h:2540
exprt & old()
Definition std_expr.h:2530
bool has_prefix(const std::string &s, const std::string &prefix)
Definition converter.cpp:13
int isdigit(int c)
Definition ctype.c:24
Forward depth-first search iterators These iterators' copy operations are expensive,...
exprt make_binary(const exprt &expr)
splits an expression with >=3 operands into nested binary expressions
Definition expr_util.cpp:38
Deprecated expression utility functions.
exprt float_bv(const exprt &src)
Definition float_bv.h:202
API to expression classes for floating-point arithmetic.
const ieee_float_op_exprt & to_ieee_float_op_expr(const exprt &expr)
Cast an exprt to an ieee_float_op_exprt.
const floatbv_fma_exprt & to_floatbv_fma_expr(const exprt &expr)
const floatbv_round_to_integral_exprt & to_floatbv_round_to_integral_expr(const exprt &expr)
Cast an exprt to a floatbv_round_to_integral_exprt.
const isnormal_exprt & to_isnormal_expr(const exprt &expr)
Cast an exprt to a isnormal_exprt.
const isinf_exprt & to_isinf_expr(const exprt &expr)
Cast an exprt to a isinf_exprt.
const isfinite_exprt & to_isfinite_expr(const exprt &expr)
Cast an exprt to a isfinite_exprt.
const isnan_exprt & to_isnan_expr(const exprt &expr)
Cast an exprt to a isnan_exprt.
const floatbv_typecast_exprt & to_floatbv_typecast_expr(const exprt &expr)
Cast an exprt to a floatbv_typecast_exprt.
static format_containert< T > format(const T &o)
Definition format.h:37
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
static std::string binary(const constant_exprt &src)
exprt to_expr(const namespacet &ns, const irep_idt &identifier, const std::string &src)
bool is_true(const literalt &l)
Definition literal.h:198
literalt const_literal(bool value)
Definition literal.h:188
literalt pos(literalt a)
Definition literal.h:194
const literal_exprt & to_literal_expr(const exprt &expr)
Cast a generic exprt to a literal_exprt.
double pow(double x, double y)
Definition math.c:3049
API to expression classes for 'mathematical' expressions.
const quantifier_exprt & to_quantifier_expr(const exprt &expr)
Cast an exprt to a quantifier_exprt.
const function_application_exprt & to_function_application_expr(const exprt &expr)
Cast an exprt to a function_application_exprt.
const integer_range_typet & to_integer_range_type(const typet &type)
Cast a typet to a integer_range_typet.
const mathematical_function_typet & to_mathematical_function_type(const typet &type)
Cast a typet to a mathematical_function_typet.
const mp_integer string2integer(const std::string &n, unsigned base)
Definition mp_arith.cpp:54
mp_integer bitwise_or(const mp_integer &a, const mp_integer &b)
bitwise 'or' of two nonnegative integers
Definition mp_arith.cpp:215
const std::string integer2binary(const mp_integer &n, std::size_t width)
Definition mp_arith.cpp:64
const element_address_exprt & to_element_address_expr(const exprt &expr)
Cast an exprt to an element_address_exprt.
const object_address_exprt & to_object_address_expr(const exprt &expr)
Cast an exprt to an object_address_exprt.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
const pointer_offset_exprt & to_pointer_offset_expr(const exprt &expr)
Cast an exprt to a pointer_offset_exprt.
const pointer_object_exprt & to_pointer_object_expr(const exprt &expr)
Cast an exprt to a pointer_object_exprt.
const field_address_exprt & to_field_address_expr(const exprt &expr)
Cast an exprt to an field_address_exprt.
std::optional< mp_integer > pointer_offset_size(const typet &type, const namespacet &ns)
Compute the size of a type in bytes, rounding up to full bytes.
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)
Tokenizer for the SMT-LIB v2.6 syntax.
void solver(std::vector< framet > &frames, const std::unordered_set< symbol_exprt, irep_hash > &address_taken, const solver_optionst &solver_options, const namespacet &ns, std::vector< propertyt > &properties, std::size_t property_index)
Definition solver.cpp:44
#define CHECK_RETURN(CONDITION)
Definition invariant.h:495
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define UNIMPLEMENTED
Definition invariant.h:558
#define INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Same as invariant, with one or more diagnostics attached Diagnostics can be of any type that has a sp...
Definition invariant.h:437
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
#define CHECK_RETURN_WITH_DIAGNOSTICS(CONDITION,...)
Definition invariant.h:496
#define DATA_INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Definition invariant.h:535
#define UNREACHABLE_BECAUSE(REASON)
Definition invariant.h:526
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition std_expr.cpp:291
API to expression classes.
const struct_exprt & to_struct_expr(const exprt &expr)
Cast an exprt to a struct_exprt.
Definition std_expr.h:1843
const array_of_exprt & to_array_of_expr(const exprt &expr)
Cast an exprt to an array_of_exprt.
Definition std_expr.h:1552
const binary_relation_exprt & to_binary_relation_expr(const exprt &expr)
Cast an exprt to a binary_relation_exprt.
Definition std_expr.h:828
const unary_plus_exprt & to_unary_plus_expr(const exprt &expr)
Cast an exprt to a unary_plus_exprt.
Definition std_expr.h:539
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1494
const mod_exprt & to_mod_expr(const exprt &expr)
Cast an exprt to a mod_exprt.
Definition std_expr.h:1260
const mult_exprt & to_mult_expr(const exprt &expr)
Cast an exprt to a mult_exprt.
Definition std_expr.h:1134
const array_comprehension_exprt & to_array_comprehension_expr(const exprt &expr)
Cast an exprt to a array_comprehension_exprt.
Definition std_expr.h:3648
const ternary_exprt & to_ternary_expr(const exprt &expr)
Cast an exprt to a ternary_exprt.
Definition std_expr.h:117
const named_term_exprt & to_named_term_expr(const exprt &expr)
Cast an exprt to a named_term_exprt.
Definition std_expr.h:3821
const cond_exprt & to_cond_expr(const exprt &expr)
Cast an exprt to a cond_exprt.
Definition std_expr.h:3443
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2024
const div_exprt & to_div_expr(const exprt &expr)
Cast an exprt to a div_exprt.
Definition std_expr.h:1196
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition std_expr.h:721
const plus_exprt & to_plus_expr(const exprt &expr)
Cast an exprt to a plus_exprt.
Definition std_expr.h:1045
const notequal_exprt & to_notequal_expr(const exprt &expr)
Cast an exprt to an notequal_exprt.
Definition std_expr.h:1413
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:424
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition std_expr.h:991
const let_exprt & to_let_expr(const exprt &expr)
Cast an exprt to a let_exprt.
Definition std_expr.h:3383
const abs_exprt & to_abs_expr(const exprt &expr)
Cast an exprt to a abs_exprt.
Definition std_expr.h:459
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition std_expr.h:2501
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:2953
const minus_exprt & to_minus_expr(const exprt &expr)
Cast an exprt to a minus_exprt.
Definition std_expr.h:1085
const union_exprt & to_union_expr(const exprt &expr)
Cast an exprt to a union_exprt.
Definition std_expr.h:1765
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3078
const not_exprt & to_not_expr(const exprt &expr)
Cast an exprt to an not_exprt.
Definition std_expr.h:2408
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:221
const with_exprt & to_with_expr(const exprt &expr)
Cast an exprt to a with_exprt.
Definition std_expr.h:2573
const implies_exprt & to_implies_expr(const exprt &expr)
Cast an exprt to a implies_exprt.
Definition std_expr.h:2174
const update_exprt & to_update_expr(const exprt &expr)
Cast an exprt to an update_exprt.
Definition std_expr.h:2762
const unary_minus_exprt & to_unary_minus_expr(const exprt &expr)
Cast an exprt to a unary_minus_exprt.
Definition std_expr.h:502
const equal_exprt & to_equal_expr(const exprt &expr)
Cast an exprt to an equal_exprt.
Definition std_expr.h:1375
const nondet_symbol_exprt & to_nondet_symbol_expr(const exprt &expr)
Cast an exprt to a nondet_symbol_exprt.
Definition std_expr.h:346
const sign_exprt & to_sign_expr(const exprt &expr)
Cast an exprt to a sign_exprt.
Definition std_expr.h:632
const euclidean_mod_exprt & to_euclidean_mod_expr(const exprt &expr)
Cast an exprt to a euclidean_mod_exprt.
Definition std_expr.h:1321
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:787
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:307
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition std_types.h:517
const complex_typet & to_complex_type(const typet &type)
Cast a typet to a complex_typet.
Definition std_types.h:1048
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:887
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition std_types.h:213
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