Skip to content

Commit a2c1685

Browse files
committed
Templatize and virtualize value-set analysis
This templates value-set-analysis, so that it can be subclassed providing a value-set extension, and virtualizes value-set so it can similarly be extended.
1 parent b63eb99 commit a2c1685

12 files changed

+261
-168
lines changed

src/goto-symex/postcondition.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ bool postconditiont::is_used(
174174
// aliasing may happen here
175175

176176
value_setst::valuest expr_set;
177-
value_set.get_value_set(expr.op0(), expr_set, ns);
177+
value_set.read_value_set(expr.op0(), expr_set, ns);
178178
std::unordered_set<irep_idt, irep_id_hash> symbols;
179179

180180
for(value_setst::valuest::const_iterator

src/goto-symex/symex_dereference_state.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ void symex_dereference_statet::get_value_set(
8181
const exprt &expr,
8282
value_setst::valuest &value_set)
8383
{
84-
state.value_set.get_value_set(expr, value_set, goto_symex.ns);
84+
state.value_set.read_value_set(expr, value_set, goto_symex.ns);
8585

8686
#if 0
8787
std::cout << "**************************\n";

src/pointer-analysis/Makefile

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ SRC = add_failed_symbols.cpp \
1111
value_set_analysis_fivr.cpp \
1212
value_set_analysis_fivrns.cpp \
1313
value_set_dereference.cpp \
14-
value_set_domain.cpp \
1514
value_set_domain_fi.cpp \
1615
value_set_domain_fivr.cpp \
1716
value_set_domain_fivrns.cpp \

src/pointer-analysis/show_value_sets.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ Author: Daniel Kroening, [email protected]
1212
#ifndef CPROVER_POINTER_ANALYSIS_SHOW_VALUE_SETS_H
1313
#define CPROVER_POINTER_ANALYSIS_SHOW_VALUE_SETS_H
1414

15+
#include <pointer-analysis/value_set_analysis.h>
1516
#include <util/ui_message.h>
1617

1718
class goto_modelt;
18-
class value_set_analysist;
1919

2020
void show_value_sets(
2121
ui_message_handlert::uit,

src/pointer-analysis/value_set.cpp

+15-6
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ bool value_sett::eval_pointer_offset(
311311
return mod;
312312
}
313313

314-
void value_sett::get_value_set(
314+
void value_sett::read_value_set(
315315
const exprt &expr,
316316
value_setst::valuest &dest,
317317
const namespacet &ns) const
@@ -340,7 +340,7 @@ void value_sett::get_value_set(
340340
{
341341
exprt tmp(expr);
342342
if(!is_simplified)
343-
simplify(tmp, ns);
343+
simplifier(tmp, ns);
344344

345345
get_value_set_rec(tmp, dest, "", tmp.type(), ns);
346346
}
@@ -809,7 +809,7 @@ void value_sett::get_value_set_rec(
809809

810810
exprt op1=expr.op1();
811811
if(eval_pointer_offset(op1, ns))
812-
simplify(op1, ns);
812+
simplifier(op1, ns);
813813

814814
mp_integer op1_offset;
815815
const typet &op0_type=ns.follow(expr.op0().type());
@@ -908,7 +908,7 @@ void value_sett::dereference_rec(
908908
dest=src;
909909
}
910910

911-
void value_sett::get_reference_set(
911+
void value_sett::read_reference_set(
912912
const exprt &expr,
913913
value_setst::valuest &dest,
914914
const namespacet &ns) const
@@ -1205,6 +1205,12 @@ void value_sett::assign(
12051205
object_mapt values_rhs;
12061206
get_value_set(rhs, values_rhs, ns, is_simplified);
12071207

1208+
// Permit custom subclass to alter the read values prior to write:
1209+
adjust_assign_rhs_values(rhs, ns, values_rhs);
1210+
1211+
// Permit custom subclass to perform global side-effects prior to write:
1212+
apply_assign_side_effects(lhs, rhs, ns);
1213+
12081214
assign_rec(lhs, values_rhs, "", ns, add_to_sets);
12091215
}
12101216
}
@@ -1482,7 +1488,7 @@ void value_sett::do_end_function(
14821488
assign(lhs, rhs, ns, false, false);
14831489
}
14841490

1485-
void value_sett::apply_code(
1491+
void value_sett::apply_code_rec(
14861492
const codet &code,
14871493
const namespacet &ns)
14881494
{
@@ -1491,7 +1497,7 @@ void value_sett::apply_code(
14911497
if(statement==ID_block)
14921498
{
14931499
forall_operands(it, code)
1494-
apply_code(to_code(*it), ns);
1500+
apply_code_rec(to_code(*it), ns);
14951501
}
14961502
else if(statement==ID_function_call)
14971503
{
@@ -1694,3 +1700,6 @@ exprt value_sett::make_member(
16941700

16951701
return member_expr;
16961702
}
1703+
1704+
value_sett::expr_simplifiert value_sett::default_simplifier=
1705+
[](exprt &e, const namespacet &ns) { simplify(e, ns); };

src/pointer-analysis/value_set.h

+80-18
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,20 @@ class namespacet;
2424

2525
class value_sett
2626
{
27+
typedef std::function<void(exprt &, const namespacet &)> expr_simplifiert;
28+
29+
static expr_simplifiert default_simplifier;
30+
2731
public:
28-
value_sett():location_number(0)
32+
value_sett():
33+
location_number(0),
34+
simplifier(default_simplifier)
35+
{
36+
}
37+
38+
explicit value_sett(expr_simplifiert simplifier):
39+
location_number(0),
40+
simplifier(std::move(simplifier))
2941
{
3042
}
3143

@@ -166,7 +178,7 @@ class value_sett
166178
typedef std::unordered_map<idt, entryt, string_hash> valuest;
167179
#endif
168180

169-
void get_value_set(
181+
void read_value_set(
170182
const exprt &expr,
171183
value_setst::valuest &dest,
172184
const namespacet &ns) const;
@@ -213,7 +225,10 @@ class value_sett
213225

214226
void apply_code(
215227
const codet &code,
216-
const namespacet &ns);
228+
const namespacet &ns)
229+
{
230+
apply_code_rec(code, ns);
231+
}
217232

218233
void assign(
219234
const exprt &lhs,
@@ -232,7 +247,7 @@ class value_sett
232247
const exprt &lhs,
233248
const namespacet &ns);
234249

235-
void get_reference_set(
250+
void read_reference_set(
236251
const exprt &expr,
237252
value_setst::valuest &dest,
238253
const namespacet &ns) const;
@@ -242,13 +257,6 @@ class value_sett
242257
const namespacet &ns) const;
243258

244259
protected:
245-
void get_value_set_rec(
246-
const exprt &expr,
247-
object_mapt &dest,
248-
const std::string &suffix,
249-
const typet &original_type,
250-
const namespacet &ns) const;
251-
252260
void get_value_set(
253261
const exprt &expr,
254262
object_mapt &dest,
@@ -272,13 +280,6 @@ class value_sett
272280
const exprt &src,
273281
exprt &dest) const;
274282

275-
void assign_rec(
276-
const exprt &lhs,
277-
const object_mapt &values_rhs,
278-
const std::string &suffix,
279-
const namespacet &ns,
280-
bool add_to_sets);
281-
282283
void do_free(
283284
const exprt &op,
284285
const namespacet &ns);
@@ -287,6 +288,67 @@ class value_sett
287288
const exprt &src,
288289
const irep_idt &component_name,
289290
const namespacet &ns);
291+
292+
// Expression simplification:
293+
294+
private:
295+
/// Expression simplification function; by default, plain old
296+
/// util/simplify_expr, but can be customised by subclass.
297+
expr_simplifiert simplifier;
298+
299+
protected:
300+
/// Run registered expression simplifier
301+
void run_simplifier(exprt &e, const namespacet &ns)
302+
{
303+
simplifier(e, ns);
304+
}
305+
306+
// Subclass customisation points:
307+
308+
protected:
309+
/// Subclass customisation point for recursion over RHS expression:
310+
virtual void get_value_set_rec(
311+
const exprt &expr,
312+
object_mapt &dest,
313+
const std::string &suffix,
314+
const typet &original_type,
315+
const namespacet &ns) const;
316+
317+
/// Subclass customisation point for recursion over LHS expression:
318+
virtual void assign_rec(
319+
const exprt &lhs,
320+
const object_mapt &values_rhs,
321+
const std::string &suffix,
322+
const namespacet &ns,
323+
bool add_to_sets);
324+
325+
/// Subclass customisation point for applying code to this domain:
326+
virtual void apply_code_rec(
327+
const codet &code,
328+
const namespacet &ns);
329+
330+
private:
331+
/// Subclass customisation point to filter or otherwise alter the value-set
332+
/// returned from get_value_set before it is passed into assign. For example,
333+
/// this is used in one subclass to tag and thus differentiate values that
334+
/// originated in a particular place, vs. those that have been copied.
335+
virtual void adjust_assign_rhs_values(
336+
const exprt &rhs,
337+
const namespacet &ns,
338+
object_mapt &rhs_values) const
339+
{
340+
}
341+
342+
/// Subclass customisation point to apply global side-effects to this domain,
343+
/// after RHS values are read but before they are written. For example, this
344+
/// is used in a recency-analysis plugin to demote existing most-recent
345+
/// objects to general case ones.
346+
virtual void apply_assign_side_effects(
347+
const exprt &lhs,
348+
const exprt &rhs,
349+
const namespacet &ns)
350+
{
351+
}
290352
};
291353

292354
#endif // CPROVER_POINTER_ANALYSIS_VALUE_SET_H

src/pointer-analysis/value_set_analysis.cpp

-65
Original file line numberDiff line numberDiff line change
@@ -13,74 +13,9 @@ Author: Daniel Kroening, [email protected]
1313

1414
#include <util/prefix.h>
1515
#include <util/cprover_prefix.h>
16-
#include <util/xml_expr.h>
17-
#include <util/xml.h>
1816

1917
#include <langapi/language_util.h>
2018

21-
void value_set_analysist::initialize(
22-
const goto_programt &goto_program)
23-
{
24-
baset::initialize(goto_program);
25-
}
26-
27-
void value_set_analysist::initialize(
28-
const goto_functionst &goto_functions)
29-
{
30-
baset::initialize(goto_functions);
31-
}
32-
33-
void value_set_analysist::convert(
34-
const goto_programt &goto_program,
35-
const irep_idt &identifier,
36-
xmlt &dest) const
37-
{
38-
source_locationt previous_location;
39-
40-
forall_goto_program_instructions(i_it, goto_program)
41-
{
42-
const source_locationt &location=i_it->source_location;
43-
44-
if(location==previous_location)
45-
continue;
46-
47-
if(location.is_nil() || location.get_file().empty())
48-
continue;
49-
50-
// find value set
51-
const value_sett &value_set=(*this)[i_it].value_set;
52-
53-
xmlt &i=dest.new_element("instruction");
54-
i.new_element()=::xml(location);
55-
56-
for(value_sett::valuest::const_iterator
57-
v_it=value_set.values.begin();
58-
v_it!=value_set.values.end();
59-
v_it++)
60-
{
61-
xmlt &var=i.new_element("variable");
62-
var.new_element("identifier").data=
63-
id2string(v_it->first);
64-
65-
#if 0
66-
const value_sett::expr_sett &expr_set=
67-
v_it->second.expr_set();
68-
69-
for(value_sett::expr_sett::const_iterator
70-
e_it=expr_set.begin();
71-
e_it!=expr_set.end();
72-
e_it++)
73-
{
74-
std::string value_str=
75-
from_expr(ns, identifier, *e_it);
76-
77-
var.new_element("value").data=
78-
xmlt::escape(value_str);
79-
}
80-
#endif
81-
}
82-
}
83-
}
8419
void convert(
8520
const goto_functionst &goto_functions,
8621
const value_set_analysist &value_set_analysis,

0 commit comments

Comments
 (0)