@@ -30,19 +30,26 @@ Author: Remi Delmas, delmarsd@amazon.com
3030#include < goto-programs/goto_functions.h>
3131#include < goto-programs/goto_inline.h>
3232#include < goto-programs/goto_model.h>
33+ #include < goto-programs/initialize_goto_model.h>
3334#include < goto-programs/link_to_library.h>
3435#include < goto-programs/remove_skip.h>
3536#include < goto-programs/remove_unused_functions.h>
3637
38+ #include < ansi-c/ansi_c_entry_point.h>
3739#include < ansi-c/c_expr.h>
40+ #include < ansi-c/c_object_factory_parameters.h>
3841#include < ansi-c/cprover_library.h>
3942#include < goto-instrument/contracts/cfg_info.h>
4043#include < goto-instrument/contracts/instrument_spec_assigns.h>
4144#include < goto-instrument/contracts/utils.h>
4245#include < goto-instrument/nondet_static.h>
46+ #include < langapi/language.h>
47+ #include < langapi/language_file.h>
48+ #include < langapi/mode.h>
4349#include < linking/static_lifetime_init.h>
4450
4551void dfcc (
52+ const optionst &options,
4653 goto_modelt &goto_model,
4754 const irep_idt &harness_id,
4855 const std::set<irep_idt> &to_check,
@@ -60,7 +67,7 @@ void dfcc(
6067 for (const auto &function_id : to_replace)
6168 to_replace_map.insert ({function_id, function_id});
6269
63- dfcct{goto_model, message_handler}.transform_goto_model (
70+ dfcct{options, goto_model, message_handler}.transform_goto_model (
6471 harness_id,
6572 to_check_map,
6673 allow_recursive_calls,
@@ -70,6 +77,7 @@ void dfcc(
7077}
7178
7279void dfcc (
80+ const optionst &options,
7381 goto_modelt &goto_model,
7482 const irep_idt &harness_id,
7583 const std::map<irep_idt, irep_idt> &to_check,
@@ -79,7 +87,7 @@ void dfcc(
7987 const std::set<std::string> &to_exclude_from_nondet_static,
8088 message_handlert &message_handler)
8189{
82- dfcct{goto_model, message_handler}.transform_goto_model (
90+ dfcct{options, goto_model, message_handler}.transform_goto_model (
8391 harness_id,
8492 to_check,
8593 allow_recursive_calls,
@@ -90,8 +98,12 @@ void dfcc(
9098
9199std::map<irep_idt, irep_idt> dfcct::wrapped_functions_cache;
92100
93- dfcct::dfcct (goto_modelt &goto_model, message_handlert &message_handler)
94- : goto_model(goto_model),
101+ dfcct::dfcct (
102+ const optionst &options,
103+ goto_modelt &goto_model,
104+ message_handlert &message_handler)
105+ : options(options),
106+ goto_model(goto_model),
95107 message_handler(message_handler),
96108 log(message_handler),
97109 utils(goto_model, message_handler),
@@ -126,26 +138,6 @@ void dfcct::check_transform_goto_model_preconditions(
126138 const bool apply_loop_contracts,
127139 const std::set<std::string> &to_exclude_from_nondet_static)
128140{
129- // TODO reactivate this once I understand how entry points work
130- // Check that the goto_model entry point matches the given harness_id
131- // if(!config.main.has_value())
132- // {
133- // log.error() << "dfcct::transform_goto_model: no entry point found in the"
134- // "goto model, expected '"
135- // << harness_id << "', aborting contracts transformations."
136- // << messaget::eom;
137- // throw invalid_input_exceptiont(msg);
138- // }
139-
140- // if(config.main.value() != harness_id)
141- // {
142- // log.error() << "dfcct::transform_goto_model: entry point '"
143- // << config.main.value()
144- // << "' differs from given harness function '" << harness_id
145- // << "', aborting contracts transformations." << messaget::eom;
146- // throw invalid_input_exceptiont(msg);
147- // }
148-
149141 // check there is at most one function to check
150142 PRECONDITION_WITH_DIAGNOSTICS (
151143 to_check.size () <= 1 ,
@@ -266,14 +258,6 @@ void dfcct::transform_goto_model(
266258 link_to_library (
267259 goto_model, log.get_message_handler (), cprover_c_library_factory);
268260
269- // Make all statics nondet. This needs to be done before starting the program
270- // transformation since the instrumentation adds static variables
271- // which must keep their initial values to function as intended.
272- log.status ()
273- << " Adding nondeterministic initialization of static/global variables."
274- << messaget::eom;
275- nondet_static (goto_model, to_exclude_from_nondet_static);
276-
277261 // partition the set of functions of the goto_model
278262 std::set<irep_idt> pure_contract_symbols;
279263 std::set<irep_idt> other_symbols;
@@ -439,8 +423,74 @@ void dfcct::transform_goto_model(
439423 instrument.get_instrumented_functions (instrumented_functions);
440424 swap_and_wrap.get_swapped_functions (instrumented_functions);
441425
442- // update statics and static function maps
443- log.status () << " Updating CPROVER init function" << messaget::eom;
444- library.create_initialize_function (instrumented_functions);
426+ // Re-initialise the GOTO model.
427+ //
428+ // The new entry point must be the proof harness function specified for
429+ // instrumentation.
430+ //
431+ // The "initialize" (aka INITIALIZE_FUNCTION) is the function that assigns
432+ // initial values to all statics of the model;
433+ //
434+ // The initialize function must do the following:
435+ // - assign a nondet value to all statics of the user program
436+ // - assign the specified initial value to all instrumentation statics
437+ // - add an entry in the static unbounded map of instrumented functions
438+ // for each instrumented function
439+ //
440+ // A call to `nondet_static` will re-generate the initialize function with
441+ // nondet values. The intrumentation statics will not get nondet initialised
442+ // by virtue of being tagged with ID_C_no_nondet_initialization.
443+ //
444+ // However, nondet_static expects instructions to be either function calls
445+ // or assignments with a symbol_exprt LHS.
446+ // Since entries for the instrumented function maps are not symbol_exprts but
447+ // index_exprts they need to be moved to the harness function.
448+ //
449+ // The "start" function (aka goto_functionst::entry_point()) is the
450+ // function from which SymEx starts.
451+ //
452+ // The start function must do the following:
453+ // - call the initialize function,
454+ // - generate nondet values for the arguments of the proof harness function
455+ // - call the harness function with said nondet arguments
456+ //
457+ // All of which can be done using a call to `generate_ansi_c_start_function`,
458+ // assuming the initialize function is already available in the symbol table.
459+ //
460+ // So we do the following:
461+ // - regenerate the "initialize" function
462+ // - call nondet_static
463+ // - add extra instructions at the end of the harness function for the
464+ // instrumented functions map
465+ // - call generate_ansi_c_start_function
466+
467+ // Make all user-defined statics nondet.
468+ // Other statics added by the instrumentation will be unaffected because they
469+ // are tagged with ID_C_no_nondet_initialization when created
470+
471+ // Update statics and static function maps
472+ log.status () << " Updating init function" << messaget::eom;
473+ utils.create_initialize_function ();
474+ goto_model.goto_functions .update ();
475+ nondet_static (goto_model, to_exclude_from_nondet_static);
476+
477+ // Initialize the map of instrumented functions by adding extra instructions
478+ // to the harness function
479+ auto &init_function = goto_model.goto_functions .function_map [harness_id];
480+ auto &body = init_function.body ;
481+ auto begin = body.instructions .begin ();
482+ goto_programt payload;
483+ library.add_instrumented_functions_map_init_instructions (
484+ instrumented_functions, begin->source_location (), payload);
485+ body.destructive_insert (begin, payload);
486+
487+ // Define harness as the entry point, overriding any preexisting one.
488+ log.status () << " Setting entry point to " << harness_id << messaget::eom;
489+ generate_ansi_c_start_function (
490+ utils.get_function_symbol (harness_id),
491+ goto_model.symbol_table ,
492+ message_handler,
493+ c_object_factory_parameterst (options));
494+
445495 goto_model.goto_functions .update ();
446496}
0 commit comments