Skip to content

Commit e718a62

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 5c26898 commit e718a62

File tree

8 files changed

+76
-26
lines changed

8 files changed

+76
-26
lines changed

src/goto-instrument/accelerate/scratch_program.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ 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), global_map);
4041
symex.symex_with_state(
4142
*symex_state,
4243
[this](const irep_idt &key) -> const goto_functionst::goto_functiont & {

src/goto-symex/goto_symex_state.cpp

Lines changed: 49 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
call_stack().new_frame(source);
@@ -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
@@ -448,10 +452,7 @@ bool goto_symex_statet::l2_thread_read_encoding(
448452

449453
if(a_s_read.second.empty())
450454
{
451-
auto level2_it =
452-
level2.current_names.emplace(l1_identifier, std::make_pair(ssa_l1, 0))
453-
.first;
454-
symex_renaming_levelt::increase_counter(level2_it);
455+
increase_generation(l1_identifier, ssa_l1);
455456
a_s_read.first=level2.current_count(l1_identifier);
456457
}
457458

@@ -487,10 +488,6 @@ bool goto_symex_statet::l2_thread_read_encoding(
487488
return true;
488489
}
489490

490-
const auto level2_it =
491-
level2.current_names.emplace(l1_identifier, std::make_pair(ssa_l1, 0))
492-
.first;
493-
494491
// No event and no fresh index, but avoid constant propagation
495492
if(!record_events)
496493
{
@@ -500,7 +497,8 @@ bool goto_symex_statet::l2_thread_read_encoding(
500497
}
501498

502499
// produce a fresh L2 name
503-
symex_renaming_levelt::increase_counter(level2_it);
500+
increase_generation(l1_identifier, ssa_l1);
501+
504502
set_l2_indices(ssa_l1, ns);
505503
expr=ssa_l1;
506504

@@ -512,6 +510,43 @@ bool goto_symex_statet::l2_thread_read_encoding(
512510
return true;
513511
}
514512

513+
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
514+
/// latest generation on this path.
515+
void goto_symex_statet::increase_generation(
516+
const irep_idt l1_identifier,
517+
const ssa_exprt &lhs)
518+
{
519+
auto current_emplace_res =
520+
level2.current_names.emplace(l1_identifier, std::make_pair(lhs, 0));
521+
auto global_emplace_res =
522+
global_name_map.emplace(l1_identifier, std::make_pair(lhs, 0));
523+
524+
global_emplace_res.first->second.second++;
525+
current_emplace_res.first->second.second =
526+
global_emplace_res.first->second.second;
527+
}
528+
529+
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
530+
/// latest generation on this path. Does nothing if there isn't an expression
531+
/// keyed by the l1 identifier.
532+
void goto_symex_statet::increase_generation_if_exists(const irep_idt identifier)
533+
{
534+
// If we can't find the name in the local scope, don't increase the global
535+
// even if it exists there.
536+
auto current_names_iter = level2.current_names.find(identifier);
537+
if(current_names_iter == level2.current_names.end())
538+
return;
539+
540+
// If we have a global store, increment its generation count, then assign
541+
// that new value to our local scope.
542+
auto global_names_iter = global_name_map.find(identifier);
543+
if(global_names_iter != global_name_map.end())
544+
{
545+
global_names_iter->second.second++;
546+
current_names_iter->second.second = global_names_iter->second.second;
547+
}
548+
}
549+
515550
/// thread encoding
516551
bool goto_symex_statet::l2_thread_write_encoding(
517552
const ssa_exprt &expr,

src/goto-symex/goto_symex_state.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Author: Daniel Kroening, [email protected]
3030
#include "renaming_level.h"
3131
#include "symex_target_equation.h"
3232

33+
using global_name_mapt = std::map<irep_idt, std::pair<ssa_exprt, unsigned>>;
34+
3335
/// \brief Central data structure: state.
3436
///
3537
/// The state is a persistent data structure that symex maintains as it
@@ -41,7 +43,9 @@ Author: Daniel Kroening, [email protected]
4143
class goto_symex_statet final : public goto_statet
4244
{
4345
public:
44-
explicit goto_symex_statet(const symex_targett::sourcet &);
46+
goto_symex_statet(
47+
const symex_targett::sourcet &,
48+
global_name_mapt &global_map);
4549
~goto_symex_statet();
4650

4751
/// \brief Fake "copy constructor" that initializes the `symex_target` member
@@ -187,7 +191,17 @@ class goto_symex_statet final : public goto_statet
187191
/// \brief Should the additional validation checks be run?
188192
bool run_validation_checks;
189193

194+
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
195+
// latest generation on this path.
196+
void increase_generation(const irep_idt l1_identifier, const ssa_exprt &lhs);
197+
198+
/// Increases the generation of the L1 identifier. Does nothing if there
199+
/// isn't an expression keyed by it.
200+
void increase_generation_if_exists(const irep_idt identifier);
201+
190202
private:
203+
global_name_mapt &global_name_map;
204+
191205
/// \brief Dangerous, do not use
192206
///
193207
/// Copying a state S1 to S2 risks S2 pointing to a deallocated

src/goto-symex/path_storage.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ class path_storaget
9898
/// error-handling paths.
9999
std::unordered_map<irep_idt, local_safe_pointerst> safe_pointers;
100100

101+
/// Tracks fresh L2 names across an entire symex run. This will be shared
102+
/// across all states to allocate unique generations.
103+
global_name_mapt level2_names;
104+
101105
private:
102106
// Derived classes should override these methods, allowing the base class to
103107
// enforce preconditions.

src/goto-symex/renaming_level.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ operator()(renamedt<ssa_exprt, L1> l1_expr) const
6767
return renamedt<ssa_exprt, L2>{std::move(l1_expr.value)};
6868
}
6969

70-
void symex_level1t::restore_from(
71-
const symex_renaming_levelt::current_namest &other)
70+
void symex_level1t::restore_from(const current_namest &other)
7271
{
7372
auto it = current_names.begin();
7473
for(const auto &pair : other)

src/goto-symex/symex_dead.cpp

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

4949
// L2 renaming
50-
auto level2_it = state.level2.current_names.find(l1_identifier);
51-
if(level2_it != state.level2.current_names.end())
52-
symex_renaming_levelt::increase_counter(level2_it);
50+
state.increase_generation_if_exists(l1_identifier);
5351
}

src/goto-symex/symex_decl.cpp

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

src/goto-symex/symex_main.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,8 @@ std::unique_ptr<goto_symext::statet> goto_symext::initialize_entry_point_state(
317317

318318
// create and prepare the state
319319
auto state = util_make_unique<statet>(
320-
symex_targett::sourcet(entry_point_id, start_function->body));
320+
symex_targett::sourcet(entry_point_id, start_function->body),
321+
path_storage.level2_names);
321322
CHECK_RETURN(!state->threads.empty());
322323
CHECK_RETURN(!state->call_stack().empty());
323324

0 commit comments

Comments
 (0)