Skip to content

Commit 4fa79ae

Browse files
committed
Add global name map to goto_symex_state
This global name map will be used to check what generation is currently available for each level1 name, and shared across all states. This will only be used when a particular state tries to find out what the next free generation is. The main draw of this is that all branches will now assign unique generations that won't clash with assignments done across other branches. One minor downside is that in VCC's the generation number might jump sporadically (say from diffblue#4 to diffblue#40).
1 parent fa9487f commit 4fa79ae

9 files changed

+84
-26
lines changed

src/goto-instrument/accelerate/scratch_program.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ bool scratch_programt::check_sat(bool do_slice)
3535
output(ns, "scratch", std::cout);
3636
#endif
3737

38+
global_name_mapt global_map;
3839
symex_state = util_make_unique<goto_symex_statet>(
39-
symex_targett::sourcet(goto_functionst::entry_point(), *this));
40+
symex_targett::sourcet(goto_functionst::entry_point(), *this),
41+
global_map);
4042
symex.symex_with_state(
4143
*symex_state,
4244
[this](const irep_idt &key) -> const goto_functionst::goto_functiont & {

src/goto-symex/goto_symex_state.cpp

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,14 @@ Author: Daniel Kroening, [email protected]
2929

3030
static void get_l1_name(exprt &expr);
3131

32-
goto_symex_statet::goto_symex_statet(const symex_targett::sourcet &_source)
33-
: goto_statet(_source), symex_target(nullptr), record_events(true), dirty()
32+
goto_symex_statet::goto_symex_statet(
33+
const symex_targett::sourcet &_source,
34+
global_name_mapt &global_map)
35+
: goto_statet(_source),
36+
symex_target(nullptr),
37+
record_events(true),
38+
dirty(),
39+
global_name_map(global_map)
3440
{
3541
threads.resize(1);
3642
new_frame();
@@ -183,9 +189,7 @@ void goto_symex_statet::assignment(
183189
#endif
184190

185191
// do the l2 renaming
186-
const auto level2_it =
187-
level2.current_names.emplace(l1_identifier, std::make_pair(lhs, 0)).first;
188-
symex_renaming_levelt::increase_counter(level2_it);
192+
increase_generation(l1_identifier, lhs);
189193
set_l2_indices(lhs, ns);
190194

191195
// in case we happen to be multi-threaded, record the memory access
@@ -433,10 +437,7 @@ bool goto_symex_statet::l2_thread_read_encoding(
433437

434438
if(a_s_read.second.empty())
435439
{
436-
auto level2_it =
437-
level2.current_names.emplace(l1_identifier, std::make_pair(ssa_l1, 0))
438-
.first;
439-
symex_renaming_levelt::increase_counter(level2_it);
440+
increase_generation(l1_identifier, ssa_l1);
440441
a_s_read.first=level2.current_count(l1_identifier);
441442
}
442443

@@ -472,10 +473,6 @@ bool goto_symex_statet::l2_thread_read_encoding(
472473
return true;
473474
}
474475

475-
const auto level2_it =
476-
level2.current_names.emplace(l1_identifier, std::make_pair(ssa_l1, 0))
477-
.first;
478-
479476
// No event and no fresh index, but avoid constant propagation
480477
if(!record_events)
481478
{
@@ -485,7 +482,8 @@ bool goto_symex_statet::l2_thread_read_encoding(
485482
}
486483

487484
// produce a fresh L2 name
488-
symex_renaming_levelt::increase_counter(level2_it);
485+
increase_generation(l1_identifier, ssa_l1);
486+
489487
set_l2_indices(ssa_l1, ns);
490488
expr=ssa_l1;
491489

@@ -497,6 +495,44 @@ bool goto_symex_statet::l2_thread_read_encoding(
497495
return true;
498496
}
499497

498+
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
499+
/// latest generation on this path.
500+
void goto_symex_statet::increase_generation(
501+
const irep_idt l1_identifier,
502+
const ssa_exprt &lhs)
503+
{
504+
auto current_emplace_res =
505+
level2.current_names.emplace(l1_identifier, std::make_pair(lhs, 0));
506+
auto global_emplace_res =
507+
global_name_map.emplace(l1_identifier, std::make_pair(lhs, 0));
508+
509+
global_emplace_res.first->second.second++;
510+
current_emplace_res.first->second.second =
511+
global_emplace_res.first->second.second;
512+
}
513+
514+
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
515+
/// latest generation on this path. Does nothing if there isn't an expression
516+
/// keyed by the l1 identifier.
517+
void goto_symex_statet::increase_generation_if_exists(
518+
const irep_idt identifier)
519+
{
520+
// If we can't find the name in the local scope, don't increase the global
521+
// even if it exists there.
522+
auto current_names_iter = level2.current_names.find(identifier);
523+
if(current_names_iter == level2.current_names.end())
524+
return;
525+
526+
// If we have a global store, increment its generation count, then assign
527+
// that new value to our local scope.
528+
auto global_names_iter = global_name_map.find(identifier);
529+
if(global_names_iter != global_name_map.end())
530+
{
531+
global_names_iter->second.second++;
532+
current_names_iter->second.second = global_names_iter->second.second;
533+
}
534+
}
535+
500536
/// thread encoding
501537
bool goto_symex_statet::l2_thread_write_encoding(
502538
const ssa_exprt &expr,

src/goto-symex/goto_symex_state.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ struct framet
135135
}
136136
};
137137

138+
using global_name_mapt = std::map<irep_idt, std::pair<ssa_exprt, unsigned>>;
139+
138140
/// Central data structure: state.
139141

140142
/// The state is a persistent data structure that symex maintains as it
@@ -146,7 +148,9 @@ struct framet
146148
class goto_symex_statet final : public goto_statet
147149
{
148150
public:
149-
explicit goto_symex_statet(const symex_targett::sourcet &);
151+
goto_symex_statet(
152+
const symex_targett::sourcet &,
153+
global_name_mapt &global_map);
150154
~goto_symex_statet();
151155

152156
/// \brief Fake "copy constructor" that initializes the `symex_target` member
@@ -317,6 +321,19 @@ class goto_symex_statet final : public goto_statet
317321
/// \brief Should the additional validation checks be run?
318322
bool run_validation_checks;
319323

324+
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
325+
// latest generation on this path.
326+
void increase_generation(
327+
const irep_idt l1_identifier,
328+
const ssa_exprt &lhs);
329+
330+
/// Increases the generation of the L1 identifier. Does nothing if there
331+
/// isn't an expression keyed by it.
332+
void increase_generation_if_exists(
333+
const irep_idt identifier);
334+
335+
global_name_mapt &global_name_map;
336+
320337
private:
321338
/// \brief Dangerous, do not use
322339
///

src/goto-symex/path_storage.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ class path_storaget
9090
/// Counter for nondet objects, which require unique names
9191
symex_nondet_generatort build_symex_nondet;
9292

93+
using global_name_mapt = std::map<irep_idt, std::pair<ssa_exprt, unsigned>>;
94+
95+
/// Tracks fresh L2 names across an entire symex run. This will be shared
96+
/// across all states to allocate unique generations.
97+
global_name_mapt level2_names;
98+
9399
private:
94100
// Derived classes should override these methods, allowing the base class to
95101
// enforce preconditions.

src/goto-symex/renaming_level.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ void symex_level1t::operator()(ssa_exprt &ssa_expr) const
5858
ssa_expr.set_level_1(it->second.second);
5959
}
6060

61-
void symex_level1t::restore_from(
62-
const symex_renaming_levelt::current_namest &other)
61+
void symex_level1t::restore_from(const current_namest &other)
6362
{
6463
auto it = current_names.begin();
6564
for(const auto &pair : other)

src/goto-symex/renaming_level.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Author: Romain Brenguier, [email protected]
1818
#include <util/irep.h>
1919
#include <util/ssa_expr.h>
2020

21+
class path_storaget;
22+
2123
/// Wrapper for a \c current_names map, which maps each identifier to an SSA
2224
/// expression and a counter.
2325
/// This is extended by the different symex_level structures which are used

src/goto-symex/symex_dead.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,5 @@ void goto_symext::symex_dead(statet &state)
4949
state.propagation.erase(l1_identifier);
5050

5151
// L2 renaming
52-
auto level2_it = state.level2.current_names.find(l1_identifier);
53-
if(level2_it != state.level2.current_names.end())
54-
symex_renaming_levelt::increase_counter(level2_it);
52+
state.increase_generation_if_exists(l1_identifier);
5553
}

src/goto-symex/symex_decl.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,8 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
6464
// L2 renaming
6565
// inlining may yield multiple declarations of the same identifier
6666
// within the same L1 context
67-
const auto level2_it =
68-
state.level2.current_names.emplace(l1_identifier, std::make_pair(ssa, 0))
69-
.first;
70-
symex_renaming_levelt::increase_counter(level2_it);
67+
state.increase_generation(l1_identifier, ssa);
68+
7169
const bool record_events=state.record_events;
7270
state.record_events=false;
7371
state.rename(ssa, ns);

src/goto-symex/symex_main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ std::unique_ptr<goto_symext::statet> goto_symext::initialize_entry_point_state(
294294

295295
// create and prepare the state
296296
auto state = util_make_unique<statet>(
297-
symex_targett::sourcet(entry_point_id, start_function->body));
297+
symex_targett::sourcet(entry_point_id, start_function->body), path_storage.level2_names);
298298
CHECK_RETURN(!state->threads.empty());
299299
CHECK_RETURN(!state->call_stack().empty());
300300

0 commit comments

Comments
 (0)