Skip to content

Commit 743bcd3

Browse files
JohnDumbellsmowton
authored andcommitted
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 e1a7eb3 commit 743bcd3

10 files changed

+91
-33
lines changed

src/goto-instrument/accelerate/scratch_program.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@ bool scratch_programt::check_sat(bool do_slice, guard_managert &guard_manager)
3737

3838
symex_state = util_make_unique<goto_symex_statet>(
3939
symex_targett::sourcet(goto_functionst::entry_point(), *this),
40-
guard_manager);
40+
guard_manager,
41+
[this](const irep_idt &id)
42+
{
43+
return path_storage.get_unique_l2_index(id);
44+
});
45+
4146
symex.symex_with_state(
4247
*symex_state,
4348
[this](const irep_idt &key) -> const goto_functionst::goto_functiont & {

src/goto-symex/goto_symex_state.cpp

+33-14
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@ static void get_l1_name(exprt &expr);
3131

3232
goto_symex_statet::goto_symex_statet(
3333
const symex_targett::sourcet &_source,
34-
guard_managert &manager)
34+
guard_managert &manager,
35+
std::function<std::size_t(const irep_idt &)> fresh_l2_name_provider)
3536
: goto_statet(_source, manager),
3637
guard_manager(manager),
3738
symex_target(nullptr),
3839
record_events(true),
39-
dirty()
40+
dirty(),
41+
fresh_l2_name_provider(fresh_l2_name_provider)
4042
{
4143
threads.emplace_back(guard_manager);
4244
call_stack().new_frame(source);
@@ -212,9 +214,7 @@ void goto_symex_statet::assignment(
212214
#endif
213215

214216
// do the l2 renaming
215-
const auto level2_it =
216-
level2.current_names.emplace(l1_identifier, std::make_pair(lhs, 0)).first;
217-
symex_renaming_levelt::increase_counter(level2_it);
217+
increase_generation(l1_identifier, lhs);
218218
lhs = set_indices<L2>(std::move(lhs), ns).get();
219219

220220
// in case we happen to be multi-threaded, record the memory access
@@ -439,10 +439,7 @@ bool goto_symex_statet::l2_thread_read_encoding(
439439

440440
if(a_s_read.second.empty())
441441
{
442-
auto level2_it =
443-
level2.current_names.emplace(l1_identifier, std::make_pair(ssa_l1, 0))
444-
.first;
445-
symex_renaming_levelt::increase_counter(level2_it);
442+
increase_generation(l1_identifier, ssa_l1);
446443
a_s_read.first=level2.current_count(l1_identifier);
447444
}
448445
const renamedt<ssa_exprt, L2> l2_false_case = set_indices<L2>(ssa_l1, ns);
@@ -476,10 +473,6 @@ bool goto_symex_statet::l2_thread_read_encoding(
476473
return true;
477474
}
478475

479-
const auto level2_it =
480-
level2.current_names.emplace(l1_identifier, std::make_pair(ssa_l1, 0))
481-
.first;
482-
483476
// No event and no fresh index, but avoid constant propagation
484477
if(!record_events)
485478
{
@@ -488,7 +481,7 @@ bool goto_symex_statet::l2_thread_read_encoding(
488481
}
489482

490483
// produce a fresh L2 name
491-
symex_renaming_levelt::increase_counter(level2_it);
484+
increase_generation(l1_identifier, ssa_l1);
492485
expr = set_indices<L2>(std::move(ssa_l1), ns).get();
493486

494487
// and record that
@@ -499,6 +492,32 @@ bool goto_symex_statet::l2_thread_read_encoding(
499492
return true;
500493
}
501494

495+
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
496+
/// latest generation on this path.
497+
void goto_symex_statet::increase_generation(
498+
const irep_idt l1_identifier,
499+
const ssa_exprt &lhs)
500+
{
501+
auto current_emplace_res =
502+
level2.current_names.emplace(l1_identifier, std::make_pair(lhs, 0));
503+
504+
current_emplace_res.first->second.second =
505+
fresh_l2_name_provider(l1_identifier);
506+
}
507+
508+
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
509+
/// latest generation on this path. Does nothing if there isn't an expression
510+
/// keyed by the l1 identifier.
511+
void goto_symex_statet::increase_generation_if_exists(const irep_idt identifier)
512+
{
513+
// If we can't find the name in the local scope, this is a no-op.
514+
auto current_names_iter = level2.current_names.find(identifier);
515+
if(current_names_iter == level2.current_names.end())
516+
return;
517+
518+
current_names_iter->second.second = fresh_l2_name_provider(identifier);
519+
}
520+
502521
/// thread encoding
503522
bool goto_symex_statet::l2_thread_write_encoding(
504523
const ssa_exprt &expr,

src/goto-symex/goto_symex_state.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ Author: Daniel Kroening, [email protected]
4141
class goto_symex_statet final : public goto_statet
4242
{
4343
public:
44-
goto_symex_statet(const symex_targett::sourcet &, guard_managert &manager);
44+
goto_symex_statet(
45+
const symex_targett::sourcet &,
46+
guard_managert &manager,
47+
std::function<std::size_t(const irep_idt &)> fresh_l2_name_provider);
4548
~goto_symex_statet();
4649

4750
/// \brief Fake "copy constructor" that initializes the `symex_target` member
@@ -190,7 +193,17 @@ class goto_symex_statet final : public goto_statet
190193
/// \brief Should the additional validation checks be run?
191194
bool run_validation_checks;
192195

196+
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
197+
// latest generation on this path.
198+
void increase_generation(const irep_idt l1_identifier, const ssa_exprt &lhs);
199+
200+
/// Increases the generation of the L1 identifier. Does nothing if there
201+
/// isn't an expression keyed by it.
202+
void increase_generation_if_exists(const irep_idt identifier);
203+
193204
private:
205+
std::function<std::size_t(const irep_idt &)> fresh_l2_name_provider;
206+
194207
/// \brief Dangerous, do not use
195208
///
196209
/// Copying a state S1 to S2 risks S2 pointing to a deallocated

src/goto-symex/path_storage.h

+25-8
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,16 @@ class path_storaget
9898
/// error-handling paths.
9999
std::unordered_map<irep_idt, local_safe_pointerst> safe_pointers;
100100

101-
/// Provide a unique index for a given \p id, starting from \p minimum_index.
102-
std::size_t get_unique_index(const irep_idt &id, std::size_t minimum_index)
101+
/// Provide a unique L1 index for a given \p id, starting from
102+
/// \p minimum_index.
103+
std::size_t get_unique_l1_index(const irep_idt &id, std::size_t minimum_index)
103104
{
104-
auto entry = unique_index_map.emplace(id, minimum_index);
105-
106-
if(!entry.second)
107-
entry.first->second = std::max(entry.first->second + 1, minimum_index);
105+
return get_unique_index(l1_indices, id, minimum_index);
106+
}
108107

109-
return entry.first->second;
108+
std::size_t get_unique_l2_index(const irep_idt &id)
109+
{
110+
return get_unique_index(l2_indices, id, 1);
110111
}
111112

112113
private:
@@ -115,8 +116,24 @@ class path_storaget
115116
virtual patht &private_peek() = 0;
116117
virtual void private_pop() = 0;
117118

119+
typedef std::unordered_map<irep_idt, std::size_t> name_index_mapt;
120+
121+
std::size_t get_unique_index(
122+
name_index_mapt &unique_index_map,
123+
const irep_idt &id,
124+
std::size_t minimum_index)
125+
{
126+
auto entry = unique_index_map.emplace(id, minimum_index);
127+
128+
if(!entry.second)
129+
entry.first->second = std::max(entry.first->second + 1, minimum_index);
130+
131+
return entry.first->second;
132+
}
133+
118134
/// Storage used by \ref get_unique_index.
119-
std::unordered_map<irep_idt, std::size_t> unique_index_map;
135+
name_index_mapt l1_indices;
136+
name_index_mapt l2_indices;
120137
};
121138

122139
/// \brief LIFO save queue: depth-first search, try to finish paths

src/goto-symex/renaming_level.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ operator()(renamedt<ssa_exprt, L1> l1_expr) const
7373
return renamedt<ssa_exprt, L2>{std::move(l1_expr.value)};
7474
}
7575

76-
void symex_level1t::restore_from(
77-
const symex_renaming_levelt::current_namest &other)
76+
void symex_level1t::restore_from(const current_namest &other)
7877
{
7978
auto it = current_names.begin();
8079
for(const auto &pair : other)

src/goto-symex/symex_dead.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@ void goto_symext::symex_dead(statet &state)
4343
// map is safe as 1) it is local to a path and 2) this instance can no longer
4444
// appear
4545
state.propagation.erase(l1_identifier);
46+
4647
// increment the L2 index to ensure a merge on join points will propagate the
4748
// value for branches that are still live
48-
auto level2_it = state.level2.current_names.find(l1_identifier);
49-
if(level2_it != state.level2.current_names.end())
50-
symex_renaming_levelt::increase_counter(level2_it);
49+
state.increase_generation_if_exists(l1_identifier);
5150
}

src/goto-symex/symex_decl.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
4242
// level-2 indices (but it's an arbitrary choice, we have just always been
4343
// doing it this way).
4444
const std::size_t fresh_l1_index =
45-
path_storage.get_unique_index(ssa.get_identifier(), 1);
45+
path_storage.get_unique_l1_index(ssa.get_identifier(), 1);
4646
state.add_object(ssa, fresh_l1_index, ns);
4747
const irep_idt &l1_identifier = ssa.get_identifier();
4848

@@ -68,6 +68,7 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
6868
state.level2.current_names.emplace(l1_identifier, std::make_pair(ssa, 1))
6969
.second;
7070
CHECK_RETURN(is_new);
71+
7172
const bool record_events=state.record_events;
7273
state.record_events=false;
7374
exprt expr_l2 = state.rename(std::move(ssa), ns);

src/goto-symex/symex_function_call.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ static void locality(
404404
state.rename_ssa<L0>(ssa_exprt{ns.lookup(param).symbol_expr()}, ns);
405405

406406
const std::size_t fresh_l1_index =
407-
path_storage.get_unique_index(ssa.get_identifier(), frame_nr);
407+
path_storage.get_unique_l1_index(ssa.get_identifier(), frame_nr);
408408
state.add_object(ssa, fresh_l1_index, ns);
409409
}
410410
}

src/goto-symex/symex_main.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,12 @@ std::unique_ptr<goto_symext::statet> goto_symext::initialize_entry_point_state(
327327
// create and prepare the state
328328
auto state = util_make_unique<statet>(
329329
symex_targett::sourcet(entry_point_id, start_function->body),
330-
guard_manager);
330+
guard_manager,
331+
[this](const irep_idt &id)
332+
{
333+
return path_storage.get_unique_l2_index(id);
334+
});
335+
331336
CHECK_RETURN(!state->threads.empty());
332337
CHECK_RETURN(!state->call_stack().empty());
333338

src/goto-symex/symex_start_thread.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void goto_symext::symex_start_thread(statet &state)
6767
// get L0 name for current thread
6868
lhs.set_level_0(t);
6969
const irep_idt &l0_name = lhs.get_identifier();
70-
std::size_t l1_index = path_storage.get_unique_index(l0_name, 0);
70+
std::size_t l1_index = path_storage.get_unique_l1_index(l0_name, 0);
7171
CHECK_RETURN(l1_index == 0);
7272

7373
// set up L1 name

0 commit comments

Comments
 (0)