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