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