30
30
#include < goto-programs/goto_functions.h>
31
31
#include < goto-programs/goto_inline.h>
32
32
#include < goto-programs/goto_model.h>
33
+ #include < goto-programs/initialize_goto_model.h>
33
34
#include < goto-programs/link_to_library.h>
34
35
#include < goto-programs/remove_skip.h>
35
36
#include < goto-programs/remove_unused_functions.h>
36
37
38
+ #include < ansi-c/ansi_c_entry_point.h>
37
39
#include < ansi-c/c_expr.h>
40
+ #include < ansi-c/c_object_factory_parameters.h>
38
41
#include < ansi-c/cprover_library.h>
39
42
#include < goto-instrument/contracts/cfg_info.h>
40
43
#include < goto-instrument/contracts/instrument_spec_assigns.h>
41
44
#include < goto-instrument/contracts/utils.h>
42
45
#include < goto-instrument/nondet_static.h>
46
+ #include < langapi/language.h>
47
+ #include < langapi/language_file.h>
48
+ #include < langapi/mode.h>
43
49
#include < linking/static_lifetime_init.h>
44
50
45
51
void dfcc (
52
+ const optionst &options,
46
53
goto_modelt &goto_model,
47
54
const irep_idt &harness_id,
48
55
const std::set<irep_idt> &to_check,
@@ -60,7 +67,7 @@ void dfcc(
60
67
for (const auto &function_id : to_replace)
61
68
to_replace_map.insert ({function_id, function_id});
62
69
63
- dfcct{goto_model, message_handler}.transform_goto_model (
70
+ dfcct{options, goto_model, message_handler}.transform_goto_model (
64
71
harness_id,
65
72
to_check_map,
66
73
allow_recursive_calls,
@@ -70,6 +77,7 @@ void dfcc(
70
77
}
71
78
72
79
void dfcc (
80
+ const optionst &options,
73
81
goto_modelt &goto_model,
74
82
const irep_idt &harness_id,
75
83
const std::map<irep_idt, irep_idt> &to_check,
@@ -79,7 +87,7 @@ void dfcc(
79
87
const std::set<std::string> &to_exclude_from_nondet_static,
80
88
message_handlert &message_handler)
81
89
{
82
- dfcct{goto_model, message_handler}.transform_goto_model (
90
+ dfcct{options, goto_model, message_handler}.transform_goto_model (
83
91
harness_id,
84
92
to_check,
85
93
allow_recursive_calls,
@@ -90,8 +98,12 @@ void dfcc(
90
98
91
99
std::map<irep_idt, irep_idt> dfcct::wrapped_functions_cache;
92
100
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),
95
107
message_handler(message_handler),
96
108
log(message_handler),
97
109
utils(goto_model, message_handler),
@@ -126,26 +138,6 @@ void dfcct::check_transform_goto_model_preconditions(
126
138
const bool apply_loop_contracts,
127
139
const std::set<std::string> &to_exclude_from_nondet_static)
128
140
{
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
-
149
141
// check there is at most one function to check
150
142
PRECONDITION_WITH_DIAGNOSTICS (
151
143
to_check.size () <= 1 ,
@@ -266,14 +258,6 @@ void dfcct::transform_goto_model(
266
258
link_to_library (
267
259
goto_model, log .get_message_handler (), cprover_c_library_factory);
268
260
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
-
277
261
// partition the set of functions of the goto_model
278
262
std::set<irep_idt> pure_contract_symbols;
279
263
std::set<irep_idt> other_symbols;
@@ -439,8 +423,74 @@ void dfcct::transform_goto_model(
439
423
instrument.get_instrumented_functions (instrumented_functions);
440
424
swap_and_wrap.get_swapped_functions (instrumented_functions);
441
425
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
+
445
495
goto_model.goto_functions .update ();
446
496
}
0 commit comments