Skip to content

Commit 538eef6

Browse files
authored
Merge pull request diffblue#1577 from smowton/smowton/fix/dependence_graph_inconsistency
Dependence graph: ensure grapht representation is consistent with domain
2 parents f7141c0 + a59dea6 commit 538eef6

File tree

5 files changed

+196
-13
lines changed

5 files changed

+196
-13
lines changed

src/analyses/ai.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,11 @@ void ai_baset::initialize(const goto_functionst &goto_functions)
280280
initialize(it->second);
281281
}
282282

283+
void ai_baset::finalize()
284+
{
285+
// Nothing to do per default
286+
}
287+
283288
ai_baset::locationt ai_baset::get_next(
284289
working_sett &working_set)
285290
{

src/analyses/ai.h

+7
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ class ai_baset
133133
initialize(goto_program);
134134
entry_state(goto_program);
135135
fixedpoint(goto_program, goto_functions, ns);
136+
finalize();
136137
}
137138

138139
void operator()(
@@ -142,6 +143,7 @@ class ai_baset
142143
initialize(goto_functions);
143144
entry_state(goto_functions);
144145
fixedpoint(goto_functions, ns);
146+
finalize();
145147
}
146148

147149
void operator()(const goto_modelt &goto_model)
@@ -150,6 +152,7 @@ class ai_baset
150152
initialize(goto_model.goto_functions);
151153
entry_state(goto_model.goto_functions);
152154
fixedpoint(goto_model.goto_functions, ns);
155+
finalize();
153156
}
154157

155158
void operator()(
@@ -160,6 +163,7 @@ class ai_baset
160163
initialize(goto_function);
161164
entry_state(goto_function.body);
162165
fixedpoint(goto_function.body, goto_functions, ns);
166+
finalize();
163167
}
164168

165169
/// Returns the abstract state before the given instruction
@@ -264,6 +268,9 @@ class ai_baset
264268
virtual void initialize(const goto_functionst::goto_functiont &);
265269
virtual void initialize(const goto_functionst &);
266270

271+
// override to add a cleanup step after fixedpoint has run
272+
virtual void finalize();
273+
267274
void entry_state(const goto_programt &);
268275
void entry_state(const goto_functionst &);
269276

src/analyses/dependence_graph.cpp

+10-13
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,6 @@ void dep_graph_domaint::control_dependencies(
120120

121121
it=next;
122122
}
123-
124-
// add edges to the graph
125-
for(const auto &c_dep : control_deps)
126-
dep_graph.add_dep(dep_edget::kindt::CTRL, c_dep, to);
127123
}
128124

129125
static bool may_be_def_use_pair(
@@ -185,15 +181,6 @@ void dep_graph_domaint::data_dependencies(
185181

186182
dep_graph.reaching_definitions()[to].clear_cache(it->first);
187183
}
188-
189-
// add edges to the graph
190-
for(const auto &d_dep : data_deps)
191-
{
192-
// *it might be handled in a future call call to visit only,
193-
// depending on the sequence of successors; make sure it exists
194-
dep_graph.get_state(d_dep);
195-
dep_graph.add_dep(dep_edget::kindt::DATA, d_dep, to);
196-
}
197184
}
198185

199186
void dep_graph_domaint::transform(
@@ -326,3 +313,13 @@ void dependence_grapht::add_dep(
326313
nodes[n_from].out[n_to].add(kind);
327314
nodes[n_to].in[n_from].add(kind);
328315
}
316+
317+
void dep_graph_domaint::populate_dep_graph(
318+
dependence_grapht &dep_graph, goto_programt::const_targett this_loc) const
319+
{
320+
for(const auto &c_dep : control_deps)
321+
dep_graph.add_dep(dep_edget::kindt::CTRL, c_dep, this_loc);
322+
323+
for(const auto &d_dep : data_deps)
324+
dep_graph.add_dep(dep_edget::kindt::DATA, d_dep, this_loc);
325+
}

src/analyses/dependence_graph.h

+16
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,21 @@ class dep_graph_domaint:public ai_domain_baset
154154
return node_id;
155155
}
156156

157+
void populate_dep_graph(
158+
dependence_grapht &, goto_programt::const_targett) const;
159+
157160
private:
158161
tvt has_values;
159162
node_indext node_id;
160163

161164
typedef std::set<goto_programt::const_targett> depst;
162165
depst control_deps, data_deps;
163166

167+
friend const depst &
168+
dependence_graph_test_get_control_deps(const dep_graph_domaint &);
169+
friend const depst &
170+
dependence_graph_test_get_data_deps(const dep_graph_domaint &);
171+
164172
void control_dependencies(
165173
goto_programt::const_targett from,
166174
goto_programt::const_targett to,
@@ -207,6 +215,14 @@ class dependence_grapht:
207215
}
208216
}
209217

