Skip to content

Commit c88a3ab

Browse files
committed
[path explore 4/7] Factor out common BMC code
The CBMC and JBMC frontends included identical code for running BMC after the language-specific preprocessing. This commit moves that common code into a static method of bmct. Parse options and help text related to bounded model checking are defined in bmc.h.
1 parent d7a70e1 commit c88a3ab

File tree

6 files changed

+161
-178
lines changed

6 files changed

+161
-178
lines changed

src/cbmc/bmc.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@ Author: Daniel Kroening, [email protected]
1212
#include "bmc.h"
1313

1414
#include <chrono>
15+
#include <exception>
1516
#include <fstream>
1617
#include <iostream>
1718
#include <memory>
1819

20+
#include <util/exit_codes.h>
1921
#include <util/string2int.h>
2022
#include <util/source_location.h>
2123
#include <util/string_utils.h>
24+
#include <util/memory_info.h>
2225
#include <util/message.h>
2326
#include <util/json.h>
2427
#include <util/cprover_prefix.h>
@@ -37,6 +40,7 @@ Author: Daniel Kroening, [email protected]
3740
#include <goto-symex/memory_model_tso.h>
3841
#include <goto-symex/memory_model_pso.h>
3942

43+
#include "cbmc_solvers.h"
4044
#include "counterexample_beautification.h"
4145
#include "fault_localization.h"
4246

@@ -595,3 +599,67 @@ void bmct::setup_unwind()
595599
if(options.get_option("unwind")!="")
596600
symex.set_unwind_limit(options.get_unsigned_int_option("unwind"));
597601
}
602+
603+
int bmct::do_language_agnostic_bmc(
604+
const optionst &opts,
605+
const goto_modelt &goto_model,
606+
const ui_message_handlert::uit &ui,
607+
messaget &message,
608+
std::function<void(bmct &, const goto_modelt &)> frontend_configure_bmc)
609+
{
610+
cbmc_solverst solvers(
611+
opts, goto_model.symbol_table, message.get_message_handler());
612+
solvers.set_ui(ui);
613+
std::unique_ptr<cbmc_solverst::solvert> solver;
614+
try
615+
{
616+
solver = solvers.get_solver();
617+
}
618+
catch(const char *error_msg)
619+
{
620+
message.error() << error_msg << message.eom;
621+
return CPROVER_EXIT_EXCEPTION;
622+
}
623+
catch(const std::string &error_msg)
624+
{
625+
message.error() << error_msg << message.eom;
626+
return CPROVER_EXIT_EXCEPTION;
627+
}
628+
catch(...)
629+
{
630+
message.error() << "unable to get solver" << message.eom;
631+
throw std::current_exception();
632+
}
633+
634+
bmct bmc(
635+
opts,
636+
goto_model.symbol_table,
637+
message.get_message_handler(),
638+
solver->prop_conv());
639+
640+
frontend_configure_bmc(bmc, goto_model);
641+
bmc.set_ui(ui);
642+
643+
int result = CPROVER_EXIT_INTERNAL_ERROR;
644+
645+
// do actual BMC
646+
switch(bmc.run(goto_model.goto_functions))
647+
{
648+
case safety_checkert::resultt::SAFE:
649+
result = CPROVER_EXIT_VERIFICATION_SAFE;
650+
break;
651+
case safety_checkert::resultt::UNSAFE:
652+
result = CPROVER_EXIT_VERIFICATION_UNSAFE;
653+
break;
654+
case safety_checkert::resultt::ERROR:
655+
result = CPROVER_EXIT_INTERNAL_ERROR;
656+
break;
657+
}
658+
659+
// let's log some more statistics
660+
message.debug() << "Memory consumption:" << messaget::endl;
661+
memory_info(message.debug());
662+
message.debug() << eom;
663+
664+
return result;
665+
}

src/cbmc/bmc.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Author: Daniel Kroening, [email protected]
2828
#include <goto-programs/goto_trace.h>
2929

3030
#include <goto-symex/symex_target_equation.h>
31+
#include <goto-programs/goto_model.h>
3132
#include <goto-programs/safety_checker.h>
3233
#include <goto-symex/memory_model.h>
3334

@@ -82,6 +83,25 @@ class bmct:public safety_checkert
8283
symex.add_recursion_unwind_handler(handler);
8384
}
8485

