Skip to content

Commit 28dc3d7

Browse files
authored
Merge pull request #3980 from tautschnig/block-scope
L1 renaming at each declaration
2 parents 150c933 + a397a58 commit 28dc3d7

File tree

12 files changed

+101
-80
lines changed

12 files changed

+101
-80
lines changed

regression/cbmc-cover/pointer-function-parameters/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ main.c
44
^\*\* 5 of 5 covered \(100\.0%\)$
55
^Test suite:$
66
^(tmp(\$\d+)?=[^,]*, a=\(\(signed int \*\)NULL\))|(a=\(\(signed int \*\)NULL\), tmp(\$\d+)?=[^,]*)$
7-
^(a=&tmp(\$\d+)?!0, tmp(\$\d+)?=4)|(tmp(\$\d+)?=4, a=&tmp(\$\d+)?!0)$
8-
^(a=&tmp(\$\d+)?!0, tmp(\$\d+)?=([012356789][0-9]*|4[0-9]+))|(tmp(\$\d+)?=([012356789][0-9]*|4[0-9]+), a=&tmp(\$\d+)?!0)$
7+
^(a=&tmp(\$\d+)?!0@1, tmp(\$\d+)?=4)|(tmp(\$\d+)?=4, a=&tmp(\$\d+)?!0@1)$
8+
^(a=&tmp(\$\d+)?!0@1, tmp(\$\d+)?=([012356789][0-9]*|4[0-9]+))|(tmp(\$\d+)?=([012356789][0-9]*|4[0-9]+), a=&tmp(\$\d+)?!0@1)$
99
^EXIT=0$
1010
^SIGNAL=0$
1111
--
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
int g;
2+
3+
int main()
4+
{
5+
for(int i = 0; i < 4; ++i)
6+
{
7+
int *x;
8+
*&x = &g;
9+
}
10+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--pointer-check
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

regression/cbmc/vla3/test.desc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,4 @@ main.c
77
--
88
^warning: ignoring
99
--
10-
Renaming is inconsistent across loop iterations as we map L1 names to types, but
11-
do not actually introduce new L1 ids each time we declare an object.
10+
The array decision procedure does not yet handle member expressions.

src/goto-programs/goto_clean_expr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ symbol_exprt goto_convertt::make_compound_literal(
4545

4646
// The lifetime of compound literals is really that of
4747
// the block they are in.
48-
copy(code_declt(result), DECL, dest);
48+
if(!new_symbol.is_static_lifetime)
49+
copy(code_declt(result), DECL, dest);
4950

5051
code_assignt code_assign(result, expr);
5152
code_assign.add_source_location()=source_location;

src/goto-symex/goto_symex_state.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,3 +766,29 @@ void goto_symex_statet::print_backtrace(std::ostream &out) const
766766
<< frame.calling_location.pc->location_number << "\n";
767767
}
768768
}
769+
770+
void goto_symex_statet::add_object(
771+
ssa_exprt &ssa,
772+
std::size_t l1_index,
773+
const namespacet &ns)
774+
{
775+
framet &frame = call_stack().top();
776+
777+
const irep_idt l0_name = ssa.get_identifier();
778+
779+
// save old L1 name, if any
780+
auto existing_or_new_entry = level1.current_names.emplace(
781+
std::piecewise_construct,
782+
std::forward_as_tuple(l0_name),
783+
std::forward_as_tuple(ssa, l1_index));
784+
785+
if(!existing_or_new_entry.second)
786+
{
787+
frame.old_level1.emplace(l0_name, existing_or_new_entry.first->second);
788+
existing_or_new_entry.first->second = std::make_pair(ssa, l1_index);
789+
}
790+
791+
ssa = rename_ssa<L1>(std::move(ssa), ns);
792+
const bool inserted = frame.local_objects.insert(ssa.get_identifier()).second;
793+
INVARIANT(inserted, "l1_name expected to be unique by construction");
794+
}

src/goto-symex/goto_symex_state.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,6 @@ class goto_symex_statet final : public goto_statet
6060

6161
symex_target_equationt *symex_target;
6262

63-
// we remember all L1 renamings
64-
std::set<irep_idt> l1_history;
65-
6663
symex_level0t level0;
6764
symex_level1t level1;
6865

