CBMC
goto_state.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Symbolic Execution
4 
5 Author: Romain Brenguier, romain.brenguier@diffblue.com
6 
7 \*******************************************************************/
8 
9 #include "goto_state.h"
10 
11 #include <util/format_expr.h>
12 
14 #include "goto_symex_state.h"
15 
19 void goto_statet::output_propagation_map(std::ostream &out)
20 {
22  propagation.get_view(view);
23 
24  for(const auto &name_value : view)
25  {
26  out << name_value.first << " <- " << format(name_value.second) << "\n";
27  }
28 }
29 
44  const exprt &condition,
45  const goto_symex_statet &previous_state,
46  const namespacet &ns)
47 {
48  if(auto and_expr = expr_try_dynamic_cast<and_exprt>(condition))
49  {
50  // A == B && C == D && E == F ...
51  // -->
52  // Apply each condition individually
53  for(const auto &op : and_expr->operands())
54  apply_condition(op, previous_state, ns);
55  }
56  else if(auto not_expr = expr_try_dynamic_cast<not_exprt>(condition))
57  {
58  const exprt &operand = not_expr->op();
59  if(auto notequal_expr = expr_try_dynamic_cast<notequal_exprt>(operand))
60  {
61  // !(A != B)
62  // -->
63  // A == B
65  equal_exprt{notequal_expr->lhs(), notequal_expr->rhs()},
66  previous_state,
67  ns);
68  }
69  else if(auto equal_expr = expr_try_dynamic_cast<equal_exprt>(operand))
70  {
71  // !(A == B)
72  // -->
73  // A != B
75  notequal_exprt{equal_expr->lhs(), equal_expr->rhs()},
76  previous_state,
77  ns);
78  }
79  else
80  {
81  // !A
82  // -->
83  // A == false
84  apply_condition(equal_exprt{operand, false_exprt{}}, previous_state, ns);
85  }
86  }
87  else if(auto equal_expr = expr_try_dynamic_cast<equal_exprt>(condition))
88  {
89  // Base case: try to apply a single equality constraint
90  exprt lhs = equal_expr->lhs();
91  exprt rhs = equal_expr->rhs();
92  if(is_ssa_expr(rhs))
93  std::swap(lhs, rhs);
94 
96  {
97  const ssa_exprt &ssa_lhs = to_ssa_expr(lhs);
98  INVARIANT(
99  !ssa_lhs.get_level_2().empty(),
100  "apply_condition operand should be L2 renamed");
101 
102  if(
103  previous_state.threads.size() == 1 ||
104  previous_state.write_is_shared(ssa_lhs, ns) !=
106  {
107  const ssa_exprt l1_lhs = remove_level_2(ssa_lhs);
108  const irep_idt &l1_identifier = l1_lhs.get_identifier();
109 
111  l1_identifier, l1_lhs, previous_state.get_l2_name_provider());
112 
113  const auto propagation_entry = propagation.find(l1_identifier);
114  if(!propagation_entry.has_value())
115  propagation.insert(l1_identifier, rhs);
116  else if(propagation_entry->get() != rhs)
117  propagation.replace(l1_identifier, rhs);
118 
119  value_set.assign(l1_lhs, rhs, ns, true, false);
120  }
121  }
122  }
123  else if(
124  can_cast_expr<symbol_exprt>(condition) && condition.type() == bool_typet())
125  {
126  // A
127  // -->
128  // A == true
129  apply_condition(equal_exprt{condition, true_exprt()}, previous_state, ns);
130  }
131  else if(
132  can_cast_expr<notequal_exprt>(condition) &&
133  expr_checked_cast<notequal_exprt>(condition).lhs().type() == bool_typet{})
134  {
135  // A != (true|false)
136  // -->
137  // A == (false|true)
138  const notequal_exprt &notequal_expr =
139  expr_dynamic_cast<notequal_exprt>(condition);
140  exprt lhs = notequal_expr.lhs();
141  exprt rhs = notequal_expr.rhs();
142  if(is_ssa_expr(rhs))
143  std::swap(lhs, rhs);
144 
145  if(!is_ssa_expr(lhs) || !goto_symex_can_forward_propagatet(ns)(rhs))
146  return;
147 
148  if(rhs.is_true())
149  apply_condition(equal_exprt{lhs, false_exprt{}}, previous_state, ns);
150  else if(rhs.is_false())
151  apply_condition(equal_exprt{lhs, true_exprt{}}, previous_state, ns);
152  else
153  UNREACHABLE;
154  }
155 }
exprt & lhs()
Definition: std_expr.h:668
exprt & rhs()
Definition: std_expr.h:678
The Boolean type.
Definition: std_types.h:36
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
Base class for all expressions.
Definition: expr.h:56
bool is_true() const
Return whether the expression is a constant representing true.
Definition: expr.cpp:27
bool is_false() const
Return whether the expression is a constant representing false.
Definition: expr.cpp:34
typet & type()
Return the type of the expression.
Definition: expr.h:84
The Boolean constant false.
Definition: std_expr.h:3064
symex_level2t level2
Definition: goto_state.h:38
void apply_condition(const exprt &condition, const goto_symex_statet &previous_state, const namespacet &ns)
Given a condition that must hold on this path, propagate as much knowledge as possible.
Definition: goto_state.cpp:43
sharing_mapt< irep_idt, exprt > propagation
Definition: goto_state.h:71
value_sett value_set
Uses level 1 names, and is used to do dereferencing.
Definition: goto_state.h:51
void output_propagation_map(std::ostream &)
Print the constant propagation map in a human-friendly format.
Definition: goto_state.cpp:19
Central data structure: state.
write_is_shared_resultt write_is_shared(const ssa_exprt &expr, const namespacet &ns) const
std::function< std::size_t(const irep_idt &)> get_l2_name_provider() const
std::vector< threadt > threads
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
Disequality.
Definition: std_expr.h:1420
std::vector< view_itemt > viewt
View of the key-value pairs in the map.
Definition: sharing_map.h:388
Expression providing an SSA-renamed symbol of expressions.
Definition: ssa_expr.h:17
const irep_idt get_level_2() const
Definition: ssa_expr.h:73
const irep_idt & get_identifier() const
Definition: std_expr.h:160
The Boolean constant true.
Definition: std_expr.h:3055
void assign(const exprt &lhs, const exprt &rhs, const namespacet &ns, bool is_simplified, bool add_to_sets)
Transforms this value-set by executing executing the assignment lhs := rhs against it.
Definition: value_set.cpp:1465
static format_containert< T > format(const T &o)
Definition: format.h:37
goto_statet class definition
GOTO Symex constant propagation.
Symbolic Execution.
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:525
const ssa_exprt & to_ssa_expr(const exprt &expr)
Cast a generic exprt to an ssa_exprt.
Definition: ssa_expr.h:145
bool is_ssa_expr(const exprt &expr)
Definition: ssa_expr.h:125
ssa_exprt remove_level_2(ssa_exprt ssa)
bool can_cast_expr< notequal_exprt >(const exprt &base)
Definition: std_expr.h:1429
bool can_cast_expr< symbol_exprt >(const exprt &base)
Definition: std_expr.h:256
std::size_t increase_generation(const irep_idt &l1_identifier, const ssa_exprt &lhs, std::function< std::size_t(const irep_idt &)> fresh_l2_name_provider)
Allocates a fresh L2 name for the given L1 identifier, and makes it the latest generation on this pat...