218+
void finalize()
219+
{
220+
for(const auto &location_state : state_map)
221+
{
222+
location_state.second.populate_dep_graph(*this, location_state.first);
223+
}
224+
}
225+
210226
void add_dep(
211227
dep_edget::kindt kind,
212228
goto_programt::const_targett from,

unit/analyses/dependence_graph.cpp

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*******************************************************************\
2+
3+
Module: Unit test for dependence_graph.h
4+
5+
Author: Chris Smowton, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include <iostream>
10+
11+
#include <testing-utils/catch.hpp>
12+
#include <analyses/dependence_graph.h>
13+
#include <util/symbol_table.h>
14+
#include <util/std_code.h>
15+
#include <util/c_types.h>
16+
#include <util/arith_tools.h>
17+
#include <goto-programs/goto_convert_functions.h>
18+
#include <langapi/mode.h>
19+
#include <java_bytecode/java_bytecode_language.h>
20+
21+
static symbolt create_void_function_symbol(
22+
const irep_idt &name,
23+
const codet &code)
24+
{
25+
code_typet void_function_type;
26+
symbolt function;
27+
function.name = name;
28+
function.type = void_function_type;
29+
function.mode = ID_java;
30+
function.value = code;
31+
return function;
32+
}
33+
34+
const std::set<goto_programt::const_targett>&
35+
dependence_graph_test_get_control_deps(const dep_graph_domaint &domain)
36+
{
37+
return domain.control_deps;
38+
}
39+
40+
const std::set<goto_programt::const_targett>&
41+
dependence_graph_test_get_data_deps(const dep_graph_domaint &domain)
42+
{
43+
return domain.data_deps;
44+
}
45+
46+
SCENARIO("dependence_graph", "[core][analyses][dependence_graph]")
47+
{
48+
GIVEN("A call under a control dependency")
49+
{
50+
// Create code like:
51+
// void __CPROVER__start() {
52+
// int x;
53+
// if(NONDET(int) == 0) {
54+
// b();
55+
// x = 1;
56+
// }
57+
// }
58+
// void b() { }
59+
60+
register_language(new_java_bytecode_language);
61+
62+
goto_modelt goto_model;
63+
namespacet ns(goto_model.symbol_table);
64+
65+
typet int_type = signed_int_type();
66+
67+
symbolt x_symbol;
68+
x_symbol.name = id2string(goto_functionst::entry_point()) + "::x";
69+
x_symbol.base_name = "x";
70+
x_symbol.type = int_type;
71+
x_symbol.is_lvalue = true;
72+
x_symbol.is_state_var = true;
73+
x_symbol.is_thread_local = true;
74+
x_symbol.is_file_local = true;
75+
goto_model.symbol_table.add(x_symbol);
76+
77+
code_typet void_function_type;
78+
79+
code_blockt a_body;
80+
code_declt declare_x(x_symbol.symbol_expr());
81+
a_body.move_to_operands(declare_x);
82+
83+
code_ifthenelset if_block;
84+
85+
if_block.cond() =
86+
equal_exprt(
87+
side_effect_expr_nondett(int_type),
88+
from_integer(0, int_type));
89+
90+
code_blockt then_block;
91+
code_function_callt call;
92+
call.function() = symbol_exprt("b", void_function_type);
93+
then_block.move_to_operands(call);
94+
code_assignt assign_x(
95+
x_symbol.symbol_expr(), from_integer(1, int_type));
96+
then_block.move_to_operands(assign_x);
97+
98+
if_block.then_case() = then_block;
99+
100+
a_body.move_to_operands(if_block);
101+
102+
goto_model.symbol_table.add(
103+
create_void_function_symbol(goto_functionst::entry_point(), a_body));
104+
goto_model.symbol_table.add(
105+
create_void_function_symbol("b", code_skipt()));
106+
107+
stream_message_handlert msg(std::cerr);
108+
goto_convert(goto_model, msg);
109+
110+
WHEN("Constructing a dependence graph")
111+
{
112+
dependence_grapht dep_graph(ns);
113+
dep_graph(goto_model.goto_functions, ns);
114+
115+
THEN("The function call and assignment instructions "
116+
"should have a control dependency")
117+
{
118+
for(std::size_t node_idx = 0; node_idx < dep_graph.size(); ++node_idx)
119+
{
120+
const dep_nodet &node = dep_graph[node_idx];
121+
const dep_graph_domaint &node_domain = dep_graph[node.PC];
122+
if(node.PC->is_assign() || node.PC->is_function_call())
123+
{
124+
REQUIRE(
125+
dependence_graph_test_get_control_deps(node_domain).size() == 1);
126+
}
127+
}
128+
}
129+
130+
THEN("The graph's domain and its grapht representation "
131+
"should be consistent")
132+
{
133+
for(std::size_t node_idx = 0; node_idx < dep_graph.size(); ++node_idx)
134+
{
135+
const dep_nodet &node = dep_graph[node_idx];
136+
const dep_graph_domaint &node_domain = dep_graph[node.PC];
137+
const std::set<goto_programt::const_targett> &control_deps =
138+
dependence_graph_test_get_control_deps(node_domain);
139+
const std::set<goto_programt::const_targett> &data_deps =
140+
dependence_graph_test_get_data_deps(node_domain);
141+
142+
std::size_t domain_dep_count =
143+
control_deps.size() + data_deps.size();
144+
145+
REQUIRE(domain_dep_count == node.in.size());
146+
147+
for(const auto &dep_edge : node.in)
148+
{
149+
if(dep_edge.second.get() == dep_edget::kindt::CTRL)
150+
REQUIRE(control_deps.count(dep_graph[dep_edge.first].PC));
151+
else if(dep_edge.second.get() == dep_edget::kindt::DATA)
152+
REQUIRE(data_deps.count(dep_graph[dep_edge.first].PC));
153+
}
154+
}
155+
}
156+
}
157+
}
158+
}

0 commit comments

Comments
 (0)