Skip to content

Commit 17951c8

Browse files
committed
Add path strategy chooser class
A new class is introduced to hold the names, descriptions and constructor thunks for all path exploration strategies. This provides a uniform way for strategy descriptions to be displayed, which can be done with the --show-symex-strategies flag.
1 parent 685937a commit 17951c8

8 files changed

+151
-31
lines changed

src/cbmc/bmc.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,7 @@ void bmct::setup_unwind()
598598
/// \param callback_after_symex: optional callback to be run after symex.
599599
/// See class member `bmct::driver_callback_after_symex` for details.
600600
int bmct::do_language_agnostic_bmc(
601+
const path_strategy_choosert &path_strategy_chooser,
601602
const optionst &opts,
602603
abstract_goto_modelt &model,
603604
const ui_message_handlert::uit &ui,
@@ -609,8 +610,12 @@ int bmct::do_language_agnostic_bmc(
609610
safety_checkert::resultt tmp_result = safety_checkert::resultt::UNKNOWN;
610611
const symbol_tablet &symbol_table = model.get_symbol_table();
611612
message_handlert &mh = message.get_message_handler();
612-
std::unique_ptr<path_storaget> worklist =
613-
path_storaget::make(path_storaget::disciplinet::FIFO);
613+
std::unique_ptr<path_storaget> worklist;
614+
std::string strategy = opts.get_option("exploration-strategy");
615+
INVARIANT(
616+
path_strategy_chooser.is_valid_strategy(strategy),
617+
"Front-end passed us invalid path strategy '" + strategy + "'");
618+
worklist = path_strategy_chooser.get(strategy);
614619
try
615620
{
616621
{

src/cbmc/bmc.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ class bmct:public safety_checkert
117117
}
118118

119119
static int do_language_agnostic_bmc(
120+
const path_strategy_choosert &path_strategy_chooser,
120121
const optionst &opts,
121122
abstract_goto_modelt &goto_model,
122123
const ui_message_handlert::uit &ui,
@@ -294,15 +295,17 @@ class path_explorert : public bmct
294295
"(no-unwinding-assertions)" \
295296
"(no-pretty-names)" \
296297
"(partial-loops)" \
297-
"(paths)" \
298+
"(paths):" \
299+
"(show-symex-strategies)" \
298300
"(depth):" \
299301
"(unwind):" \
300302
"(unwindset):" \
301303
"(graphml-witness):" \
302304
"(unwindset):"
303305

304306
#define HELP_BMC \
305-
" --paths explore paths one at a time\n" \
307+
" --paths [strategy] explore paths one at a time\n" \
308+
" --show-symex-strategies list strategies for use with --paths\n" \
306309
" --program-only only show program expression\n" \
307310
" --show-loops show the loops in the program\n" \
308311
" --depth nr limit search depth\n" \

src/cbmc/cbmc_parse_options.cpp

+16-5
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ cbmc_parse_optionst::cbmc_parse_optionst(int argc, const char **argv):
6868
parse_options_baset(CBMC_OPTIONS, argc, argv),
6969
xml_interfacet(cmdline),
7070
messaget(ui_message_handler),
71-
ui_message_handler(cmdline, "CBMC " CBMC_VERSION)
71+
ui_message_handler(cmdline, "CBMC " CBMC_VERSION),
72+
path_strategy_chooser()
7273
{
7374
}
7475

@@ -79,7 +80,8 @@ ::cbmc_parse_optionst::cbmc_parse_optionst(
7980
parse_options_baset(CBMC_OPTIONS+extra_options, argc, argv),
8081
xml_interfacet(cmdline),
8182
messaget(ui_message_handler),
82-
ui_message_handler(cmdline, "CBMC " CBMC_VERSION)
83+
ui_message_handler(cmdline, "CBMC " CBMC_VERSION),
84+
path_strategy_chooser()
8385
{
8486
}
8587

@@ -146,8 +148,13 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options)
146148
exit(CPROVER_EXIT_USAGE_ERROR);
147149
}
148150

149-
if(cmdline.isset("paths"))
150-
options.set_option("paths", true);
151+
if(cmdline.isset("show-symex-strategies"))
152+
{
153+
std::cout << path_strategy_chooser.show_strategies();
154+
exit(CPROVER_EXIT_SUCCESS);
155+
}
156+
157+
path_strategy_chooser.set_path_strategy_options(cmdline, options, *this);
151158

152159
if(cmdline.isset("program-only"))
153160
options.set_option("program-only", true);
@@ -531,7 +538,11 @@ int cbmc_parse_optionst::doit()
531538
return CPROVER_EXIT_SET_PROPERTIES_FAILED;
532539

533540
return bmct::do_language_agnostic_bmc(
534-
options, goto_model, ui_message_handler.get_ui(), *this);
541+
path_strategy_chooser,
542+
options,
543+
goto_model,
544+
ui_message_handler.get_ui(),
545+
*this);
535546
}
536547

537548
bool cbmc_parse_optionst::set_properties()

src/cbmc/cbmc_parse_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class cbmc_parse_optionst:
110110
protected:
111111
goto_modelt goto_model;
112112
ui_message_handlert ui_message_handler;
113+
const path_strategy_choosert path_strategy_chooser;
113114

114115
void eval_verbosity();
115116
void register_languages();

src/goto-symex/path_storage.cpp

+47-10
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,10 @@ Author: Kareem Khazem <[email protected]>
88

99
#include "path_storage.h"
1010

11-
std::unique_ptr<path_storaget>
12-
path_storaget::make(path_storaget::disciplinet discipline)
13-
{
14-
switch(discipline)
15-
{
16-
case path_storaget::disciplinet::FIFO:
17-
return std::unique_ptr<path_fifot>(new path_fifot());
18-
}
19-
UNREACHABLE;
20-
}
11+
#include <sstream>
12+
13+
#include <util/exit_codes.h>
14+
#include <util/make_unique.h>
2115

2216
path_storaget::patht &path_fifot::private_peek()
2317
{
@@ -41,3 +35,46 @@ std::size_t path_fifot::size() const
4135
{
4236
return paths.size();
4337
}
38+
39+
std::string path_strategy_choosert::show_strategies() const
40+
{
41+
std::stringstream ss;
42+
for(auto &pair : strategies)
43+
ss << pair.second.first;
44+
return ss.str();
45+
}
46+
47+
void path_strategy_choosert::set_path_strategy_options(
48+
const cmdlinet &cmdline,
49+
optionst &options,
50+
messaget &message) const
51+
{
52+
if(cmdline.isset("paths"))
53+
{
54+
options.set_option("paths", true);
55+
std::string strategy = cmdline.get_value("paths");
56+
if(!is_valid_strategy(strategy))
57+
{
58+
message.error() << "Unknown strategy '" << strategy
59+
<< "'. Pass the --show-symex-strategies flag to list "
60+
"available strategies."
61+
<< message.eom;
62+
exit(CPROVER_EXIT_USAGE_ERROR);
63+
}
64+
options.set_option("exploration-strategy", strategy);
65+
}
66+
else
67+
options.set_option("exploration-strategy", default_strategy());
68+
}
69+
70+
path_strategy_choosert::path_strategy_choosert()
71+
: strategies(
72+
{{"fifo",
73+
{" fifo next instruction is pushed before\n"
74+
" goto target; paths are popped in\n"
75+
" first-in, first-out order\n",
76+
[]() { // NOLINT(whitespace/braces)
77+
return util_make_unique<path_fifot>();
78+
}}}})
79+
{
80+
}

src/goto-symex/path_storage.h

+52-9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
#include "goto_symex_state.h"
99
#include "symex_target_equation.h"
1010

11+
#include <util/options.h>
12+
#include <util/cmdline.h>
13+
#include <util/ui_message.h>
14+
#include <util/invariant.h>
15+
1116
#include <memory>
1217

1318
/// \brief Storage for symbolic execution paths to be resumed later
@@ -19,13 +24,6 @@
1924
class path_storaget
2025
{
2126
public:
22-
/// \brief Derived types of path_storaget
23-
enum class disciplinet
24-
{
25-
/// path_fifot
26-
FIFO
27-
};
28-
2927
/// \brief Information saved at a conditional goto to resume execution
3028
struct patht
3129
{
@@ -43,8 +41,6 @@ class path_storaget
4341
}
4442
};
4543

46-
/// \brief Factory method for building a subtype of path_storaget
47-
static std::unique_ptr<path_storaget> make(disciplinet discipline);
4844
virtual ~path_storaget() = default;
4945

5046
/// \brief Reference to the next path to resume
@@ -103,4 +99,51 @@ class path_fifot : public path_storaget
10399
void private_pop() override;
104100
};
105101

102+
/// \brief Factory and information for path_storaget
103+
class path_strategy_choosert
104+
{
105+
public:
106+
path_strategy_choosert();
107+
108+
/// \brief suitable for displaying as a front-end help message
109+
std::string show_strategies() const;
110+
111+
/// \brief is there a factory constructor for the named strategy?
112+
bool is_valid_strategy(const std::string strategy) const
113+
{
114+
return strategies.find(strategy) != strategies.end();
115+
}
116+
117+
/// \brief Factory for a path_storaget
118+
///
119+
/// Ensure that path_strategy_choosert::is_valid_strategy() returns true for a
120+
/// particular string before calling this function on that string.
121+
std::unique_ptr<path_storaget> get(const std::string strategy) const
122+
{
123+
auto found = strategies.find(strategy);
124+
INVARIANT(
125+
found != strategies.end(), "Unknown strategy '" + strategy + "'.");
126+
return found->second.second();
127+
}
128+
129+
/// \brief add `paths` and `exploration-strategy` option, suitable to be
130+
/// invoked from front-ends.
131+
void
132+
set_path_strategy_options(const cmdlinet &, optionst &, messaget &) const;
133+
134+
protected:
135+
std::string default_strategy() const
136+
{
137+
return "fifo";
138+
}
139+
140+
/// Map from the name of a strategy (to be supplied on the command line), to
141+
/// the help text for that strategy and a factory thunk returning a pointer to
142+
/// a derived class of path_storaget that implements that strategy.
143+
std::map<const std::string,
144+
std::pair<const std::string,
145+
const std::function<std::unique_ptr<path_storaget>()>>>
146+
strategies;
147+
};
148+
106149
#endif /* CPROVER_GOTO_SYMEX_PATH_STORAGE_H */

src/jbmc/jbmc_parse_options.cpp

+20-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Author: Daniel Kroening, [email protected]
1616
#include <iostream>
1717
#include <memory>
1818

19+
#include <util/exit_codes.h>
1920
#include <util/string2int.h>
2021
#include <util/config.h>
2122
#include <util/unicode.h>
@@ -63,7 +64,8 @@ Author: Daniel Kroening, [email protected]
6364
jbmc_parse_optionst::jbmc_parse_optionst(int argc, const char **argv):
6465
parse_options_baset(JBMC_OPTIONS, argc, argv),
6566
messaget(ui_message_handler),
66-
ui_message_handler(cmdline, "JBMC " CBMC_VERSION)
67+
ui_message_handler(cmdline, "JBMC " CBMC_VERSION),
68+
path_strategy_chooser()
6769
{
6870
}
6971

@@ -73,7 +75,8 @@ ::jbmc_parse_optionst::jbmc_parse_optionst(
7375
const std::string &extra_options):
7476
parse_options_baset(JBMC_OPTIONS+extra_options, argc, argv),
7577
messaget(ui_message_handler),
76-
ui_message_handler(cmdline, "JBMC " CBMC_VERSION)
78+
ui_message_handler(cmdline, "JBMC " CBMC_VERSION),
79+
path_strategy_chooser()
7780
{
7881
}
7982

@@ -100,6 +103,14 @@ void jbmc_parse_optionst::get_command_line_options(optionst &options)
100103
exit(1); // should contemplate EX_USAGE from sysexits.h
101104
}
102105

