Skip to content

Commit 8c501cc

Browse files
committed
Use abstract_goto_modelt instead of goto_functionst in bmc reporting phase
This allows lazy_goto_modelt to be passed in instead of a goto_modelt's functions map as was used previously.
1 parent 760d1ca commit 8c501cc

File tree

7 files changed

+78
-62
lines changed

7 files changed

+78
-62
lines changed

src/cbmc/bmc.cpp

+43-20
Original file line numberDiff line numberDiff line change
@@ -357,11 +357,25 @@ void bmct::setup()
357357
setup_unwind();
358358
}
359359

360-
safety_checkert::resultt bmct::execute(const goto_functionst &goto_functions)
360+
safety_checkert::resultt bmct::execute(
361+
abstract_goto_modelt &goto_model)
361362
{
362363
try
363364
{
364-
perform_symbolic_execution(goto_functions);
365+
auto get_goto_function = [&goto_model](const irep_idt &id) ->
366+
const goto_functionst::goto_functiont &
367+
{
368+
return goto_model.get_goto_function(id);
369+
};
370+
371+
perform_symbolic_execution(get_goto_function);
372+
373+
// Borrow a reference to the goto functions map. This reference, or
374+
// iterators pointing into it, must not be stored by this function or its
375+
// callees, as goto_model.get_goto_function (as used by symex)
376+
// will have side-effects on it.
377+
const goto_functionst &goto_functions =
378+
goto_model.get_goto_functions();
365379

366380
// add a partial ordering, if required
367381
if(equation.has_threads())
@@ -492,11 +506,11 @@ void bmct::slice()
492506
}
493507

494508
safety_checkert::resultt bmct::run(
495-
const goto_functionst &goto_functions)
509+
abstract_goto_modelt &goto_model)
496510
{
497511
setup();
498512

499-
return execute(goto_functions);
513+
return execute(goto_model);
500514
}
501515

502516
safety_checkert::resultt bmct::decide(
@@ -595,29 +609,38 @@ void bmct::setup_unwind()
595609
symex.set_unwind_limit(options.get_unsigned_int_option("unwind"));
596610
}
597611