86+
/// \brief common BMC code, invoked from language-specific frontends
87+
///
88+
/// Do bounded model-checking after all language-specific program
89+
/// preprocessing has been completed by language-specific frontends.
90+
/// Language-specific frontends may customize the \ref bmct objects
91+
/// that are used for model-checking by supplying a function object to
92+
/// the `frontend_configure_bmc` parameter of this function; the
93+
/// function object will be called with every \ref bmct object that
94+
/// is constructed by `do_language_agnostic_bmc`.
95+
static int do_language_agnostic_bmc(
96+
const optionst &opts,
97+
const goto_modelt &goto_model,
98+
const ui_message_handlert::uit &ui,
99+
messaget &message,
100+
std::function<void(bmct &, const goto_modelt &)> frontend_configure_bmc =
101+
[](bmct &_bmc, const goto_modelt &) { // NOLINT (*)
102+
// Empty default implementation
103+
});
104+
85105
protected:
86106
const optionst &options;
87107
symbol_tablet new_symbol_table;
@@ -144,6 +164,36 @@ class bmct:public safety_checkert
144164
template <template <class goalt> class covert>
145165
friend class bmc_goal_covert;
146166
friend class fault_localizationt;
167+
168+
#define OPT_BMC \
169+
"(program-only)" \
170+
"(show-loops)" \
171+
"(show-vcc)" \
172+
"(slice-formula)" \
173+
"(unwinding-assertions)" \
174+
"(no-unwinding-assertions)" \
175+
"(no-pretty-names)" \
176+
"(partial-loops)" \
177+
"(depth):" \
178+
"(unwind):" \
179+
"(unwindset):" \
180+
"(graphml-witness):" \
181+
"(unwindset):"
182+
183+
#define HELP_BMC \
184+
" --program-only only show program expression\n" \
185+
" --show-loops show the loops in the program\n" \
186+
" --depth nr limit search depth\n" \
187+
" --unwind nr unwind nr times\n" \
188+
" --unwindset L:B,... unwind loop L with a bound of B\n" \
189+
" (use --show-loops to get the loop IDs)\n" \
190+
" --show-vcc show the verification conditions\n" \
191+
" --slice-formula remove assignments unrelated to property\n" \
192+
" --unwinding-assertions generate unwinding assertions\n" \
193+
" --partial-loops permit paths with partial loops\n" \
194+
" --no-pretty-names do not simplify identifiers\n" \
195+
" --graphml-witness filename write the witness in GraphML format to " \
196+
"filename\n" // NOLINT(*)
147197
};
148198

149199
#endif // CPROVER_CBMC_BMC_H

src/cbmc/cbmc_parse_options.cpp

Lines changed: 5 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ Author: Daniel Kroening, [email protected]
1919
#include <util/string2int.h>
2020
#include <util/config.h>
2121
#include <util/unicode.h>
22-
#include <util/memory_info.h>
2322
#include <util/invariant.h>
2423
#include <util/exit_codes.h>
2524

@@ -63,8 +62,6 @@ Author: Daniel Kroening, [email protected]
6362

6463
#include <langapi/mode.h>
6564

66-
#include "cbmc_solvers.h"
67-
#include "bmc.h"
6865
#include "version.h"
6966
#include "xml_interface.h"
7067

@@ -373,13 +370,13 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options)
373370
}
374371
else
375372
{
376-
assert(options.get_bool_option("smt2"));
373+
PRECONDITION(options.get_bool_option("smt2"));
377374
options.set_option("z3", true), solver_set=true;
378375
}
379376
}
380377
}
381378
// Either have solver and standard version set, or neither.
382-
assert(version_set==solver_set);
379+
PRECONDITION(version_set == solver_set);
383380

384381
if(cmdline.isset("beautify"))
385382
options.set_option("beautify", true);
@@ -542,36 +539,8 @@ int cbmc_parse_optionst::doit()
542539
if(set_properties())
543540
return CPROVER_EXIT_SET_PROPERTIES_FAILED;
544541

545-
// get solver
546-
cbmc_solverst cbmc_solvers(
547-
options,
548-
goto_model.symbol_table,
549-
get_message_handler());
550-
cbmc_solvers.set_ui(ui_message_handler.get_ui());
551-
552-
std::unique_ptr<cbmc_solverst::solvert> cbmc_solver;
553-
554-
try
555-
{
556-
cbmc_solver=cbmc_solvers.get_solver();
557-
}
558-
559-
catch(const char *error_msg)
560-
{
561-
error() << error_msg << eom;
562-
return CPROVER_EXIT_EXCEPTION;
563-
}
564-
565-
prop_convt &prop_conv=cbmc_solver->prop_conv();
566-
567-
bmct bmc(
568-
options,
569-
goto_model.symbol_table,
570-
get_message_handler(),
571-
prop_conv);
572-
573-
// do actual BMC
574-
return do_bmc(bmc);
542+
return bmct::do_language_agnostic_bmc(
543+
options, goto_model, ui_message_handler.get_ui(), *this);
575544
}
576545

577546
bool cbmc_parse_optionst::set_properties()
@@ -871,35 +840,6 @@ bool cbmc_parse_optionst::process_goto_program(
871840
return false;
872841
}
873842

