Skip to content

Commit 89d248e

Browse files
Merge pull request diffblue#4755 from romainbrenguier/unit/renaming_level
Clean-up and unit test the renaming level classes
2 parents 97457ea + 530c35b commit 89d248e

13 files changed

+419
-179
lines changed

src/goto-symex/frame.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct framet
3232
exprt return_value = nil_exprt();
3333
bool hidden_function = false;
3434

35-
symex_renaming_levelt::current_namest old_level1;
35+
symex_level1t old_level1;
3636

3737
std::set<irep_idt> local_objects;
3838

src/goto-symex/goto_symex_state.cpp

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -135,21 +135,22 @@ template <>
135135
renamedt<ssa_exprt, L0>
136136
goto_symex_statet::set_indices<L0>(ssa_exprt ssa_expr, const namespacet &ns)
137137
{
138-
return level0(std::move(ssa_expr), ns, source.thread_nr);
138+
return symex_level0(std::move(ssa_expr), ns, source.thread_nr);
139139
}
140140

141141
template <>
142142
renamedt<ssa_exprt, L1>
143143
goto_symex_statet::set_indices<L1>(ssa_exprt ssa_expr, const namespacet &ns)
144144
{
145-
return level1(level0(std::move(ssa_expr), ns, source.thread_nr));
145+
return level1(symex_level0(std::move(ssa_expr), ns, source.thread_nr));
146146
}
147147

148148
template <>
149149
renamedt<ssa_exprt, L2>
150150
goto_symex_statet::set_indices<L2>(ssa_exprt ssa_expr, const namespacet &ns)
151151
{
152-
return level2(level1(level0(std::move(ssa_expr), ns, source.thread_nr)));
152+
return level2(
153+
level1(symex_level0(std::move(ssa_expr), ns, source.thread_nr)));
153154
}
154155

