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