@@ -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
494508safety_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
502516safety_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.
598621int 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
706729void 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}
0 commit comments