Skip to content

Commit f5485a9

Browse files
Merge pull request diffblue#256 from danpoe/feature/control-deps-of-function-body-instructions-on-calls
Control dependencies of function body instructions to function calls
2 parents f8d2eb5 + 12c0933 commit f5485a9

File tree

5 files changed

+102
-31
lines changed

5 files changed

+102
-31
lines changed

regression/goto-analyzer/dependence-graph13/test.desc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ main.c
44
activate-multi-line-match
55
^EXIT=0$
66
^SIGNAL=0$
7-
Function: main\n.*\n.*\n.*\nControl dependencies: [0-9]+
8-
Function: func\n.*\n.*\n.*\nControl dependencies: [0-9]+
9-
Function: __CPROVER_initialize\n.*\n.*\n.*\nControl dependencies: [0-9]+
7+
// The function entry points shall have a control dependency on the function call
8+
Function: main\n.*\n.*\n.*\nControl dependencies: [0-9]+ \[CALL\]
9+
Function: func\n.*\n.*\n.*\nControl dependencies: [0-9]+ \[CALL\]
10+
Function: __CPROVER_initialize\n.*\n.*\n.*\nControl dependencies: [0-9]+ \[CALL\]
1011
--
12+
// The __CPROVER__start function must not have a control dependency on anything
1113
Function: __CPROVER__start\n.*\n.*\n.*\nControl dependencies: [0-9]+
1214
^warning: ignoring
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
void main(void)
3+
{
4+
int a;
5+
6+
if(a)
7+
{
8+
a = 1;
9+
}
10+
11+
a = 2;
12+
}
13+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
--show --dependence-graph
4+
activate-multi-line-match
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
Control dependencies: [0-9]+ \[TRUE\]\n.*\n.*\n\s+a = 1;
8+
Control dependencies: [0-9]+ \[CALL\]\n.*\n.*\n\s+a = 2;
9+
10+
--
11+
^warning: ignoring

src/analyses/dependence_graph.cpp

Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ bool dep_graph_domaint::merge(
4444

4545
changed|=merge_control_dependencies(
4646
src.control_deps,
47-
src.control_dep_candidates);
47+
src.control_dep_candidates,
48+
src.control_dep_calls);
4849

4950
has_changed=false;
5051
has_values=tvt::unknown();
@@ -74,7 +75,9 @@ void dep_graph_domaint::control_dependencies(
7475
control_dep_candidates.insert(from);
7576
else if(from->is_end_function())
7677
{
78+
control_deps.clear();
7779
control_dep_candidates.clear();
80+
control_dep_calls.clear();
7881
return;
7982
}
8083

@@ -149,6 +152,7 @@ void dep_graph_domaint::control_dependencies(
149152
}
150153

151154
control_deps.insert(std::make_pair(cd, branch));
155+
control_dep_calls.clear();
152156
}
153157
}
154158

