Skip to content

Commit ac2b5b7

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 f45028b commit ac2b5b7

10 files changed

+89
-33
lines changed

src/goto-instrument/accelerate/scratch_program.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ 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+
return path_storage.get_unique_l2_index(id);
43+
});
44+
4145
symex.symex_with_state(
4246
*symex_state,
4347
[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,13 +31,15 @@ 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(manager),
3637
source(_source),
3738
guard_manager(manager),
3839
symex_target(nullptr),
3940
record_events(true),
40-
dirty()
41+
dirty(),
42+
fresh_l2_name_provider(fresh_l2_name_provider)
4143
{
4244
threads.emplace_back(guard_manager);
4345
call_stack().new_frame(source);
@@ -213,9 +215,7 @@ void goto_symex_statet::assignment(
213215
#endif
214216

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

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

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

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

491484
// produce a fresh L2 name
492-
symex_renaming_levelt::increase_counter(level2_it);
485+
increase_generation(l1_identifier, ssa_l1);
493486
expr = set_indices<L2>(std::move(ssa_l1), ns).get();
494487

495488
// and record that
@@ -500,6 +493,32 @@ bool goto_symex_statet::l2_thread_read_encoding(
500493
return true;
501494
}
502495

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

src/goto-symex/goto_symex_state.h

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

4851
/// \brief Fake "copy constructor" that initializes the `symex_target` member
@@ -202,7 +205,17 @@ class goto_symex_statet final : public goto_statet
202205
unsigned total_vccs = 0;
203206
unsigned remaining_vccs = 0;
204207

208+
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
209+
// latest generation on this path.
210+
void increase_generation(const irep_idt l1_identifier, const ssa_exprt &lhs);
211+
212+
/// Increases the generation of the L1 identifier. Does nothing if there
213+
/// isn't an expression keyed by it.
214+
void increase_generation_if_exists(const irep_idt identifier);
215+
205216
private:
217+
std::function<std::size_t(const irep_idt &)> fresh_l2_name_provider;
218+
206219
/// \brief Dangerous, do not use
207220
///
208221
/// 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
@@ -43,7 +43,7 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
4343
ssa_exprt ssa = state.add_object(
4444
expr,
4545
[this](const irep_idt &l0_name) {
46-
return path_storage.get_unique_index(l0_name, 1);
46+
return path_storage.get_unique_l1_index(l0_name, 1);
4747
},
4848
ns);
4949
const irep_idt &l1_identifier = ssa.get_identifier();
@@ -70,6 +70,7 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
7070
state.level2.current_names.emplace(l1_identifier, std::make_pair(ssa, 1))
7171
.second;
7272
CHECK_RETURN(is_new);
73+
7374
const bool record_events=state.record_events;
7475
state.record_events=false;
7576
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
@@ -402,7 +402,7 @@ static void locality(
402402
(void)state.add_object(
403403
ns.lookup(param).symbol_expr(),
404404
[&path_storage, &frame_nr](const irep_idt &l0_name) {
405-
return path_storage.get_unique_index(l0_name, frame_nr);
405+
return path_storage.get_unique_l1_index(l0_name, frame_nr);
406406
},
407407
ns);
408408
}

src/goto-symex/symex_main.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,11 @@ 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+
return path_storage.get_unique_l2_index(id);
333+
});
334+
331335
CHECK_RETURN(!state->threads.empty());
332336
CHECK_RETURN(!state->call_stack().empty());
333337

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)