Skip to content

Commit 409d802

Browse files
Merge pull request diffblue#265 from danpoe/feature/cyclic-dependency-analysis-vs
Cyclic variable sensitivity dependency analysis
2 parents e140339 + 8c6ee64 commit 409d802

File tree

7 files changed

+235
-6
lines changed

7 files changed

+235
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
int x;
2+
int y;
3+
4+
void main(void)
5+
{
6+
x = y;
7+
y = 1;
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
--show --dependence-graph-vs --periodic-task --json -
4+
activate-multi-line-match
5+
EXIT=0
6+
SIGNAL=0
7+
"task": "first"
8+
"task": "later"
9+
"expression": "y"
10+
--
11+
^warning: ignoring
12+
"expression": "x"
13+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
int g_x;
2+
int g_y;
3+
4+
int x;
5+
int y;
6+
7+
void main(void)
8+
{
9+
g_x = g_y;
10+
x = y;
11+
12+
g_y = 1;
13+
y = 1;
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
--show --dependence-graph-vs --periodic-task --json -
4+
activate-multi-line-match
5+
EXIT=0
6+
SIGNAL=0
7+
"line": "2",\n.*\n.*\n\s*"task": "first"
8+
"line": "12",\n.*\n.*\n\s*"task": "later"
9+
"line": "5",\n.*\n.*\n\s*"task": "first"
10+
"line": "13",\n.*\n.*\n\s*"task": "later"
11+
--
12+
^warning: ignoring
13+
--

src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp

+79
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,85 @@ jsont variable_sensitivity_dependence_domaint::output_json(
520520
return graph;
521521
}
522522

523+
jsont variable_sensitivity_dependence_domaint::output_json_additional(
524+
const namespacet &ns,
525+
const variable_sensitivity_dependence_domaint &base_state) const
526+
{
527+
json_arrayt graph;
528+
529+
for(const auto &cd : control_deps)
530+
{
531+
const goto_programt::const_targett target=cd.first;
532+
const tvt branch=cd.second;
533+
534+
json_objectt &link=graph.push_back().make_object();
535+
536+
link["locationNumber"]=
537+
json_numbert(std::to_string(target->location_number));
538+
link["sourceLocation"]=json(target->source_location);
539+
link["type"]=json_stringt("control");
540+
link["branch"]=json_stringt(branch.to_string());
541+
}
542+
543+
for(const auto &target : control_dep_calls)
544+
{
545+
json_objectt &link=graph.push_back().make_object();
546+
link["locationNumber"]=
547+
json_numbert(std::to_string(target->location_number));
548+
link["sourceLocation"]=json(target->source_location);
549+
link["type"]=json_stringt("control");
550+
link["branch"]=json_stringt("UNCONDITIONAL");
551+
}
552+
553+
for(const auto &dep : base_state.domain_data_deps)
554+
{
555+
json_objectt &link=graph.push_back().make_object();
556+
link["locationNumber"]=
557+
json_numbert(std::to_string(dep.first->location_number));
558+
link["sourceLocation"]=json(dep.first->source_location);
559+
json_stringt(dep.first->source_location.as_string());
560+
link["type"]=json_stringt("data");
561+
link["task"]=json_stringt("first");
562+
563+
const std::set<exprt> &expr_set=dep.second;
564+
json_arrayt &expressions=link["expressions"].make_array();
565+
566+
for(const exprt &e : expr_set)
567+
{
568+
json_objectt &object=expressions.push_back().make_object();
569+
object["expression"]=json_stringt(from_expr(ns, "", e));
570+
object["certainty"]=json_stringt("maybe");
571+
}
572+
}
573+
574+
for(const auto &dep : domain_data_deps)
575+
{
576+
if(base_state.domain_data_deps.find(dep.first) !=
577+
base_state.domain_data_deps.end())
578+
continue;
579+
580+
json_objectt &link=graph.push_back().make_object();
581+
link["locationNumber"]=
582+
json_numbert(std::to_string(dep.first->location_number));
583+
link["sourceLocation"]=json(dep.first->source_location);
584+
json_stringt(dep.first->source_location.as_string());
585+
link["type"]=json_stringt("data");
586+
link["task"]=json_stringt("later");
587+
588+
const std::set<exprt> &expr_set=dep.second;
589+
json_arrayt &expressions=link["expressions"].make_array();
590+
591+
for(const exprt &e : expr_set)
592+
{
593+
json_objectt &object=expressions.push_back().make_object();
594+
object["expression"]=json_stringt(from_expr(ns, "", e));
595+
object["certainty"]=json_stringt("maybe");
596+
}
597+
}
598+
599+
return graph;
600+
}
601+
523602
void variable_sensitivity_dependence_domaint::populate_dep_graph(
524603
variable_sensitivity_dependence_grapht &dep_graph,
525604
goto_programt::const_targett this_loc) const

src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h

+71
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ class variable_sensitivity_dependence_domaint:
132132
const ai_baset &ai,
133133
const namespacet &ns) const override;
134134

135+
jsont output_json_additional(
136+
const namespacet &ns,
137+
const variable_sensitivity_dependence_domaint &base_state) const;
138+
135139
void populate_dep_graph(
136140
variable_sensitivity_dependence_grapht &,
137141
goto_programt::const_targett) const;
@@ -259,6 +263,73 @@ class variable_sensitivity_dependence_grapht:
259263
return entry.first->second;
260264
}
261265

