Skip to content

Commit 15f99ce

Browse files
committed
Maintain a single write set
Signed-off-by: Felipe R. Monteiro <felisous@amazon.com>
1 parent b6f30b9 commit 15f99ce

File tree

3 files changed

+46
-80
lines changed

3 files changed

+46
-80
lines changed

src/goto-instrument/contracts/assigns.cpp

Lines changed: 36 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,36 @@ exprt assigns_clauset::targett::normalize(const exprt &expr)
4343
return to_index_expr(object).array();
4444
}
4545

46+
assigns_clauset::assigns_clauset(
47+
const exprt::operandst &assigns,
48+
const messaget &log,
49+
const namespacet &ns)
50+
: log(log), ns(ns)
51+
{
52+
for(const auto &target_expr : assigns)
53+
{
54+
add_to_write_set(target_expr);
55+
}
56+
}
57+
58+
void assigns_clauset::add_to_write_set(const exprt &target_expr)
59+
{
60+
auto insertion_succeeded = write_set.emplace(*this, target_expr).second;
61+
62+
if(!insertion_succeeded)
63+
{
64+
log.warning() << "Ignored duplicate expression '"
65+
<< from_expr(ns, target_expr.id(), target_expr)
66+
<< "' in assigns clause at "
67+
<< target_expr.source_location().as_string() << messaget::eom;
68+
}
69+
}
70+
71+
void assigns_clauset::remove_from_write_set(const exprt &target_expr)
72+
{
73+
write_set.erase(targett(*this, target_expr));
74+
}
75+
4676
exprt assigns_clauset::targett::generate_containment_check(
4777
const address_of_exprt &lhs_address) const
4878
{
@@ -91,54 +121,11 @@ exprt assigns_clauset::targett::generate_containment_check(
91121
return or_exprt{not_exprt{address_validity}, conjunction(containment_check)};
92122
}
93123

94-
assigns_clauset::assigns_clauset(
95-
const exprt::operandst &assigns,
96-
const messaget &log,
97-
const namespacet &ns)
98-
: log(log), ns(ns)
99-
{
100-
for(const auto &target_expr : assigns)
101-
{
102-
add_to_global_write_set(target_expr);
103-
}
104-
}
105-
106-
void assigns_clauset::add_to_global_write_set(const exprt &target_expr)
107-
{
108-
auto insertion_succeeded =
109-
global_write_set.emplace(*this, target_expr).second;
110-
111-
if(!insertion_succeeded)
112-
{
113-
log.warning() << "Ignored duplicate expression '"
114-
<< from_expr(ns, target_expr.id(), target_expr)
115-
<< "' in assigns clause at "
116-
<< target_expr.source_location().as_string() << messaget::eom;
117-
}
118-
}
119-
120-
void assigns_clauset::remove_from_global_write_set(const exprt &target_expr)
121-
{
122-
global_write_set.erase(targett(*this, target_expr));
123-
}
124-
125-
void assigns_clauset::add_to_local_write_set(const exprt &expr)
126-
{
127-
local_write_set.emplace(*this, expr);
128-
}
129-
130-
void assigns_clauset::remove_from_local_write_set(const exprt &expr)
131-
{
132-
local_write_set.erase(targett(*this, expr));
133-
}
134-
135124
goto_programt
136125
assigns_clauset::generate_havoc_code(const source_locationt &location) const
137126
{
138127
modifiest modifies;
139-
for(const auto &target : global_write_set)
140-
modifies.insert(target.address.object());
141-
for(const auto &target : local_write_set)
128+
for(const auto &target : write_set)
142129
modifies.insert(target.address.object());
143130

144131
goto_programt havoc_statements;
@@ -151,17 +138,13 @@ assigns_clauset::generate_havoc_code(const source_locationt &location) const
151138
exprt assigns_clauset::generate_containment_check(const exprt &lhs) const
152139
{
153140
// If write set is empty, no assignment is allowed.
154-
if(global_write_set.empty() && local_write_set.empty())
141+
if(write_set.empty())
155142
return false_exprt();
156143

157144
const auto lhs_address = address_of_exprt(targett::normalize(lhs));
158145

159146
exprt::operandst condition;
160-
for(const auto &target : local_write_set)
161-
{
162-
condition.push_back(target.generate_containment_check(lhs_address));
163-
}
164-
for(const auto &target : global_write_set)
147+
for(const auto &target : write_set)
165148
{
166149
condition.push_back(target.generate_containment_check(lhs_address));
167150
}
@@ -171,26 +154,14 @@ exprt assigns_clauset::generate_containment_check(const exprt &lhs) const
171154
exprt assigns_clauset::generate_subset_check(
172155
const assigns_clauset &subassigns) const
173156
{
174-
if(subassigns.global_write_set.empty())
157+
if(subassigns.write_set.empty())
175158
return true_exprt();
176159

177-
INVARIANT(
178-
subassigns.local_write_set.empty(),
179-
"Local write set for function calls should be empty at this point.\n" +
180-
subassigns.local_write_set.begin()
181-
->address.source_location()
182-
.as_string());
183-
184160
exprt result = true_exprt();
185-
for(const auto &subtarget : subassigns.global_write_set)
161+
for(const auto &subtarget : subassigns.write_set)
186162
{
187163
exprt::operandst current_subtarget_found_conditions;
188-
for(const auto &target : global_write_set)
189-
{
190-
current_subtarget_found_conditions.push_back(
191-
target.generate_containment_check(subtarget.address));
192-
}
193-
for(const auto &target : local_write_set)
164+
for(const auto &target : write_set)
194165
{
195166
current_subtarget_found_conditions.push_back(
196167
target.generate_containment_check(subtarget.address));

src/goto-instrument/contracts/assigns.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,8 @@ class assigns_clauset
5858
const messaget &,
5959
const namespacet &);
6060

61-
void add_to_global_write_set(const exprt &);
62-
void remove_from_global_write_set(const exprt &);
63-
void add_to_local_write_set(const exprt &);
64-
void remove_from_local_write_set(const exprt &);
61+
void add_to_write_set(const exprt &);
62+
void remove_from_write_set(const exprt &);
6563

6664
goto_programt generate_havoc_code(const source_locationt &) const;
6765
exprt generate_containment_check(const exprt &) const;
@@ -71,8 +69,7 @@ class assigns_clauset
7169
const namespacet &ns;
7270

7371
protected:
74-
std::unordered_set<targett, targett::hasht> global_write_set;
75-
std::unordered_set<targett, targett::hasht> local_write_set;
72+
std::unordered_set<targett, targett::hasht> write_set;
7673
};
7774

7875
#endif // CPROVER_GOTO_INSTRUMENT_CONTRACTS_ASSIGNS_H

src/goto-instrument/contracts/contracts.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ void code_contractst::instrument_assign_statement(
678678
lhs_sym.is_static_lifetime &&
679679
lhs_sym.location.get_function() ==
680680
instruction_iterator->source_location.get_function())
681-
assigns_clause.add_to_local_write_set(lhs);
681+
assigns_clause.add_to_write_set(lhs);
682682
}
683683

684684
add_containment_check(program, assigns_clause, instruction_iterator, lhs);
@@ -719,7 +719,7 @@ void code_contractst::instrument_call_statement(
719719
{
720720
instrument_assign_statement(instruction_it, body, assigns);
721721
const exprt &lhs = instruction_it->assign_lhs();
722-
assigns.add_to_local_write_set(dereference_exprt(lhs));
722+
assigns.add_to_write_set(dereference_exprt(lhs));
723723
}
724724
return; // assume malloc edits no pre-existing memory objects.
725725
}
@@ -728,8 +728,7 @@ void code_contractst::instrument_call_statement(
728728
const exprt &lhs_dereference = dereference_exprt(
729729
to_typecast_expr(instruction_it->call_arguments().front()).op());
730730
add_containment_check(body, assigns, instruction_it, lhs_dereference);
731-
assigns.remove_from_local_write_set(lhs_dereference);
732-
assigns.remove_from_global_write_set(lhs_dereference);
731+
assigns.remove_from_write_set(lhs_dereference);
733732
return;
734733
}
735734
}
@@ -822,7 +821,7 @@ bool code_contractst::check_frame_conditions_function(const irep_idt &function)
822821
// Adds formal parameters to freely assignable set
823822
for(auto &parameter : to_code_type(target.type).parameters())
824823
{
825-
assigns.add_to_local_write_set(
824+
assigns.add_to_write_set(
826825
ns.lookup(parameter.get_identifier()).symbol_expr());
827826
}
828827

@@ -847,7 +846,7 @@ void code_contractst::check_frame_conditions(
847846
if(instruction_it->is_decl())
848847
{
849848
// Local variables are always freely assignable
850-
assigns.add_to_local_write_set(instruction_it->get_decl().symbol());
849+
assigns.add_to_write_set(instruction_it->get_decl().symbol());
851850
}
852851
else if(instruction_it->is_assign())
853852
{
@@ -859,7 +858,7 @@ void code_contractst::check_frame_conditions(
859858
}
860859
else if(instruction_it->is_dead())
861860
{
862-
assigns.remove_from_local_write_set(instruction_it->get_dead().symbol());
861+
assigns.remove_from_write_set(instruction_it->get_dead().symbol());
863862
}
864863
else if(
865864
instruction_it->is_other() &&
@@ -868,8 +867,7 @@ void code_contractst::check_frame_conditions(
868867
const exprt &havoc_argument = dereference_exprt(
869868
to_typecast_expr(instruction_it->get_other().operands().front()).op());
870869
add_containment_check(body, assigns, instruction_it, havoc_argument);
871-
assigns.remove_from_local_write_set(havoc_argument);
872-
assigns.remove_from_global_write_set(havoc_argument);
870+
assigns.remove_from_write_set(havoc_argument);
873871
}
874872
}
875873
}

0 commit comments

Comments
 (0)