Skip to content

Commit 1daa2c6

Browse files
committed
Use depth_begin() and depth_end() to selectively mutate renamed expressions
1 parent eb55978 commit 1daa2c6

File tree

2 files changed

+58
-89
lines changed

2 files changed

+58
-89
lines changed

src/goto-symex/renaming_level.h

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Author: Romain Brenguier, [email protected]
1515
#include <map>
1616
#include <unordered_set>
1717

18+
#include <util/expr_iterator.h>
1819
#include <util/irep.h>
1920
#include <util/range.h>
2021
#include <util/simplify_expr.h>
@@ -67,31 +68,6 @@ struct symex_renaming_levelt
6768
}
6869
};
6970

70-
template <typename underlyingt, levelt level>
71-
class renamedt;
72-
73-
template <typename underlyingt, levelt level>
74-
class renamed_vectort
75-
{
76-
public:
77-
void for_each(std::function<void(renamedt<underlyingt, level>&)> f)
78-
{
79-
for(auto &op : values)
80-
{
81-
auto op_as_renamed = renamedt<underlyingt, level>{op};
82-
f(op_as_renamed);
83-
op = op_as_renamed.value;
84-
}
85-
}
86-
87-
private:
88-
std::vector<underlyingt> &values;
89-
90-
explicit renamed_vectort(std::vector<underlyingt> &values) : values(values){};
91-
92-
friend renamedt<underlyingt, level>;
93-
};
94-
9571
/// Wrapper for expressions or types which have been renamed up to a given
9672
/// \p level
9773
template <typename underlyingt, levelt level>
@@ -108,19 +84,32 @@ class renamedt
10884
return value;
10985
}
11086

111-
renamed_vectort<underlyingt, level> operands()
112-
{
113-
return renamed_vectort<underlyingt, level>{value.operands()};
114-
};
115-
116-
const renamed_vectort<underlyingt, level> operands() const
87+
void simplify(const namespacet &ns)
11788
{
118-
return renamed_vectort<underlyingt, level>{value.operands()};
89+
(void)::simplify(value, ns);
11990
}
12091

121-
void simplify(const namespacet &ns)
92+
typedef std::function<optionalt<renamedt<exprt, level>>(const exprt &)>
93+
expr_mutator_functiont;
94+
95+
/// This permits replacing subexpressions of the renamed value, so long as
96+
/// each replacement is consistent with our current renaming level (for
97+
/// example, replacing subexpressions of L2 expressions with ones which are
98+
/// themselves L2 renamed).
99+
/// The passed function will be called with each expression node in preorder
100+
/// (i.e. parent expressions before children), and should return an empty
101+
/// optional to make no change or a renamed expression to make a change.
102+
void selectively_mutate(expr_mutator_functiont get_mutated_expr)
122103
{
123-
(void)::simplify(value, ns);
104+
for(
105+
auto it = value.depth_begin(), itend = value.depth_end();
106+
it != itend;
107+
++it)
108+
{
109+
auto replacement = get_mutated_expr(*it);
110+
if(replacement)
111+
it.mutate() = replacement->get();
112+
}
124113
}
125114

126115
private:
@@ -130,7 +119,6 @@ class renamedt
130119
friend struct symex_level1t;
131120
friend struct symex_level2t;
132121
friend class goto_symex_statet;
133-
friend renamed_vectort<underlyingt, level>;
134122
template <levelt make_renamed_level>
135123
friend renamedt<exprt, make_renamed_level> make_renamed(constant_exprt constant);
136124

src/goto-symex/symex_goto.cpp