155156
renamedt<ssa_exprt, L2> goto_symex_statet::assignment(
@@ -437,7 +438,7 @@ bool goto_symex_statet::l2_thread_read_encoding(
437438
if(a_s_read.second.empty())
438439
{
439440
increase_generation(l1_identifier, ssa_l1);
440-
a_s_read.first=level2.current_count(l1_identifier);
441+
a_s_read.first = level2.latest_index(l1_identifier);
441442
}
442443
const renamedt<ssa_exprt, L2> l2_false_case = set_indices<L2>(ssa_l1, ns);
443444

@@ -796,28 +797,18 @@ ssa_exprt goto_symex_statet::add_object(
796797
{
797798
framet &frame = call_stack().top();
798799

799-
ssa_exprt ssa = rename_ssa<L0>(ssa_exprt{expr}, ns).get();
800-
const irep_idt l0_name = ssa.get_identifier();
801-
const std::size_t l1_index = index_generator(l0_name);
800+
const renamedt<ssa_exprt, L0> renamed = rename_ssa<L0>(ssa_exprt{expr}, ns);
801+
const irep_idt l0_name = renamed.get_identifier();
802+
const auto l1_index = narrow_cast<unsigned>(index_generator(l0_name));
802803

803-
const auto r_opt = level1.current_names.find(l0_name);
804-
805-
if(!r_opt)
806-
{
807-
level1.current_names.insert(l0_name, std::make_pair(ssa, l1_index));
808-
}
809-
else
804+
if(const auto old_value = level1.insert_or_replace(renamed, l1_index))
810805
{
811806
// save old L1 name
812-
if(!frame.old_level1.has_key(l0_name))
813-
{
814-
frame.old_level1.insert(l0_name, r_opt->get());
815-
}
816-
817-
level1.current_names.replace(l0_name, std::make_pair(ssa, l1_index));
807+
if(!frame.old_level1.has(renamed))
808+
frame.old_level1.insert(renamed, old_value->second);
818809
}
819810

820-
ssa = rename_ssa<L1>(std::move(ssa), ns).get();
811+
const ssa_exprt ssa = rename_ssa<L1>(renamed.get(), ns).get();
821812
const bool inserted = frame.local_objects.insert(ssa.get_identifier()).second;
822813
INVARIANT(inserted, "l1_name expected to be unique by construction");
823814

src/goto-symex/goto_symex_state.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ class goto_symex_statet final : public goto_statet
7070
guard_managert &guard_manager;
7171
symex_target_equationt *symex_target;
7272

73-
symex_level0t level0;
7473
symex_level1t level1;
7574

7675
/// Rewrites symbol expressions in \ref exprt, applying a suffix to each

src/goto-symex/renamed.h

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*******************************************************************\
2+
3+
Module: Symbolic Execution
4+
5+
Author: Romain Brenguier, [email protected]
6+
7+
\*******************************************************************/
8+
/// \file
9+
/// Class for expressions or types renamed up to a given level
10+
11+
#ifndef CPROVER_GOTO_SYMEX_RENAMED_H
12+
#define CPROVER_GOTO_SYMEX_RENAMED_H
13+
14+
/// Symex renaming level names.
15+
enum levelt
16+
{
17+
L0 = 0,
18+
L1 = 1,
19+
L2 = 2
20+
};
21+
22+
/// Wrapper for expressions or types which have been renamed up to a given
23+
/// \p level
24+
template <typename underlyingt, levelt level>
25+
class renamedt : private underlyingt
26+
{
27+
public:
28+
static_assert(
29+
std::is_base_of<exprt, underlyingt>::value ||
30+
std::is_base_of<typet, underlyingt>::value,
31+
"underlyingt should inherit from exprt or typet");
32+
33+
const underlyingt &get() const
34+
{
35+
return static_cast<const underlyingt &>(*this);
36+
}
37+
38+
void simplify(const namespacet &ns)
39+
{
40+
(void)::simplify(value(), ns);
41+
}
42+
43+
using mutator_functiont =
44+
std::function<optionalt<renamedt>(const renamedt &)>;
45+
46+
private:
47+
underlyingt &value()
48+
{
49+
return static_cast<underlyingt &>(*this);
50+
};
51+
52+
friend renamedt<ssa_exprt, L0>
53+
symex_level0(ssa_exprt, const namespacet &, unsigned);
54+
friend struct symex_level1t;
55+
friend struct symex_level2t;
56+
friend class goto_symex_statet;
57+
58+
template <levelt make_renamed_level>
59+
friend renamedt<exprt, make_renamed_level>
60+
make_renamed(constant_exprt constant);
61+
62+
template <levelt selectively_mutate_level>
63+
friend void selectively_mutate(
64+
renamedt<exprt, selectively_mutate_level> &renamed,
65+
typename renamedt<exprt, selectively_mutate_level>::mutator_functiont
66+
get_mutated_expr);
67+
68+
/// Only the friend classes can create renamedt objects
69+
explicit renamedt(underlyingt value) : underlyingt(std::move(value))
70+
{
71+
}
72+
};
73+
74+
template <levelt level>
75+
renamedt<exprt, level> make_renamed(constant_exprt constant)
76+
{
77+
return renamedt<exprt, level>(std::move(constant));
78+
}
79+
80+
/// This permits replacing subexpressions of the renamed value, so long as
81+
/// each replacement is consistent with our current renaming level (for
82+
/// example, replacing subexpressions of L2 expressions with ones which are
83+
/// themselves L2 renamed).
84+
/// The passed function will be called with each expression node in preorder
85+
/// (i.e. parent expressions before children), and should return an empty
86+
/// optional to make no change or a renamed expression to make a change.
87+
template <levelt level>
88+
void selectively_mutate(
89+
renamedt<exprt, level> &renamed,
90+
typename renamedt<exprt, level>::mutator_functiont get_mutated_expr)
91+
{
92+
for(auto it = renamed.depth_begin(), itend = renamed.depth_end(); it != itend;
93+
++it)
94+
{
95+
optionalt<renamedt<exprt, level>> replacement =
96+
get_mutated_expr(static_cast<const renamedt<exprt, level> &>(*it));
97+
98+
if(replacement)
99+
it.mutate() = std::move(replacement->value());
100+
}
101+
}
102+
103+
#endif // CPROVER_GOTO_SYMEX_RENAMED_H

src/goto-symex/renaming_level.cpp

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,21 @@ Author: Romain Brenguier, [email protected]
1717

1818
#include "goto_symex_state.h"
1919

20-
renamedt<ssa_exprt, L0> symex_level0t::
21-
operator()(ssa_exprt ssa_expr, const namespacet &ns, unsigned thread_nr) const
20+
void get_variables(
21+
const symex_renaming_levelt &current_names,
22+
std::unordered_set<ssa_exprt, irep_hash> &vars)
23+
{
24+
symex_renaming_levelt::viewt view;
25+
current_names.get_view(view);
26+
27+
for(const auto &pair : view)
28+
{
29+
vars.insert(pair.second.first);
30+
}
31+
}
32+
33+
renamedt<ssa_exprt, L0>
34+
symex_level0(ssa_exprt ssa_expr, const namespacet &ns, unsigned thread_nr)
2235
{
2336
// already renamed?
2437
if(!ssa_expr.get_level_0().empty())
@@ -43,6 +56,33 @@ operator()(ssa_exprt ssa_expr, const namespacet &ns, unsigned thread_nr) const
4356
return renamedt<ssa_exprt, L0>{ssa_expr};
4457
}
4558

59+
void symex_level1t::insert(const renamedt<ssa_exprt, L0> &ssa, unsigned index)
60+
{
61+
current_names.insert(
62+
ssa.get().get_identifier(), std::make_pair(ssa.get(), index));
63+
}
64+
65+
optionalt<std::pair<ssa_exprt, unsigned>> symex_level1t::insert_or_replace(
66+
const renamedt<ssa_exprt, L0> &ssa,
67+
unsigned index)
68+
{
69+
const irep_idt &identifier = ssa.get().get_identifier();
70+
const auto old_value = current_names.find(identifier);
71+
if(old_value)
72+
{
73+
std::pair<ssa_exprt, unsigned> result = *old_value;
74+
current_names.replace(identifier, std::make_pair(ssa.get(), index));
75+
return result;
76+
}
77+
current_names.insert(identifier, std::make_pair(ssa.get(), index));
78+
return {};
79+
}
80+
81+
bool symex_level1t::has(const renamedt<ssa_exprt, L0> &ssa) const
82+
{
83+
return current_names.has_key(ssa.get().get_identifier());
84+
}
85+
4686
renamedt<ssa_exprt, L1> symex_level1t::
4787
operator()(renamedt<ssa_exprt, L0> l0_expr) const
4888
{
@@ -72,14 +112,14 @@ operator()(renamedt<ssa_exprt, L1> l1_expr) const
72112
{
73113
if(!l1_expr.get().get_level_2().empty())
74114
return renamedt<ssa_exprt, L2>{std::move(l1_expr.value())};
75-
l1_expr.value().set_level_2(current_count(l1_expr.get().get_identifier()));
115+
l1_expr.value().set_level_2(latest_index(l1_expr.get().get_identifier()));
76116
return renamedt<ssa_exprt, L2>{std::move(l1_expr.value())};
77117
}
78118

79-
void symex_level1t::restore_from(const current_namest &other)
119+
void symex_level1t::restore_from(const symex_level1t &other)
80120
{
81-
current_namest::delta_viewt delta_view;
82-
other.get_delta_view(current_names, delta_view, false);
121+
symex_renaming_levelt::delta_viewt delta_view;
122+
other.current_names.get_delta_view(current_names, delta_view, false);
83123

84124
for(const auto &delta_item : delta_view)
85125
{
@@ -97,6 +137,12 @@ void symex_level1t::restore_from(const current_namest &other)
97137
}
98138
}
99139

140+
unsigned symex_level2t::latest_index(const irep_idt &identifier) const
141+
{
142+
const auto r_opt = current_names.find(identifier);
143+
return !r_opt ? 0 : r_opt->get().second;
144+
}
145+
100146
exprt get_original_name(exprt expr)
101147
{
102148
expr.type() = get_original_name(std::move(expr.type()));

0 commit comments

Comments
 (0)