266+
// output json, and mark additional data dependencies in this dependence graph
267+
// compared to the given `base`
268+
jsont output_json_additional(
269+
const goto_modelt &goto_model,
270+
const variable_sensitivity_dependence_grapht &base) const
271+
{
272+
const namespacet ns(goto_model.symbol_table);
273+
274+
json_objectt result;
275+
276+
forall_goto_functions(f_it, goto_model.goto_functions)
277+
{
278+
if(f_it->second.body_available())
279+
{
280+
result[id2string(f_it->first)]=
281+
output_json_additional(ns, f_it->second.body, f_it->first, base);
282+
}
283+
else
284+
{
285+
result[id2string(f_it->first)]=json_arrayt();
286+
}
287+
}
288+
289+
return result;
290+
}
291+
292+
jsont output_json_additional(
293+
const namespacet &ns,
294+
const goto_programt &goto_program,
295+
const irep_idt &identifier,
296+
const variable_sensitivity_dependence_grapht &base) const
297+
{
298+
json_arrayt contents;
299+
300+
forall_goto_program_instructions(i_it, goto_program)
301+
{
302+
json_objectt location;
303+
location["locationNumber"]=
304+
json_numbert(std::to_string(i_it->location_number));
305+
location["sourceLocation"]=
306+
json_stringt(i_it->source_location.as_string());
307+
308+
// state of this
309+
const statet &state = find_state(i_it);
310+
const variable_sensitivity_dependence_domaint &dep_graph_state =
311+
static_cast<const variable_sensitivity_dependence_domaint &>(state);
312+
313+
// state of base
314+
const statet &base_state = base.find_state(i_it);
315+
const variable_sensitivity_dependence_domaint &base_dep_graph_state =
316+
static_cast<const variable_sensitivity_dependence_domaint &>(base_state);
317+
318+
location["abstractState"]=dep_graph_state.output_json_additional(
319+
ns,
320+
base_dep_graph_state);
321+
322+
// Ideally we need output_instruction_json
323+
std::ostringstream out;
324+
goto_program.output_instruction(ns, identifier, out, *i_it);
325+
location["instruction"]=json_stringt(out.str());
326+
327+
contents.push_back(location);
328+
}
329+
330+
return contents;
331+
}
332+
262333
post_dominators_mapt &cfg_post_dominators()
263334
{
264335
return post_dominators;

src/goto-analyzer/goto_analyzer_parse_options.cpp

+37-6
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options)
344344
{
345345
options.set_option("dependence-graph-vs", true);
346346
options.set_option("domain set", true);
347+
options.set_option("periodic-task", cmdline.isset("periodic-task"));
347348

348349
// Configuration of variable sensitivity domain
349350
options.set_option("pointers", cmdline.isset("pointers"));
@@ -777,6 +778,13 @@ int goto_analyzer_parse_optionst::perform_analysis(const optionst &options)
777778
if(options.get_bool_option("dependence-graph") &&
778779
options.get_bool_option("periodic-task"))
779780
{
781+
if(!options.get_bool_option("json"))
782+
{
783+
error() << "Must use json output via --json with --periodic-task"
784+
<< eom;
785+
return CPROVER_EXIT_INTERNAL_ERROR;
786+
}
787+
780788
namespacet ns(goto_model.symbol_table);
781789

782790
dependence_grapht dg_base(goto_model.goto_functions, ns, false);
@@ -785,16 +793,39 @@ int goto_analyzer_parse_optionst::perform_analysis(const optionst &options)
785793
dependence_grapht dg_periodic(goto_model.goto_functions, ns, true);
786794
dg_periodic(goto_model);
787795

788-
if(options.get_bool_option("json"))
789-
{
790-
out << dg_periodic.output_json_additional(goto_model, dg_base);
791-
}
792-
else
796+
out << dg_periodic.output_json_additional(goto_model, dg_base);
797+
798+
return CPROVER_EXIT_SUCCESS;
799+
}
800+
801+
// special case for variable sensitivity dependence graph with the
802+
// assumption of periodic tasks for now
803+
if(options.get_bool_option("dependence-graph-vs") &&
804+
options.get_bool_option("periodic-task"))
805+
{
806+
if(!options.get_bool_option("json"))
793807
{
794-
error() << "Must use json output via --json with --periodic-task" << eom;
808+
error() << "Must use json output via --json with --periodic-task"
809+
<< eom;
795810
return CPROVER_EXIT_INTERNAL_ERROR;
796811
}
797812

813+
namespacet ns(goto_model.symbol_table);
814+
815+
variable_sensitivity_dependence_grapht dg_vs_base(
816+
goto_model.goto_functions,
817+
ns,
818+
ai_configt::from_options(options).with_periodic_task(false));
819+
dg_vs_base(goto_model);
820+
821+
variable_sensitivity_dependence_grapht dg_vs_periodic(
822+
goto_model.goto_functions,
823+
ns,
824+
ai_configt::from_options(options).with_periodic_task(true));
825+
dg_vs_periodic(goto_model);
826+
827+
out << dg_vs_periodic.output_json_additional(goto_model, dg_vs_base);
828+
798829
return CPROVER_EXIT_SUCCESS;
799830
}
800831

0 commit comments

Comments
 (0)