612+
/// Perform core BMC, using an abstract model to supply GOTO function bodies
613+
/// (perhaps created on demand).
614+
/// \param opts: command-line options affecting BMC
615+
/// \param model: provides goto function bodies and the symbol table, perhaps
616+
// creating those function bodies on demand.
617+
/// \param ui: user-interface mode (plain text, XML output, JSON output, ...)
618+
/// \param message: used for logging
619+
/// \param frontend_configure_bmc: function provided by the frontend program,
620+
/// which applies frontend-specific configuration to a bmct before running.
598621
int bmct::do_language_agnostic_bmc(
599622
const optionst &opts,
600-
const goto_modelt &goto_model,
623+
abstract_goto_modelt &model,
601624
const ui_message_handlert::uit &ui,
602625
messaget &message,
603-
std::function<void(bmct &, const goto_modelt &)> frontend_configure_bmc)
626+
std::function<void(bmct &, const symbol_tablet &)> frontend_configure_bmc)
604627
{
628+
const symbol_tablet &symbol_table = model.get_symbol_table();
605629
message_handlert &mh = message.get_message_handler();
606630
safety_checkert::resultt result;
607631
goto_symext::branch_worklistt worklist;
608632
try
609633
{
610634
{
611-
cbmc_solverst solvers(
612-
opts, goto_model.symbol_table, message.get_message_handler());
635+
cbmc_solverst solvers(opts, symbol_table, message.get_message_handler());
613636
solvers.set_ui(ui);
614637
std::unique_ptr<cbmc_solverst::solvert> cbmc_solver;
615638
cbmc_solver = solvers.get_solver();
616639
prop_convt &pc = cbmc_solver->prop_conv();
617-
bmct bmc(opts, goto_model.symbol_table, mh, pc, worklist);
640+
bmct bmc(opts, symbol_table, mh, pc, worklist);
618641
bmc.set_ui(ui);
619-
frontend_configure_bmc(bmc, goto_model);
620-
result = bmc.run(goto_model.goto_functions);
642+
frontend_configure_bmc(bmc, symbol_table);
643+
result = bmc.run(model);
621644
}
622645
INVARIANT(
623646
opts.get_bool_option("paths") || worklist.empty(),
@@ -646,23 +669,22 @@ int bmct::do_language_agnostic_bmc(
646669
<< "Starting new path (" << worklist.size()
647670
<< " to go)\n"
648671
<< message.eom;
649-
cbmc_solverst solvers(
650-
opts, goto_model.symbol_table, message.get_message_handler());
672+
cbmc_solverst solvers(opts, symbol_table, message.get_message_handler());
651673
solvers.set_ui(ui);
652674
std::unique_ptr<cbmc_solverst::solvert> cbmc_solver;
653675
cbmc_solver = solvers.get_solver();
654676
prop_convt &pc = cbmc_solver->prop_conv();
655677
goto_symext::branch_pointt &resume = worklist.front();
656678
path_explorert pe(
657679
opts,
658-
goto_model.symbol_table,
680+
symbol_table,
659681
mh,
660682
pc,
661683
resume.equation,
662684
resume.state,
663685
worklist);
664-
frontend_configure_bmc(pe, goto_model);
665-
result &= pe.run(goto_model.goto_functions);
686+
frontend_configure_bmc(pe, symbol_table);
687+
result &= pe.run(model);
666688
worklist.pop_front();
667689
}
668690
}
@@ -694,18 +716,19 @@ int bmct::do_language_agnostic_bmc(
694716
UNREACHABLE;
695717
}
696718

697-
void bmct::perform_symbolic_execution(const goto_functionst &goto_functions)
719+
void bmct::perform_symbolic_execution(
720+
goto_symext::get_goto_functiont get_goto_function)
698721
{
699-
symex.symex_from_entry_point_of(goto_functions, symex_symbol_table);
722+
symex.symex_from_entry_point_of(get_goto_function, symex_symbol_table);
700723
INVARIANT(
701724
options.get_bool_option("paths") || branch_worklist.empty(),
702725
"Branch points were saved even though we should have been "
703726
"executing the entire program and merging paths");
704727
}
705728

706729
void path_explorert::perform_symbolic_execution(
707-
const goto_functionst &goto_functions)
730+
goto_symext::get_goto_functiont get_goto_function)
708731
{
709732
symex.resume_symex_from_saved_state(
710-
goto_functions, saved_state, &equation, symex_symbol_table);
733+
get_goto_function, saved_state, &equation, symex_symbol_table);
711734
}

src/cbmc/bmc.h

+14-18
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,14 @@ class bmct:public safety_checkert
9090
!options.get_option("symex-coverage-report").empty();
9191
}
9292

93-
virtual resultt run(const goto_functionst &goto_functions);
93+
virtual resultt run(const goto_functionst &goto_functions)
94+
{
95+
wrapper_goto_modelt model(outer_symbol_table, goto_functions);
96+
return run(model);
97+
}
98+
resultt run(abstract_goto_modelt &);
9499
void setup();
95-
safety_checkert::resultt execute(const goto_functionst &);
100+
safety_checkert::resultt execute(abstract_goto_modelt &);
96101
virtual ~bmct() { }
97102

98103
// additional stuff
@@ -118,22 +123,13 @@ class bmct:public safety_checkert
118123
symex.add_recursion_unwind_handler(handler);
119124
}
120125