@@ -259,7 +263,8 @@ void dep_graph_domaint::control_dependencies(
259263

260264
bool dep_graph_domaint::merge_control_dependencies(
261265
const control_depst &other_control_deps,
262-
const control_dep_candidatest &other_control_dep_candidates)
266+
const control_dep_candidatest &other_control_dep_candidates,
267+
const control_dep_callst &other_control_dep_calls)
263268
{
264269
bool changed=false;
265270

@@ -308,6 +313,16 @@ bool dep_graph_domaint::merge_control_dependencies(
308313

309314
changed|=n!=control_dep_candidates.size();
310315

316+
// Merge call control dependencies
317+
318+
n=control_dep_calls.size();
319+
320+
control_dep_calls.insert(
321+
other_control_dep_calls.begin(),
322+
other_control_dep_calls.end());
323+
324+
changed|=n!=control_dep_calls.size();
325+
311326
return changed;
312327
}
313328

@@ -448,25 +463,6 @@ void dep_graph_domaint::transform(
448463
dependence_grapht *dep_graph=dynamic_cast<dependence_grapht*>(&ai);
449464
assert(dep_graph!=nullptr);
450465

451-
// We do not propagate control dependencies on function calls, i.e., only the
452-
// entry point of a function should have a control dependency on the call
453-
if(!control_deps.empty())
454-
{
455-
const goto_programt::const_targett &dep = control_deps.begin()->first;
456-
if(dep->is_function_call())
457-
{
458-
INVARIANT(
459-
std::all_of(
460-
std::next(control_deps.begin()),
461-
control_deps.end(),
462-
[](const std::pair<const goto_programt::const_targett, tvt> &d)
463-
{ return d.first->is_function_call(); }),
464-
"All entries must be function calls");
465-
466-
control_deps.clear();
467-
}
468-
}
469-
470466
// propagate control dependencies across function calls
471467
if(from->is_function_call())
472468
{
@@ -492,13 +488,15 @@ void dep_graph_domaint::transform(
492488
// modify abstract state of return location
493489
if(s->merge_control_dependencies(
494490
control_deps,
495-
control_dep_candidates))
491+
control_dep_candidates,
492+
control_dep_calls))
496493
s->has_changed=true;
497494

498495
control_deps.clear();
499-
control_deps.insert(std::make_pair(from, tvt::unknown()));
500-
501496
control_dep_candidates.clear();
497+
498+
control_dep_calls.clear();
499+
control_dep_calls.insert(from);
502500
}
503501
}
504502
else
@@ -512,7 +510,7 @@ void dep_graph_domaint::output(
512510
const ai_baset &ai,
513511
const namespacet &ns) const
514512
{
515-
if(!control_deps.empty())
513+
if(!control_deps.empty() || !control_dep_calls.empty())
516514
{
517515
out << "Control dependencies: ";
518516
for(control_depst::const_iterator
@@ -528,6 +526,18 @@ void dep_graph_domaint::output(
528526

529527
out << cd->location_number << " [" << branch << "]";
530528
}
529+
530+
for(control_dep_callst::const_iterator
531+
it=control_dep_calls.begin();
532+
it!=control_dep_calls.end();
533+
++it)
534+
{
535+
if(!control_deps.empty() || it!=control_dep_calls.begin())
536+
out << ",";
537+
538+
out << (*it)->location_number << " [CALL]";
539+
}
540+
531541
out << "\n";
532542
}
533543

@@ -584,6 +594,17 @@ jsont dep_graph_domaint::output_json(
584594
link["branch"]=json_stringt(branch.to_string());
585595
}
586596

597+
for(const auto &target : control_dep_calls)
598+
{
599+
json_objectt &link=graph.push_back().make_object();
600+
601+
link["locationNumber"]=
602+
json_numbert(std::to_string(target->location_number));
603+
link["sourceLocation"]=json(target->source_location);
604+
link["type"]=json_stringt("control");
605+
link["branch"]=json_stringt("CALL");
606+
}
607+
587608
for(const auto &dd : data_deps)
588609
{
589610
goto_programt::const_targett target=dd.first;
@@ -628,6 +649,17 @@ jsont dep_graph_domaint::output_json_additional(
628649
link["branch"]=json_stringt(branch.to_string());
629650
}
630651

652+
for(const auto &target : control_dep_calls)
653+
{
654+
json_objectt &link=graph.push_back().make_object();
655+
656+
link["locationNumber"]=
657+
json_numbert(std::to_string(target->location_number));
658+
link["sourceLocation"]=json(target->source_location);
659+
link["type"]=json_stringt("control");
660+
link["branch"]=json_stringt("CALL");
661+
}
662+
631663
for(const auto &dd : base_state.data_deps)
632664
{
633665
goto_programt::const_targett target=dd.first;
@@ -704,6 +736,9 @@ void dep_graph_domaint::populate_dep_graph(
704736
for(const auto &c_dep : control_deps)
705737
dep_graph.add_dep(dep_edget::kindt::CTRL, c_dep.first, this_loc);
706738

739+
for(const auto &c_dep : control_dep_calls)
740+
dep_graph.add_dep(dep_edget::kindt::CTRL, c_dep, this_loc);
741+
707742
for(const auto &d_dep : data_deps)
708743
dep_graph.add_dep(dep_edget::kindt::DATA, d_dep.first, this_loc);
709744
}

src/analyses/dependence_graph.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ class dep_graph_domaint:public ai_domain_baset
121121
has_changed=false;
122122
control_deps.clear();
123123
control_dep_candidates.clear();
124+
control_dep_calls.clear();
124125
data_deps.clear();
125126
}
126127

@@ -133,6 +134,7 @@ class dep_graph_domaint:public ai_domain_baset
133134
has_changed=false;
134135
control_deps.clear();
135136
control_dep_candidates.clear();
137+
control_dep_calls.clear();
136138
data_deps.clear();
137139
}
138140

@@ -147,7 +149,9 @@ class dep_graph_domaint:public ai_domain_baset
147149
"node_id must be valid");
148150

149151
DATA_INVARIANT(!has_values.is_true() ||
150-
(control_deps.empty() && data_deps.empty()),
152+
(control_deps.empty() &&
153+
control_dep_calls.empty() &&
154+
data_deps.empty()),
151155
"If the domain is top, it must have no dependencies");
152156

153157
return has_values.is_true();
@@ -159,7 +163,9 @@ class dep_graph_domaint:public ai_domain_baset
159163
"node_id must be valid");
160164

161165
DATA_INVARIANT(!has_values.is_false() ||
162-
(control_deps.empty() && data_deps.empty()),
166+
(control_deps.empty() &&
167+
control_dep_calls.empty() &&
168+
data_deps.empty()),
163169
"If the domain is bottom, it must have no dependencies");
164170

165171
return has_values.is_false();
@@ -190,6 +196,9 @@ class dep_graph_domaint:public ai_domain_baset
190196
typedef std::set<goto_programt::const_targett> control_dep_candidatest;
191197
control_dep_candidatest control_dep_candidates;
192198

199+
typedef std::set<goto_programt::const_targett> control_dep_callst;
200+
control_dep_callst control_dep_calls;
201+
193202
typedef std::map<goto_programt::const_targett, std::set<exprt>> data_depst;
194203
data_depst data_deps;
195204

@@ -211,7 +220,8 @@ class dep_graph_domaint:public ai_domain_baset
211220

212221
bool merge_control_dependencies(
213222
const control_depst &other_control_deps,
214-
const control_dep_candidatest &other_control_dep_candidates);
223+
const control_dep_candidatest &other_control_dep_candidates,
224+
const control_dep_callst &other_control_dep_calls);
215225
};
216226

217227
class dependence_grapht:

0 commit comments

Comments
 (0)