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