Skip to content

Commit 744f918

Browse files
authored
Merge pull request #2758 from nmanthey/upstream-slice-functions
Upstream slice functions
2 parents 273f375 + d86701c commit 744f918

File tree

14 files changed

+228
-13
lines changed

14 files changed

+228
-13
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
void a()
2+
{
3+
int e;
4+
}
5+
6+
void b()
7+
{
8+
double f;
9+
if(f == 0)
10+
a();
11+
}
12+
13+
void c()
14+
{
15+
int d;
16+
}
17+
18+
int main()
19+
{
20+
int k;
21+
if(k == 0)
22+
{
23+
int l;
24+
a();
25+
c();
26+
}
27+
else
28+
{
29+
b();
30+
}
31+
int n;
32+
a();
33+
return n;
34+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
--fp-reachability-slice c
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
1: ASSUME FALSE
7+
dead e;
8+
dead d;
9+
--
10+
^warning: ignoring
11+
dead f;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
void a()
2+
{
3+
int e;
4+
}
5+
6+
void b()
7+
{
8+
double f;
9+
if(f == 0)
10+
a();
11+
}
12+
13+
void c()
14+
{
15+
int d;
16+
}
17+
18+
int main()
19+
{
20+
int k;
21+
if(k == 0)
22+
{
23+
int l;
24+
a();
25+
c();
26+
}
27+
else
28+
{
29+
b();
30+
}
31+
int n;
32+
a();
33+
return n;
34+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--fp-reachability-slice a,c
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
dead d;
7+
dead e;
8+
--
9+
^warning: ignoring
10+
dead f;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
void a()
2+
{
3+
int e;
4+
}
5+
6+
void b()
7+
{
8+
double f;
9+
if(f == 0)
10+
a();
11+
}
12+
13+
void c()
14+
{
15+
int d;
16+
}
17+
18+
int main()
19+
{
20+
int k;
21+
if(k == 0)
22+
{
23+
int l;
24+
a();
25+
c();
26+
}
27+
else
28+
{
29+
b();
30+
}
31+
int n;
32+
a();
33+
return n;
34+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
--fp-reachability-slice b,c
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
1 file main.c line 34
7+
--
8+
^warning: ignoring
9+
dead d;
10+
dead e;
11+
dead f;

src/cbmc/cbmc_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,7 @@ void cbmc_parse_optionst::help()
940940
" --cover CC create test-suite with coverage criterion CC\n" // NOLINT(*)
941941
" --mm MM memory consistency model for concurrent programs\n" // NOLINT(*)
942942
HELP_REACHABILITY_SLICER
943+
HELP_REACHABILITY_SLICER_FB
943944
" --full-slice run full slicer (experimental)\n" // NOLINT(*)
944945
" --drop-unused-functions drop functions trivially unreachable from main function\n" // NOLINT(*)
945946
"\n"

src/goto-instrument/full_slicer_class.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,23 @@ class assert_criteriont:public slicing_criteriont
113113
}
114114
};
115115

116+
class in_function_criteriont : public slicing_criteriont
117+
{
118+
public:
119+
explicit in_function_criteriont(const std::string &function_name)
120+
: target_function(function_name)
121+
{
122+
}
123+
124+
virtual bool operator()(goto_programt::const_targett target)
125+
{
126+
return target->function == target_function;
127+
}
128+
129+
protected:
130+
const irep_idt target_function;
131+
};
132+
116133
class properties_criteriont:public slicing_criteriont
117134
{
118135
public:

src/goto-instrument/goto_instrument_parse_options.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,15 @@ void goto_instrument_parse_optionst::instrument_goto_program()
14301430
reachability_slicer(goto_model);
14311431
}
14321432

1433+
if(cmdline.isset("fp-reachability-slice"))
1434+
{
1435+
do_indirect_call_and_rtti_removal();
1436+
1437+
status() << "Performing a function pointer reachability slice" << eom;
1438+
function_path_reachability_slicer(
1439+
goto_model, cmdline.get_comma_separated_values("fp-reachability-slice"));
1440+
}
1441+
14331442
// full slice?
14341443
if(cmdline.isset("full-slice"))
14351444
{
@@ -1610,7 +1619,7 @@ void goto_instrument_parse_optionst::help()
16101619
" --render-cluster-function clusterises the dot by functions\n"
16111620
"\n"
16121621
"Slicing:\n"
1613-
" --reachability-slice slice away instructions that can't reach assertions\n" // NOLINT(*)
1622+
HELP_REACHABILITY_SLICER
16141623
" --full-slice slice away instructions that don't affect assertions\n" // NOLINT(*)
16151624
" --property id slice with respect to specific property only\n" // NOLINT(*)
16161625
" --slice-global-inits slice away initializations of unused global variables\n" // NOLINT(*)

src/goto-instrument/goto_instrument_parse_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ Author: Daniel Kroening, [email protected]
7171
"(show-struct-alignment)(interval-analysis)(show-intervals)" \
7272
"(show-uninitialized)(show-locations)" \
7373
"(full-slice)(reachability-slice)(slice-global-inits)" \
74+
"(fp-reachability-slice):" \
7475
"(inline)(partial-inline)(function-inline):(log):(no-caching)" \
7576
OPT_REMOVE_CONST_FUNCTION_POINTERS \
7677
"(print-internal-representation)" \

src/goto-instrument/reachability_slicer.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ Author: Daniel Kroening, [email protected]
1717

1818
#include <stack>
1919

20+
#include <goto-programs/cfg.h>
21+
#include <goto-programs/remove_calls_no_body.h>
2022
#include <goto-programs/remove_skip.h>
2123
#include <goto-programs/remove_unreachable.h>
22-
#include <goto-programs/cfg.h>
24+
25+
#include "util/message.h"
2326

2427
#include "full_slicer_class.h"
2528
#include "reachability_slicer_class.h"
@@ -91,8 +94,7 @@ void reachability_slicert::fixedpoint_to_assertions(
9194
"all function return edges should point to the successor of a "
9295
"FUNCTION_CALL instruction");
9396
stack.emplace_back(edge.first, true);
94-
stack.emplace_back(
95-
cfg.entry_map[std::prev(node.PC)], caller_is_known);
97+
stack.emplace_back(cfg.entry_map[std::prev(node.PC)], caller_is_known);
9698
}
9799
else if(pred_node.PC->is_function_call())
98100
{
@@ -193,7 +195,7 @@ void reachability_slicert::slice(goto_functionst &goto_functions)
193195
{
194196
Forall_goto_program_instructions(i_it, f_it->second.body)
195197
{
196-
const cfgt::nodet &e=cfg[cfg.entry_map[i_it]];
198+
cfgt::nodet &e = cfg[cfg.entry_map[i_it]];
197199
if(
198200
!e.reaches_assertion && !e.reachable_from_assertion &&
199201
!i_it->is_end_function())
@@ -240,6 +242,29 @@ void reachability_slicer(
240242
s(goto_model.goto_functions, p, include_forward_reachability);
241243
}
242244

245+
/// Perform reachability slicing on goto_model for selected functions.
246+
/// \param goto_model Goto program to slice
247+
/// \param functions_list The functions relevant for the slicing (i.e. starting
248+
/// point for the search in the CFG). Anything that is reachable in the CFG
249+
/// starting from these functions will be kept.
250+
void function_path_reachability_slicer(
251+
goto_modelt &goto_model,
252+
const std::list<std::string> &functions_list)
253+
{
254+
for(const auto &function : functions_list)
255+
{
256+
in_function_criteriont matching_criterion(function);
257+
reachability_slicert slicer;
258+
slicer(goto_model.goto_functions, matching_criterion, true);
259+
}
260+
261+
remove_calls_no_bodyt remove_calls_no_body;
262+
remove_calls_no_body(goto_model.goto_functions);
263+
264+
goto_model.goto_functions.update();
265+
goto_model.goto_functions.compute_loop_numbers();
266+
}
267+
243268
/// Perform reachability slicing on goto_model, with respect to criterion
244269
/// comprising all properties. Only instructions from which the criterion
245270
/// is reachable will be kept.

src/goto-instrument/reachability_slicer.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ void reachability_slicer(
2323
goto_modelt &,
2424
const std::list<std::string> &properties);
2525

26+
void function_path_reachability_slicer(
27+
goto_modelt &goto_model,
28+
const std::list<std::string> &functions_list);
29+
2630
void reachability_slicer(
2731
goto_modelt &,
2832
const bool include_forward_reachability);
@@ -33,13 +37,18 @@ void reachability_slicer(
3337
const bool include_forward_reachability);
3438

3539
// clang-format off
36-
#define OPT_REACHABILITY_SLICER \
37-
"(reachability-slice)(reachability-slice-fb)" // NOLINT(*)
38-
39-
#define HELP_REACHABILITY_SLICER \
40-
" --reachability-slice remove instructions that cannot appear on\n" \
41-
" a trace from entry point to a property\n" \
42-
" --reachability-slice-fb remove instructions that cannot appear on\n" \
43-
" a trace from entry point through a property\n" // NOLINT(*)
40+
#define OPT_REACHABILITY_SLICER \
41+
"(fp-reachability-slice):(reachability-slice)(reachability-slice-fb)" // NOLINT(*)
42+
43+
#define HELP_REACHABILITY_SLICER \
44+
" --fp-reachability-slice f remove instructions that cannot appear on a trace\n" \
45+
" that visits all given functions. The list of\n" \
46+
" functions has to be given as a comma separated\n" \
47+
" list f.\n" \
48+
" --reachability-slice remove instructions that cannot appear on a trace\n" \
49+
" from entry point to a property\n" // NOLINT(*)
50+
#define HELP_REACHABILITY_SLICER_FB \
51+
" --reachability-slice-fb remove instructions that cannot appear on a trace\n" \
52+
" from entry point through a property\n" // NOLINT(*)
4453
// clang-format on
4554
#endif // CPROVER_GOTO_INSTRUMENT_REACHABILITY_SLICER_H

src/util/cmdline.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,23 @@ const std::list<std::string> &cmdlinet::get_values(
118118
return immutable_empty_list;
119119
}
120120

121+
std::list<std::string>
122+
cmdlinet::get_comma_separated_values(const char *option) const
123+
{
124+
std::list<std::string> separated_values;
125+
auto i = getoptnr(option);
126+
if(i.has_value() && !options[*i].values.empty())
127+
{
128+
std::istringstream values_stream(options[*i].values.front());
129+
std::string single_value;
130+
while(std::getline(values_stream, single_value, ','))
131+
{
132+
separated_values.push_back(single_value);
133+
}
134+
}
135+
return separated_values;
136+
}
137+
121138
optionalt<std::size_t> cmdlinet::getoptnr(char option) const
122139
{
123140
for(std::size_t i=0; i<options.size(); i++)

src/util/cmdline.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class cmdlinet
2727
const std::list<std::string> &get_values(const std::string &option) const;
2828
const std::list<std::string> &get_values(char option) const;
2929

30+
std::list<std::string> get_comma_separated_values(const char *option) const;
31+
3032
virtual bool isset(char option) const;
3133
virtual bool isset(const char *option) const;
3234
virtual void set(const std::string &option);

0 commit comments

Comments
 (0)