7
7
\*******************************************************************/
8
8
9
9
#include " goto_state.h"
10
+ #include " goto_symex_is_constant.h"
11
+ #include " goto_symex_state.h"
10
12
11
13
#include < util/format_expr.h>
12
14
@@ -20,3 +22,74 @@ void goto_statet::output_propagation_map(std::ostream &out)
20
22
out << name_value.first << " <- " << format (name_value.second ) << " \n " ;
21
23
}
22
24
}
25
+
26
+ std::size_t goto_statet::increase_generation (
27
+ const irep_idt l1_identifier,
28
+ const ssa_exprt &lhs,
29
+ std::function<std::size_t (const irep_idt &)> fresh_l2_name_provider)
30
+ {
31
+ auto current_emplace_res =
32
+ level2.current_names .emplace (l1_identifier, std::make_pair (lhs, 0 ));
33
+
34
+ current_emplace_res.first ->second .second =
35
+ fresh_l2_name_provider (l1_identifier);
36
+
37
+ return current_emplace_res.first ->second .second ;
38
+ }
39
+
40
+ // / Given a condition that must hold on this path, propagate as much knowledge
41
+ // / as possible. For example, if the condition is (x == 5), whether that's an
42
+ // / assumption or a GOTO condition that we just passed through, we can propagate
43
+ // / the constant '5' for future 'x' references. If the condition is (y == &o1)
44
+ // / then we can use that to populate the value set.
45
+ // / \param condition: condition that must hold on this path. Expected to already
46
+ // / be L2-renamed.
47
+ // / \param previous_state: currently active state, not necessarily the same as
48
+ // / *this. For a GOTO instruction this is the state immediately preceding the
49
+ // / branch while *this is the state that will be used on the taken- or
50
+ // / not-taken path. For an ASSUME instruction \p previous_state and *this are
51
+ // / equal.
52
+ // / \param ns: global namespace
53
+ void goto_statet::apply_condition (
54
+ const exprt &condition,
55
+ const goto_symex_statet &previous_state,
56
+ const namespacet &ns)
57
+ {
58
+ if (condition.id () == ID_and)
59
+ {
60
+ for (const auto &op : condition.operands ())
61
+ apply_condition (op, previous_state, ns);
62
+ }
63
+ else if (condition.id () == ID_equal)
64
+ {
65
+ exprt lhs = condition.op0 ();
66
+ exprt rhs = condition.op1 ();
67
+ if (is_ssa_expr (rhs))
68
+ std::swap (lhs, rhs);
69
+
70
+ if (is_ssa_expr (lhs) && goto_symex_is_constantt ()(rhs))
71
+ {
72
+ const ssa_exprt &ssa_lhs = to_ssa_expr (lhs);
73
+ INVARIANT (
74
+ !ssa_lhs.get_level_2 ().empty (),
75
+ " apply_condition operand should be L2 renamed" );
76
+
77
+ if (
78
+ previous_state.threads .size () == 1 ||
79
+ previous_state.write_is_shared (ssa_lhs, ns) !=
80
+ goto_symex_statet::write_is_shared_resultt::SHARED)
81
+ {
82
+ ssa_exprt l1_lhs = ssa_lhs;
83
+ l1_lhs.remove_level_2 ();
84
+ const irep_idt &l1_identifier = l1_lhs.get_identifier ();
85
+
86
+ increase_generation (
87
+ l1_identifier, l1_lhs, previous_state.get_l2_name_provider ());
88
+
89
+ propagation[l1_identifier] = rhs;
90
+
91
+ value_set.assign (l1_lhs, rhs, ns, true , false );
92
+ }
93
+ }
94
+ }
95
+ }
0 commit comments