106+
if(cmdline.isset("show-symex-strategies"))
107+
{
108+
std::cout << path_strategy_chooser.show_strategies();
109+
exit(CPROVER_EXIT_SUCCESS);
110+
}
111+
112+
path_strategy_chooser.set_path_strategy_options(cmdline, options, *this);
113+
103114
if(cmdline.isset("program-only"))
104115
options.set_option("program-only", true);
105116

@@ -533,7 +544,12 @@ int jbmc_parse_optionst::doit()
533544
// The `configure_bmc` callback passed will enable enum-unwind-static if
534545
// applicable.
535546
return bmct::do_language_agnostic_bmc(
536-
options, goto_model, ui_message_handler.get_ui(), *this, configure_bmc);
547+
path_strategy_chooser,
548+
options,
549+
goto_model,
550+
ui_message_handler.get_ui(),
551+
*this,
552+
configure_bmc);
537553
}
538554
else
539555
{
@@ -573,6 +589,7 @@ int jbmc_parse_optionst::doit()
573589
// applicable.
574590
return
575591
bmct::do_language_agnostic_bmc(
592+
path_strategy_chooser,
576593
options,
577594
lazy_goto_model,
578595
ui_message_handler.get_ui(),

src/jbmc/jbmc_parse_options.h

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ Author: Daniel Kroening, [email protected]
2727
#include <goto-programs/show_properties.h>
2828
#include <goto-instrument/cover.h>
2929

30+
#include <goto-symex/path_storage.h>
31+
3032
#include <java_bytecode/java_bytecode_language.h>
3133

3234
class bmct;
@@ -103,6 +105,7 @@ class jbmc_parse_optionst:
103105
protected:
104106
ui_message_handlert ui_message_handler;
105107
std::unique_ptr<cover_configt> cover_config;
108+
path_strategy_choosert path_strategy_chooser;
106109

107110
void eval_verbosity();
108111
void get_command_line_options(optionst &);

0 commit comments

Comments
 (0)