874-
/// invoke main modules
875-
int cbmc_parse_optionst::do_bmc(bmct &bmc)
876-
{
877-
bmc.set_ui(ui_message_handler.get_ui());
878-
879-
int result = CPROVER_EXIT_INTERNAL_ERROR;
880-
881-
// do actual BMC
882-
switch(bmc.run(goto_model.goto_functions))
883-
{
884-
case safety_checkert::resultt::SAFE:
885-
result = CPROVER_EXIT_VERIFICATION_SAFE;
886-
break;
887-
case safety_checkert::resultt::UNSAFE:
888-
result = CPROVER_EXIT_VERIFICATION_UNSAFE;
889-
break;
890-
case safety_checkert::resultt::ERROR:
891-
result = CPROVER_EXIT_INTERNAL_ERROR;
892-
break;
893-
}
894-
895-
// let's log some more statistics
896-
debug() << "Memory consumption:" << messaget::endl;
897-
memory_info(debug());
898-
debug() << eom;
899-
900-
return result;
901-
}
902-
903843
/// display command line help
904844
void cbmc_parse_optionst::help()
905845
{
@@ -989,18 +929,7 @@ void cbmc_parse_optionst::help()
989929
" --nondet-static add nondeterministic initialization of variables with static lifetime\n"
990930
"\n"
991931
"BMC options:\n"
992-
" --program-only only show program expression\n"
993-
" --show-loops show the loops in the program\n"
994-
" --depth nr limit search depth\n"
995-
" --unwind nr unwind nr times\n"
996-
" --unwindset L:B,... unwind loop L with a bound of B\n"
997-
" (use --show-loops to get the loop IDs)\n"
998-
" --show-vcc show the verification conditions\n"
999-
" --slice-formula remove assignments unrelated to property\n"
1000-
" --unwinding-assertions generate unwinding assertions\n"
1001-
" --partial-loops permit paths with partial loops\n"
1002-
" --no-pretty-names do not simplify identifiers\n"
1003-
" --graphml-witness filename write the witness in GraphML format to filename\n" // NOLINT(*)
932+
HELP_BMC
1004933
"\n"
1005934
"Backend options:\n"
1006935
" --object-bits n number of bits used for object addresses\n"

src/cbmc/cbmc_parse_options.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Author: Daniel Kroening, [email protected]
2222

2323
#include <goto-programs/goto_trace.h>
2424

25+
#include "bmc.h"
2526
#include "xml_interface.h"
2627

2728
class bmct;
@@ -30,21 +31,21 @@ class optionst;
3031

3132
// clang-format off
3233
#define CBMC_OPTIONS \
33-
"(program-only)(preprocess)(slice-by-trace):" \
34+
OPT_BMC \
35+
"(preprocess)(slice-by-trace):" \
3436
OPT_FUNCTIONS \
35-
"(no-simplify)(unwind):(unwindset):(slice-formula)(full-slice)" \
37+
"(no-simplify)(full-slice)" \
3638
"(debug-level):(no-propagation)(no-simplify-if)" \
3739
"(document-subgoals)(outfile):(test-preprocessor)" \
3840
"D:I:(c89)(c99)(c11)(cpp98)(cpp03)(cpp11)" \
3941
"(object-bits):" \
40-
"(depth):(partial-loops)(no-unwinding-assertions)(unwinding-assertions)" \
4142
OPT_GOTO_CHECK \
4243
"(no-assertions)(no-assumptions)" \
4344
"(no-built-in-assertions)" \
4445
"(xml-ui)(xml-interface)(json-ui)" \
4546
"(smt1)(smt2)(fpa)(cvc3)(cvc4)(boolector)(yices)(z3)(opensmt)(mathsat)" \
4647
"(no-sat-preprocessor)" \
47-
"(no-pretty-names)(beautify)" \
48+
"(beautify)" \
4849
"(dimacs)(refine)(max-node-refinement):(refine-arrays)(refine-arithmetic)"\
4950
"(refine-strings)" \
5051
"(string-printable)" \
@@ -54,8 +55,7 @@ class optionst;
5455
"(little-endian)(big-endian)" \
5556
OPT_SHOW_GOTO_FUNCTIONS \
5657
OPT_SHOW_PROPERTIES \
57-
"(show-loops)" \
58-
"(show-symbol-table)(show-parse-tree)(show-vcc)" \
58+
"(show-symbol-table)(show-parse-tree)" \
5959
"(drop-unused-functions)" \
6060
"(property):(stop-on-fail)(trace)" \
6161
"(error-label):(verbosity):(no-library)" \
@@ -69,7 +69,6 @@ class optionst;
6969
"(arrays-uf-always)(arrays-uf-never)" \
7070
"(string-abstraction)(no-arch)(arch):" \
7171
"(round-to-nearest)(round-to-plus-inf)(round-to-minus-inf)(round-to-zero)" \
72-
"(graphml-witness):" \
7372
"(localize-faults)(localize-faults-method):" \
7473
OPT_GOTO_TRACE \
7574
"(claim):(show-claims)(fixedbv)(floatbv)(all-claims)(all-properties)" // legacy, and will eventually disappear // NOLINT(whitespace/line_length)

0 commit comments

Comments
 (0)