121-
/// \brief common BMC code, invoked from language-specific frontends
122-
///
123-
/// Do bounded model-checking after all language-specific program
124-
/// preprocessing has been completed by language-specific frontends.
125-
/// Language-specific frontends may customize the \ref bmct objects
126-
/// that are used for model-checking by supplying a function object to
127-
/// the `frontend_configure_bmc` parameter of this function; the
128-
/// function object will be called with every \ref bmct object that
129-
/// is constructed by `do_language_agnostic_bmc`.
130126
static int do_language_agnostic_bmc(
131127
const optionst &opts,
132-
const goto_modelt &goto_model,
128+
abstract_goto_modelt &goto_model,
133129
const ui_message_handlert::uit &ui,
134130
messaget &message,
135-
std::function<void(bmct &, const goto_modelt &)> frontend_configure_bmc =
136-
[](bmct &_bmc, const goto_modelt &) { // NOLINT (*)
131+
std::function<void(bmct &, const symbol_tablet &)> frontend_configure_bmc =
132+
[](bmct &_bmc, const symbol_tablet &) { // NOLINT (*)
137133
// Empty default implementation
138134
});
139135

@@ -240,8 +236,8 @@ class bmct:public safety_checkert
240236
/// invoke the symbolic executor in a class-specific way. This
241237
/// implementation invokes goto_symext::operator() to perform
242238
/// full-program model-checking from the entry point of the program.
243-
virtual void
244-
perform_symbolic_execution(const goto_functionst &goto_functions);
239+
virtual void perform_symbolic_execution(
240+
goto_symext::get_goto_functiont get_goto_function);
245241
};
246242

247243
/// \brief Symbolic execution from a saved branch point
@@ -285,8 +281,8 @@ class path_explorert : public bmct
285281
/// This overrides the base implementation to call the symbolic executor with
286282
/// the saved symex_target_equationt, symbol_tablet, and goto_symex_statet
287283
/// provided as arguments to the constructor of this class.
288-
void
289-
perform_symbolic_execution(const goto_functionst &goto_functions) override;
284+
void perform_symbolic_execution(
285+
goto_symext::get_goto_functiont get_goto_function) override;
290286

291287
#define OPT_BMC \
292288
"(program-only)" \

src/goto-symex/goto_symex.h

+10-10
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,6 @@ class goto_symext
105105
const goto_functionst &goto_functions,
106106
symbol_tablet &new_symbol_table);
107107

108-
/// Performs symbolic execution using a state and equation that have
109-
/// already been used to symex part of the program. The state is not
110-
/// re-initialized; instead, symbolic execution resumes from the program
111-
/// counter of the saved state.
112-
virtual void resume_symex_from_saved_state(
113-
const goto_functionst &goto_functions,
114-
const statet &saved_state,
115-
symex_target_equationt *const saved_equation,
116-
symbol_tablet &new_symbol_table);
117-
118108
/// \brief symex entire program starting from entry point
119109
///
120110
/// The state that goto_symext maintains has a large memory footprint.
@@ -125,6 +115,16 @@ class goto_symext
125115
const get_goto_functiont &get_goto_function,
126116
symbol_tablet &new_symbol_table);
127117

118+
/// Performs symbolic execution using a state and equation that have
119+
/// already been used to symex part of the program. The state is not
120+
/// re-initialized; instead, symbolic execution resumes from the program
121+
/// counter of the saved state.
122+
virtual void resume_symex_from_saved_state(
123+
const get_goto_functiont &get_goto_function,
124+
const statet &saved_state,
125+
symex_target_equationt *const saved_equation,
126+
symbol_tablet &new_symbol_table);
127+
128128
//// \brief symex entire program starting from entry point
129129
///
130130
/// This method uses the `state` argument as the symbolic execution

src/goto-symex/symex_main.cpp

+1-4
Original file line numberDiff line numberDiff line change
@@ -211,14 +211,11 @@ void goto_symext::symex_with_state(
211211
}
212212