Lines changed: 35 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,9 @@ void goto_symext::apply_goto_condition(
7979
/// \param value_set: The value-set for looking up what the symbol can point to
8080
/// \param language_mode: The language mode
8181
/// \param ns: A namespace
82-
static void try_evaluate_pointer_comparisons_base_case(
83-
renamedt<exprt, L2> &condition,
82+
static optionalt<renamedt<exprt, L2>>
83+
try_evaluate_pointer_comparison(
84+
irep_idt operation,
8485
const symbol_exprt &symbol_expr,
8586
const exprt &other_operand,
8687
const value_sett &value_set,
@@ -116,7 +117,7 @@ static void try_evaluate_pointer_comparisons_base_case(
116117
{
117118
// If ID_unknown or ID_invalid are in the value-set then we can't
118119
// conclude anything about it
119-
return;
120+
return {};
120121
}
121122

122123
if(!constant_found)
@@ -142,20 +143,22 @@ static void try_evaluate_pointer_comparisons_base_case(
142143
{
143144
// The symbol cannot possibly have the value \p other_operand because it
144145
// isn't in the symbol's value-set
145-
condition = condition.get().id() == ID_equal ? make_renamed<L2>(false_exprt{})
146-
: make_renamed<L2>(true_exprt{});
146+
return operation == ID_equal ? make_renamed<L2>(false_exprt{})
147+
: make_renamed<L2>(true_exprt{});
147148
}
148149
else if(value_set_elements.size() == 1)
149150
{
150151
// The symbol must have the value \p other_operand because it is the only
151152
// thing in the symbol's value-set
152-
condition = condition.get().id() == ID_equal ? make_renamed<L2>(true_exprt{})
153-
: make_renamed<L2>(false_exprt{});
153+
return operation == ID_equal ? make_renamed<L2>(true_exprt{})
154+
: make_renamed<L2>(false_exprt{});
155+
}
156+
else
157+
{
158+
return {};
154159
}
155160
}
156161

157-
158-
159162
/// Check if we have a simple pointer comparison, and if so try to evaluate it.
160163
/// \param [in,out] condition: An L2- renamed expression of the form
161164
/// "symbol_expr == other" or "symbol_expr != other" (or one of those with
@@ -168,30 +171,34 @@ static void try_evaluate_pointer_comparisons_base_case(
168171
/// \param value_set: The value-set for looking up what the symbol can point to
169172
/// \param language_mode: The language mode
170173
/// \param ns: A namespace
171-
static bool try_evaluate_pointer_comparisons_base_case_with_check(
172-
renamedt<exprt, L2> &condition,
173-
const exprt &symbol_expr,
174-
const exprt &other_operand,
174+
static optionalt<renamedt<exprt, L2>>
175+
try_evaluate_pointer_comparison(
176+
const exprt &expr,
175177
const value_sett &value_set,
176178
const irep_idt language_mode,
177179
const namespacet &ns)
178180
{
181+
if(expr.id() != ID_equal && expr.id() != ID_notequal)
182+
return {};
183+
184+
if(!can_cast_type<pointer_typet>(expr.op0().type()))
185+
return {};
186+
187+
exprt lhs = expr.op0(), rhs = expr.op1();
188+
if(can_cast_expr<symbol_exprt>(rhs))
189+
std::swap(lhs, rhs);
190+
179191
const symbol_exprt *symbol_expr_lhs =
180-
expr_try_dynamic_cast<symbol_exprt>(symbol_expr);
192+
expr_try_dynamic_cast<symbol_exprt>(lhs);
181193

182194
if(!symbol_expr_lhs)
183-
{
184-
return false;
185-
}
195+
return {};
186196

187-
if(!goto_symex_is_constantt()(other_operand))
188-
{
189-
return false;
190-
}
197+
if(!goto_symex_is_constantt()(rhs))
198+
return {};
191199

192-
try_evaluate_pointer_comparisons_base_case(
193-
condition, *symbol_expr_lhs, other_operand, value_set, language_mode, ns);
194-
return true;
200+
return try_evaluate_pointer_comparison(
201+
expr.id(), *symbol_expr_lhs, rhs, value_set, language_mode, ns);
195202
}
196203

197204
/// Try to evaluate pointer comparisons where they can be trivially determined
@@ -208,37 +215,11 @@ static renamedt<exprt, L2> try_evaluate_pointer_comparisons(
208215
const irep_idt language_mode,
209216
const namespacet &ns)
210217
{
211-
const exprt &condition_expr = condition.get();
212-
if(condition_expr.id() == ID_equal || condition_expr.id() == ID_notequal)
213-
{
214-
if(can_cast_type<pointer_typet>(condition_expr.op0().type()))
215-
{
216-
// Check if this is the form "symbol rel constant" or "constant rel symbol"
217-
if(!try_evaluate_pointer_comparisons_base_case_with_check(
218-
condition,
219-
condition_expr.op0(),
220-
condition_expr.op1(),
221-
value_set,
222-
language_mode,
223-
ns))
224-
{
225-
try_evaluate_pointer_comparisons_base_case_with_check(
226-
condition,
227-
condition_expr.op1(),
228-
condition_expr.op0(),
229-
value_set,
230-
language_mode,
231-
ns);
232-
}
233-
}
234-
}
235-
else
236-
{
237-
condition.operands().for_each([&](renamedt<exprt, L2> &op) {
238-
op = try_evaluate_pointer_comparisons(
239-
std::move(op), value_set, language_mode, ns);
218+
condition.selectively_mutate(
219+
[&value_set, &language_mode, &ns](const exprt &expr) {
220+
return try_evaluate_pointer_comparison(
221+
expr, value_set, language_mode, ns);
240222
});
241-
}
242223

243224
return condition;
244225
}

0 commit comments

Comments
 (0)