Skip to content

Commit dbc874e

Browse files
authored
Merge pull request #6510 from tautschnig/thread-unwind
Document and test thread-specific unwindset option
2 parents 718b547 + a9ae449 commit dbc874e

File tree

10 files changed

+76
-30
lines changed

10 files changed

+76
-30
lines changed

doc/cprover-manual/cbmc-unwinding.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,12 @@ first use:
9090
to obtain a list of all loops in the program. Then identify the loops
9191
you need to set a separate bound for, and note their loop ID. Then use:
9292

93-
--unwindset L:B
93+
--unwindset [T:]L:B
9494

95-
where `L` denotes a loop ID and `B` denotes the bound for that loop. The
96-
option can be given multiple times.
95+
where `L` denotes a loop ID and `B` denotes the bound for that loop in thread T,
96+
if a thread number is included. The initial thread has index 0, and threads are
97+
consecutively numbered in program order of threads being spawned. The
98+
`--unwindset` option can be given multiple times.
9799

98100
As an example, consider a program with two loops in the function main:
99101

doc/man/cbmc.1

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,12 @@ Only show program expression
137137
Limit search depth
138138
.IP "--unwind nr "
139139
Unwind loops nr times
140-
.IP "--unwindset L:B,..."
141-
Unwind loop L with a bound of B (use \-\-show\-loops to get the loop IDs)
140+
.IP "--unwindset [T:]L:B,..."
141+
Unwind loop L with a bound of B, optionally restricted to thread T. Use
142+
\-\-show\-loops to get the loop IDs. Thread numbers are set as follows: The
143+
initial thread has index 0, and threads are consecutively numbered in program
144+
order of threads being spawned. The`--unwindset` option can be given multiple
145+
times.
142146
.IP --show-vcc
143147
Show the verification conditions
144148
.IP --slice-formula
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
void *thr1(void *arg)
2+
{
3+
for(int i = 0; i < *(int *)arg; ++i)
4+
;
5+
6+
return 0;
7+
}
8+
9+
int l1 = 1;
10+
int l2 = 2;
11+
12+
int main()
13+
{
14+
__CPROVER_ASYNC_1:
15+
thr1(&l1);
16+
__CPROVER_ASYNC_2:
17+
thr1(&l2);
18+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--unwindset 1:thr1.0:2,2:thr1.0:3 --unwinding-assertions
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring

src/goto-checker/bmc_util.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Author: Daniel Kroening, Peter Schrammel
1717

1818
#include <goto-symex/build_goto_trace.h>
1919

20+
#include <goto-instrument/unwindset.h>
21+
2022
#include "incremental_goto_checker.h"
2123
#include "properties.h"
2224

@@ -172,7 +174,6 @@ void run_property_decider(
172174
#define OPT_BMC \
173175
"(program-only)" \
174176
"(show-byte-ops)" \
175-
"(show-loops)" \
176177
"(show-vcc)" \
177178
"(show-goto-symex-steps)" \
178179
"(show-points-to-sets)" \
@@ -185,18 +186,17 @@ void run_property_decider(
185186
"(paths):" \
186187
"(show-symex-strategies)" \
187188
"(depth):" \
188-
"(unwind):" \
189189
"(max-field-sensitivity-array-size):" \
190190
"(no-array-field-sensitivity)" \
191191
"(graphml-witness):" \
192-
"(unwindset):" \
193192
"(symex-complexity-limit):" \
194193
"(symex-complexity-failed-child-loops-limit):" \
195194
"(incremental-loop):" \
196195
"(unwind-min):" \
197196
"(unwind-max):" \
198197
"(ignore-properties-before-unwind-min)" \
199198
"(symex-cache-dereferences)" \
199+
OPT_UNWINDSET \
200200

201201
#define HELP_BMC \
202202
" --paths [strategy] explore paths one at a time\n" \
@@ -207,7 +207,6 @@ void run_property_decider(
207207
" pointer dereference. Requires --json-ui.\n" \
208208
" --program-only only show program expression\n" \
209209
" --show-byte-ops show all byte extracts and updates\n" \
210-
" --show-loops show the loops in the program\n" \
211210
" --depth nr limit search depth\n" \
212211
" --max-field-sensitivity-array-size M\n" \
213212
" maximum size M of arrays for which field\n" \
@@ -218,9 +217,7 @@ void run_property_decider(
218217
"this is\n" \
219218
" equivalent to setting the maximum field \n" \
220219
" sensitivity size for arrays to 0\n" \
221-
" --unwind nr unwind nr times\n" \
222-
" --unwindset L:B,... unwind loop L with a bound of B\n" \
223-
" (use --show-loops to get the loop IDs)\n" \
220+
HELP_UNWINDSET \
224221
" --incremental-loop L check properties after each unwinding\n" \
225222
" of loop L\n" \
226223
" (use --show-loops to get the loop IDs)\n" \

src/goto-checker/module_dependencies.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
cbmc # symex_bmc will be moved next
22
goto-checker
3+
goto-instrument
34
goto-programs
45
goto-symex
56
linking

src/goto-instrument/goto_instrument_parse_options.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ Author: Daniel Kroening, [email protected]
108108
#include "thread_instrumentation.h"
109109
#include "undefined_functions.h"
110110
#include "unwind.h"
111-
#include "unwindset.h"
112111
#include "value_set_fi_fp_removal.h"
113112

114113
/// invoke main modules
@@ -1726,7 +1725,6 @@ void goto_instrument_parse_optionst::help()
17261725
HELP_DUMP_C
17271726
"\n"
17281727
"Diagnosis:\n"
1729-
" --show-loops show the loops in the program\n"
17301728
HELP_SHOW_PROPERTIES
17311729
" --show-symbol-table show loaded symbol table\n"
17321730
" --list-symbols list symbols with type information\n"
@@ -1763,8 +1761,7 @@ void goto_instrument_parse_optionst::help()
17631761
"\n"
17641762
"Semantic transformations:\n"
17651763
<< HELP_NONDET_VOLATILE <<
1766-
" --unwind <n> unwinds the loops <n> times\n"
1767-
" --unwindset L:B,... unwind loop L with a bound of B\n"
1764+
HELP_UNWINDSET
17681765
" --unwindset-file <file> read unwindset from file\n"
17691766
" --partial-loops permit paths with partial loops\n"
17701767
" --unwinding-assertions generate unwinding assertions\n"

src/goto-instrument/goto_instrument_parse_options.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Author: Daniel Kroening, [email protected]
4141
#include "nondet_volatile.h"
4242
#include "replace_calls.h"
4343
#include "uninitialized.h"
44+
#include "unwindset.h"
4445
#include "wmm/weak_memory.h"
4546

4647
// clang-format off
@@ -54,7 +55,8 @@ Author: Daniel Kroening, [email protected]
5455
OPT_UNINITIALIZED_CHECK \
5556
OPT_WMM \
5657
"(race-check)" \
57-
"(unwind):(unwindset):(unwindset-file):" \
58+
OPT_UNWINDSET \
59+
"(unwindset-file):" \
5860
"(unwinding-assertions)(partial-loops)(continue-as-loops)" \
5961
"(log):" \
6062
"(call-graph)(reachable-call-graph)" \
@@ -86,7 +88,7 @@ Author: Daniel Kroening, [email protected]
8688
OPT_TIMESTAMP \
8789
"(show-natural-loops)(show-lexical-loops)(accelerate)(havoc-loops)" \
8890
"(string-abstraction)" \
89-
"(verbosity):(version)(xml-ui)(json-ui)(show-loops)" \
91+
"(verbosity):(version)(xml-ui)(json-ui)" \
9092
"(accelerate)(constant-propagator)" \
9193
"(k-induction):(step-case)(base-case)" \
9294
"(show-call-sequences)(check-call-sequence)" \

src/goto-instrument/unwindset.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,26 @@ void unwindsett::parse_unwind(const std::string &unwind)
2525

2626
void unwindsett::parse_unwindset_one_loop(std::string val)
2727
{
28-
unsigned thread_nr = 0;
29-
bool thread_nr_set = false;
28+
if(val.empty())
29+
return;
3030

31-
if(!val.empty() && isdigit(val[0]) && val.find(":") != std::string::npos)
31+
optionalt<unsigned> thread_nr;
32+
if(isdigit(val[0]))
3233
{
33-
std::string nr = val.substr(0, val.find(":"));
34-
thread_nr = unsafe_string2unsigned(nr);
35-
thread_nr_set = true;
36-
val.erase(0, nr.size() + 1);
34+
auto c_pos = val.find(':');
35+
if(c_pos != std::string::npos)
36+
{
37+
std::string nr = val.substr(0, c_pos);
38+
thread_nr = unsafe_string2unsigned(nr);
39+
val.erase(0, nr.size() + 1);
40+
}
3741
}
3842

39-
if(val.rfind(":") != std::string::npos)
43+
auto last_c_pos = val.rfind(':');
44+
if(last_c_pos != std::string::npos)
4045
{
41-
std::string id = val.substr(0, val.rfind(":"));
42-
std::string uw_string = val.substr(val.rfind(":") + 1);
46+
std::string id = val.substr(0, last_c_pos);
47+
std::string uw_string = val.substr(last_c_pos + 1);
4348

4449
// the below initialisation makes g++-5 happy
4550
optionalt<unsigned> uw(0);
@@ -49,8 +54,8 @@ void unwindsett::parse_unwindset_one_loop(std::string val)
4954
else
5055
uw = unsafe_string2unsigned(uw_string);
5156

52-
if(thread_nr_set)
53-
thread_loop_map[std::pair<irep_idt, unsigned>(id, thread_nr)] = uw;
57+
if(thread_nr.has_value())
58+
thread_loop_map[std::pair<irep_idt, unsigned>(id, *thread_nr)] = uw;
5459
else
5560
loop_map[id] = uw;
5661
}

src/goto-instrument/unwindset.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,16 @@ class unwindsett
5656
void parse_unwindset_one_loop(std::string loop_limit);
5757
};
5858

59+
#define OPT_UNWINDSET \
60+
"(show-loops)" \
61+
"(unwind):" \
62+
"(unwindset):"
63+
64+
#define HELP_UNWINDSET \
65+
" --show-loops show the loops in the program\n" \
66+
" --unwind nr unwind nr times\n" \
67+
" --unwindset [T:]L:B,... unwind loop L with a bound of B\n" \
68+
" (optionally restricted to thread T)\n" \
69+
" (use --show-loops to get the loop IDs)\n"
70+
5971
#endif // CPROVER_GOTO_INSTRUMENT_UNWINDSET_H

0 commit comments

Comments
 (0)