213213
void goto_symext::resume_symex_from_saved_state(
214-
const goto_functionst &goto_functions,
214+
const get_goto_functiont &get_goto_function,
215215
const statet &saved_state,
216216
symex_target_equationt *const saved_equation,
217217
symbol_tablet &new_symbol_table)
218218
{
219-
const get_goto_functiont get_goto_function = get_function_from_goto_functions(
220-
goto_functions);
221-
222219
// saved_state contains a pointer to a symex_target_equationt that is
223220
// almost certainly stale. This is because equations are owned by bmcts,
224221
// and we construct a new bmct for every path that we execute. We're on a

src/jbmc/jbmc_parse_options.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -489,12 +489,12 @@ int jbmc_parse_optionst::doit()
489489
if(set_properties(goto_model))
490490
return 7; // should contemplate EX_USAGE from sysexits.h
491491

492-
std::function<void(bmct &, const goto_modelt &)> configure_bmc;
492+
std::function<void(bmct &, const symbol_tablet &)> configure_bmc;
493493
if(options.get_bool_option("java-unwind-enum-static"))
494494
{
495495
configure_bmc = [](
496-
bmct &bmc, const goto_modelt &goto_model) { // NOLINT (*)
497-
bmc.add_loop_unwind_handler([&goto_model](
496+
bmct &bmc, const symbol_tablet &symbol_table) { // NOLINT (*)
497+
bmc.add_loop_unwind_handler([&symbol_table](
498498
const irep_idt &function_id,
499499
unsigned loop_number,
500500
unsigned unwind,
@@ -504,14 +504,14 @@ int jbmc_parse_optionst::doit()
504504
loop_number,
505505
unwind,
506506
max_unwind,
507-
goto_model.symbol_table);
507+
symbol_table);
508508
});
509509
};
510510
}
511511
else
512512
{
513513
configure_bmc = [](
514-
bmct &bmc, const goto_modelt &goto_model) { // NOLINT (*)
514+
bmct &bmc, const symbol_tablet &symbol_table) { // NOLINT (*)
515515
// NOOP
516516
};
517517
}
@@ -637,7 +637,7 @@ int jbmc_parse_optionst::get_goto_program(
637637

638638
void jbmc_parse_optionst::process_goto_function(
639639
goto_model_functiont &function,
640-
const can_produce_functiont &available_functions,
640+
const abstract_goto_modelt &model,
641641
const optionst &options)
642642
{
643643
journalling_symbol_tablet &symbol_table = function.get_symbol_table();
@@ -651,9 +651,9 @@ void jbmc_parse_optionst::process_goto_function(
651651
remove_virtual_functions(function);
652652

653653
auto function_is_stub =
654-
[&symbol_table, &available_functions](const irep_idt &id) { // NOLINT(*)
654+
[&symbol_table, &model](const irep_idt &id) { // NOLINT(*)
655655
return symbol_table.lookup_ref(id).value.is_nil() &&
656-
!available_functions.can_produce_function(id);
656+
!model.can_produce_function(id);
657657
};
658658

659659
remove_returns(function, function_is_stub);

src/jbmc/jbmc_parse_options.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class jbmc_parse_optionst:
9191

9292
void process_goto_function(
9393
goto_model_functiont &function,
94-
const can_produce_functiont &,
94+
const abstract_goto_modelt &,
9595
const optionst &);
9696
bool process_goto_functions(goto_modelt &goto_model, const optionst &options);
9797

unit/testing-utils/load_java_class.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ symbol_tablet load_java_class(
8888
// Construct a lazy_goto_modelt
8989
null_message_handlert message_handler;
9090
lazy_goto_modelt lazy_goto_model(
91-
[] (goto_model_functiont &function, const can_produce_functiont &cpf) { }, // NOLINT (*)
91+
[] (goto_model_functiont &function, const abstract_goto_modelt &model) { }, // NOLINT (*)
9292
[] (goto_modelt &goto_model) { return false; }, // NOLINT (*)
9393
message_handler);
9494

0 commit comments

Comments
 (0)