@@ -141,6 +138,11 @@ class goto_symex_statet final : public goto_statet
141138
return threads[source.thread_nr].call_stack;
142139
}
143140

141+
/// Create a new instance of the L0-renamed object \p ssa. As part of this,
142+
/// turn \p ssa into an L1-renamed SSA expression. When doing so, use
143+
/// \p l1_index as the L1 index, which must not previously have been used.
144+
void add_object(ssa_exprt &ssa, std::size_t l1_index, const namespacet &ns);
145+
144146
void print_backtrace(std::ostream &) const;
145147

146148
// threads

src/goto-symex/path_storage.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,25 @@ 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)
103+
{
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);
108+
109+
return entry.first->second;
110+
}
111+
101112
private:
102113
// Derived classes should override these methods, allowing the base class to
103114
// enforce preconditions.
104115
virtual patht &private_peek() = 0;
105116
virtual void private_pop() = 0;
117+
118+
/// Storage used by \ref get_unique_index.
119+
std::unordered_map<irep_idt, std::size_t> unique_index_map;
106120
};
107121

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

src/goto-symex/symex_dead.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ Author: Daniel Kroening, [email protected]
1111

1212
#include "goto_symex.h"
1313

14-
#include <cassert>
15-
1614
#include <util/std_expr.h>
1715

1816
#include <pointer-analysis/add_failed_symbols.h>
@@ -23,9 +21,6 @@ void goto_symext::symex_dead(statet &state)
2321

2422
const code_deadt &code = instruction.get_dead();
2523

26-
// We increase the L2 renaming to make these non-deterministic.
27-
// We also prevent propagation of old values.
28-
2924
ssa_exprt ssa = state.rename_ssa<L1>(ssa_exprt{code.symbol()}, ns);
3025

3126
// in case of pointers, put something into the value set
@@ -43,10 +38,13 @@ void goto_symext::symex_dead(statet &state)
4338

4439
const irep_idt &l1_identifier = ssa.get_identifier();
4540

46-
// prevent propagation
41+
// we cannot remove the object from the L1 renaming map, because L1 renaming
42+
// information is not local to a path, but removing it from the propagation
43+
// map is safe as 1) it is local to a path and 2) this instance can no longer
44+
// appear
4745
state.propagation.erase(l1_identifier);
48-
49-
// L2 renaming
46+
// increment the L2 index to ensure a merge on join points will propagate the
47+
// value for branches that are still live
5048
auto level2_it = state.level2.current_names.find(l1_identifier);
5149
if(level2_it != state.level2.current_names.end())
5250
symex_renaming_levelt::increase_counter(level2_it);

src/goto-symex/symex_decl.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,16 @@ void goto_symext::symex_decl(statet &state)
3434

3535
void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
3636
{
37-
// We increase the L2 renaming to make these non-deterministic.
38-
// We also prevent propagation of old values.
39-
40-
ssa_exprt ssa = state.rename_ssa<L1>(ssa_exprt{expr}, ns);
37+
// each declaration introduces a new object, which we record as a fresh L1
38+
// index
39+
40+
ssa_exprt ssa = state.rename_ssa<L0>(ssa_exprt{expr}, ns);
41+
// We use "1" as the first level-1 index, which is in line with doing so for
42+
// level-2 indices (but it's an arbitrary choice, we have just always been
43+
// doing it this way).
44+
const std::size_t fresh_l1_index =
45+
path_storage.get_unique_index(ssa.get_identifier(), 1);
46+
state.add_object(ssa, fresh_l1_index, ns);
4147
const irep_idt &l1_identifier = ssa.get_identifier();
4248

4349
// rename type to L2
@@ -57,16 +63,11 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
5763
state.value_set.assign(ssa, l1_rhs, ns, true, false);
5864
}
5965

60-
// prevent propagation
61-
state.propagation.erase(l1_identifier);
62-
6366
// L2 renaming
64-
// inlining may yield multiple declarations of the same identifier
65-
// 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);
67+
bool is_new =
68+
state.level2.current_names.emplace(l1_identifier, std::make_pair(ssa, 1))
69+
.second;
70+
CHECK_RETURN(is_new);
7071
const bool record_events=state.record_events;
7172
state.record_events=false;
7273
exprt expr_l2 = state.rename(std::move(ssa), ns);

0 commit comments

Comments
 (0)