Skip to content

Commit c7ad581

Browse files
Remi Delmasqinheping
Remi Delmas
authored andcommitted
CONTRACTS: add loop contracts support in DFCC
1 parent cd2efad commit c7ad581

11 files changed

+477
-418
lines changed

src/goto-instrument/contracts/dynamic-frames/dfcc.cpp

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ Author: Remi Delmas, [email protected]
3838
#include <ansi-c/c_object_factory_parameters.h>
3939
#include <ansi-c/cprover_library.h>
4040
#include <goto-instrument/contracts/cfg_info.h>
41-
#include <goto-instrument/contracts/instrument_spec_assigns.h>
4241
#include <goto-instrument/contracts/utils.h>
4342
#include <goto-instrument/nondet_static.h>
4443
#include <langapi/language.h>
@@ -122,6 +121,7 @@ void dfcc(
122121
const bool allow_recursive_calls,
123122
const std::set<irep_idt> &to_replace,
124123
const bool apply_loop_contracts,
124+
const bool unwind_transformed_loops,
125125
const std::set<std::string> &to_exclude_from_nondet_static,
126126
message_handlert &message_handler)
127127
{
@@ -138,6 +138,7 @@ void dfcc(
138138
allow_recursive_calls,
139139
to_replace_map,
140140
apply_loop_contracts,
141+
unwind_transformed_loops,
141142
to_exclude_from_nondet_static,
142143
message_handler);
143144
}
@@ -150,6 +151,7 @@ void dfcc(
150151
const bool allow_recursive_calls,
151152
const std::map<irep_idt, irep_idt> &to_replace,
152153
const bool apply_loop_contracts,
154+
const bool unwind_transformed_loops,
153155
const std::set<std::string> &to_exclude_from_nondet_static,
154156
message_handlert &message_handler)
155157
{
@@ -160,7 +162,8 @@ void dfcc(
160162
to_check,
161163
allow_recursive_calls,
162164
to_replace,
163-
apply_loop_contracts,
165+
dfcc_loop_contract_mode_from_bools(
166+
apply_loop_contracts, unwind_transformed_loops),
164167
message_handler,
165168
to_exclude_from_nondet_static};
166169
}
@@ -172,7 +175,7 @@ dfcct::dfcct(
172175
const optionalt<std::pair<irep_idt, irep_idt>> &to_check,
173176
const bool allow_recursive_calls,
174177
const std::map<irep_idt, irep_idt> &to_replace,
175-
const bool apply_loop_contracts,
178+
const dfcc_loop_contract_modet loop_contract_mode,
176179
message_handlert &message_handler,
177180
const std::set<std::string> &to_exclude_from_nondet_static)
178181
: options(options),
@@ -181,22 +184,23 @@ dfcct::dfcct(
181184
to_check(to_check),
182185
allow_recursive_calls(allow_recursive_calls),
183186
to_replace(to_replace),
184-
apply_loop_contracts(apply_loop_contracts),
187+
loop_contract_mode(loop_contract_mode),
185188
to_exclude_from_nondet_static(to_exclude_from_nondet_static),
186189
message_handler(message_handler),
187190
log(message_handler),
188191
utils(goto_model, message_handler),
189192
library(goto_model, utils, message_handler),
190193
ns(goto_model.symbol_table),
191-
instrument(goto_model, message_handler, utils, library),
192-
memory_predicates(goto_model, utils, library, instrument, message_handler),
193-
spec_functions(goto_model, message_handler, utils, library, instrument),
194-
contract_clauses_codegen(
194+
spec_functions(goto_model, message_handler, utils, library),
195+
contract_clauses_codegen(goto_model, message_handler, utils, library),
196+
instrument(
195197
goto_model,
196198
message_handler,
197199
utils,
198200
library,
199-
spec_functions),
201+
spec_functions,
202+
contract_clauses_codegen),
203+
memory_predicates(goto_model, utils, library, instrument, message_handler),
200204
contract_handler(
201205
goto_model,
202206
message_handler,
@@ -340,7 +344,7 @@ void dfcct::instrument_harness_function()
340344
<< messaget::eom;
341345

342346
instrument.instrument_harness_function(
343-
harness_id, function_pointer_contracts);
347+
harness_id, loop_contract_mode, function_pointer_contracts);
344348

345349
other_symbols.erase(harness_id);
346350
}
@@ -369,6 +373,7 @@ void dfcct::wrap_checked_function()
369373
<< contract_id << "' in CHECK mode" << messaget::eom;
370374

371375
swap_and_wrap.swap_and_wrap_check(
376+
loop_contract_mode,
372377
wrapper_id,
373378
contract_id,
374379
function_pointer_contracts,
@@ -377,7 +382,7 @@ void dfcct::wrap_checked_function()
377382
if(other_symbols.find(wrapper_id) != other_symbols.end())
378383
other_symbols.erase(wrapper_id);
379384

380-
// upate max contract size
385+
// update max contract size
381386
const std::size_t assigns_clause_size =
382387
contract_handler.get_assigns_clause_size(contract_id);
383388
if(assigns_clause_size > max_assigns_clause_size)
@@ -485,20 +490,11 @@ void dfcct::instrument_other_functions()
485490

486491
log.status() << "Instrumenting '" << function_id << "'" << messaget::eom;
487492

488-
instrument.instrument_function(function_id, function_pointer_contracts);
493+
instrument.instrument_function(
494+
function_id, loop_contract_mode, function_pointer_contracts);
489495
}
490496

491497
goto_model.goto_functions.update();
492-
493-
// TODO specialise the library functions for the max size of
494-
// loop and function contracts
495-
if(to_check.has_value())
496-
{
497-
log.status() << "Specializing cprover_contracts functions for assigns "
498-
"clauses of at most "
499-
<< max_assigns_clause_size << " targets" << messaget::eom;
500-
library.specialize(max_assigns_clause_size);
501-
}
502498
}
503499

504500
void dfcct::transform_goto_model()
@@ -511,6 +507,17 @@ void dfcct::transform_goto_model()
511507
wrap_replaced_functions();
512508
wrap_discovered_function_pointer_contracts();
513509
instrument_other_functions();
510+
511+
// take the max of function of loop contracts assigns clauses
512+
auto assigns_clause_size = instrument.get_max_assigns_clause_size();
513+
if(assigns_clause_size > max_assigns_clause_size)
514+
max_assigns_clause_size = assigns_clause_size;
515+
516+
log.status() << "Specializing cprover_contracts functions for assigns "
517+
"clauses of at most "
518+
<< max_assigns_clause_size << " targets" << messaget::eom;
519+
library.specialize(max_assigns_clause_size);
520+
514521
library.inhibit_front_end_builtins();
515522

516523
// TODO implement a means to inhibit unreachable functions (possibly via the

src/goto-instrument/contracts/dynamic-frames/dfcc.h

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Author: Remi Delmas, [email protected]
3838
#include "dfcc_instrument.h"
3939
#include "dfcc_library.h"
4040
#include "dfcc_lift_memory_predicates.h"
41+
#include "dfcc_loop_contract_mode.h"
4142
#include "dfcc_spec_functions.h"
4243
#include "dfcc_swap_and_wrap.h"
4344
#include "dfcc_utils.h"
@@ -50,17 +51,16 @@ class messaget;
5051
class message_handlert;
5152
class symbolt;
5253
class conditional_target_group_exprt;
53-
class cfg_infot;
5454
class optionst;
5555

5656
#define FLAG_DFCC "dfcc"
5757
#define OPT_DFCC "(" FLAG_DFCC "):"
5858

5959
// clang-format off
6060
#define HELP_DFCC \
61-
" --dfcc <harness> activate dynamic frame condition checking\n"\
62-
" for function contracts using the given\n"\
63-
" harness as entry point\n"
61+
" --dfcc <harness> activate dynamic frame condition checking\n" \
62+
" for contracts using the given harness as\n" \
63+
" entry point\n"
6464

6565
#define FLAG_ENFORCE_CONTRACT_REC "enforce-contract-rec"
6666
#define OPT_ENFORCE_CONTRACT_REC "(" FLAG_ENFORCE_CONTRACT_REC "):"
@@ -100,6 +100,8 @@ class invalid_function_contract_pair_exceptiont : public cprover_exception_baset
100100
/// \param allow_recursive_calls Allow the checked function to be recursive
101101
/// \param to_replace set of functions to replace with their contract
102102
/// \param apply_loop_contracts apply loop contract transformations iff true
103+
/// \param unwind_transformed_loops unwind transformed loops after applying loop
104+
/// contracts.
103105
/// \param to_exclude_from_nondet_static set of symbols to exclude when havocing
104106
/// static program symbols.
105107
/// \param message_handler used for debug/warning/error messages
@@ -111,6 +113,7 @@ void dfcc(
111113
const bool allow_recursive_calls,
112114
const std::set<irep_idt> &to_replace,
113115
const bool apply_loop_contracts,
116+
const bool unwind_transformed_loops,
114117
const std::set<std::string> &to_exclude_from_nondet_static,
115118
message_handlert &message_handler);
116119

@@ -129,7 +132,9 @@ void dfcc(
129132
/// \param to_check (function,contract) pair for contract checking
130133
/// \param allow_recursive_calls Allow the checked function to be recursive
131134
/// \param to_replace Functions-to-contract mapping for replacement
132-
/// \param apply_loop_contracts Spply loop contract transformations iff true
135+
/// \param apply_loop_contracts Apply loop contract transformations iff true
136+
/// \param unwind_transformed_loops unwind transformed loops after applying loop
137+
/// contracts.
133138
/// \param to_exclude_from_nondet_static Set of symbols to exclude when havocing
134139
/// static program symbols.
135140
/// \param message_handler used for debug/warning/error messages
@@ -141,6 +146,7 @@ void dfcc(
141146
const bool allow_recursive_calls,
142147
const std::map<irep_idt, irep_idt> &to_replace,
143148
const bool apply_loop_contracts,
149+
const bool unwind_transformed_loops,
144150
const std::set<std::string> &to_exclude_from_nondet_static,
145151
message_handlert &message_handler);
146152

@@ -157,8 +163,7 @@ class dfcct
157163
/// \param to_check (function,contract) pair for contract checking
158164
/// \param allow_recursive_calls Allow the checked function to be recursive
159165
/// \param to_replace functions-to-contract mapping for replacement
160-
/// \param apply_loop_contracts apply loop contract transformations iff true
161-
/// havocing static program symbols.
166+
/// \param loop_contract_mode
162167
/// \param message_handler used for debug/warning/error messages
163168
/// \param to_exclude_from_nondet_static set of symbols to exclude when
164169
dfcct(
@@ -168,7 +173,7 @@ class dfcct
168173
const optionalt<std::pair<irep_idt, irep_idt>> &to_check,
169174
const bool allow_recursive_calls,
170175
const std::map<irep_idt, irep_idt> &to_replace,
171-
const bool apply_loop_contracts,
176+
const dfcc_loop_contract_modet loop_contract_mode,
172177
message_handlert &message_handler,
173178
const std::set<std::string> &to_exclude_from_nondet_static);
174179

@@ -194,7 +199,7 @@ class dfcct
194199
/// (replacement mode)
195200
/// - instrument all remaining functions GOTO model
196201
/// - (this includes standard library functions).
197-
/// - specialise the instrumentation functions by unwiding loops they contain
202+
/// - specialise the instrumentation functions by unwinding loops they contain
198203
/// to the maximum size of any assigns clause involved in the model.
199204
void transform_goto_model();
200205

@@ -205,7 +210,7 @@ class dfcct
205210
const optionalt<std::pair<irep_idt, irep_idt>> &to_check;
206211
const bool allow_recursive_calls;
207212
const std::map<irep_idt, irep_idt> &to_replace;
208-
const bool apply_loop_contracts;
213+
const dfcc_loop_contract_modet loop_contract_mode;
209214
const std::set<std::string> &to_exclude_from_nondet_static;
210215
message_handlert &message_handler;
211216
messaget log;
@@ -215,10 +220,10 @@ class dfcct
215220
dfcc_utilst utils;
216221
dfcc_libraryt library;
217222
namespacet ns;
218-
dfcc_instrumentt instrument;
219-
dfcc_lift_memory_predicatest memory_predicates;
220223
dfcc_spec_functionst spec_functions;
221224
dfcc_contract_clauses_codegent contract_clauses_codegen;
225+
dfcc_instrumentt instrument;
226+
dfcc_lift_memory_predicatest memory_predicates;
222227
dfcc_contract_handlert contract_handler;
223228
dfcc_swap_and_wrapt swap_and_wrap;
224229

@@ -277,7 +282,7 @@ class dfcct
277282
/// for each instrumented function
278283
///
279284
/// A call to `nondet_static` will re-generate the initialize function with
280-
/// nondet values. The intrumentation statics will not get nondet initialised
285+
/// nondet values. The instrumentation statics will not get nondet initialised
281286
/// by virtue of being tagged with ID_C_no_nondet_initialization.
282287
///
283288
/// However, nondet_static expects instructions to be either function calls

src/goto-instrument/contracts/dynamic-frames/dfcc_contract_clauses_codegen.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ Date: February 2023
88
\*******************************************************************/
99
#include "dfcc_contract_clauses_codegen.h"
1010

11+
#include <util/c_types.h>
1112
#include <util/expr_util.h>
1213
#include <util/fresh_symbol.h>
1314
#include <util/invariant.h>
1415
#include <util/mathematical_expr.h>
1516
#include <util/namespace.h>
17+
#include <util/pointer_expr.h>
1618
#include <util/pointer_offset_size.h>
1719
#include <util/std_expr.h>
1820

@@ -23,21 +25,18 @@ Date: February 2023
2325
#include <langapi/language_util.h>
2426

2527
#include "dfcc_library.h"
26-
#include "dfcc_spec_functions.h"
2728
#include "dfcc_utils.h"
2829

2930
dfcc_contract_clauses_codegent::dfcc_contract_clauses_codegent(
3031
goto_modelt &goto_model,
3132
message_handlert &message_handler,
3233
dfcc_utilst &utils,
33-
dfcc_libraryt &library,
34-
dfcc_spec_functionst &spec_functions)
34+
dfcc_libraryt &library)
3535
: goto_model(goto_model),
3636
message_handler(message_handler),
3737
log(message_handler),
3838
utils(utils),
3939
library(library),
40-
spec_functions(spec_functions),
4140
ns(goto_model.symbol_table)
4241
{
4342
}
@@ -63,6 +62,7 @@ void dfcc_contract_clauses_codegent::gen_spec_assigns_instructions(
6362

6463
// inline resulting program and check for loops
6564
inline_and_check_warnings(dest);
65+
dest.update();
6666
PRECONDITION_WITH_DIAGNOSTICS(
6767
is_loop_free(dest, ns, log),
6868
"loops in assigns clause specification functions must be unwound before "

src/goto-instrument/contracts/dynamic-frames/dfcc_contract_clauses_codegen.h

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ Date: February 2023
88
\*******************************************************************/
99

1010
/// \file
11-
/// Translates assigns and frees clauses of a function contract or
12-
/// loop contract into goto programs that build write sets or havoc write sets.
1311

1412
#ifndef CPROVER_GOTO_INSTRUMENT_CONTRACTS_DYNAMIC_FRAMES_DFCC_CONTRACT_CLAUSES_CODEGEN_H
1513
#define CPROVER_GOTO_INSTRUMENT_CONTRACTS_DYNAMIC_FRAMES_DFCC_CONTRACT_CLAUSES_CODEGEN_H
@@ -29,25 +27,23 @@ class goto_modelt;
2927
class message_handlert;
3028
class dfcc_libraryt;
3129
class dfcc_utilst;
32-
class dfcc_spec_functionst;
3330
class code_with_contract_typet;
3431
class conditional_target_group_exprt;
3532

33+
/// Translates assigns and frees clauses of a function contract or
34+
/// loop contract into GOTO programs that build write sets or havoc write sets.
3635
class dfcc_contract_clauses_codegent
3736
{
3837
public:
39-
/// \param goto_model goto model being transformed
40-
/// \param message_handler used debug/warning/error messages
41-
/// \param utils utility class for dynamic frames
42-
/// \param library the contracts instrumentation library
43-
/// \param spec_functions provides translation methods for assignable set
44-
/// or freeable set specification functions.
38+
/// \param goto_model GOTO model being transformed
39+
/// \param message_handler Used debug/warning/error messages
40+
/// \param utils Utility class for dynamic frames
41+
/// \param library The contracts instrumentation library
4542
dfcc_contract_clauses_codegent(
4643
goto_modelt &goto_model,
4744
message_handlert &message_handler,
4845
dfcc_utilst &utils,
49-
dfcc_libraryt &library,
50-
dfcc_spec_functionst &spec_functions);
46+
dfcc_libraryt &library);
5147

5248
/// \brief Generates instructions encoding the \p assigns_clause targets and
5349
/// adds them to \p dest.
@@ -85,7 +81,6 @@ class dfcc_contract_clauses_codegent
8581
messaget log;
8682
dfcc_utilst &utils;
8783
dfcc_libraryt &library;
88-
dfcc_spec_functionst &spec_functions;
8984
namespacet ns;
9085

9186
/// Generates GOTO instructions to build the representation of the given

src/goto-instrument/contracts/dynamic-frames/dfcc_contract_handler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ Date: August 2022
2424
#include <goto-programs/remove_function_pointers.h>
2525

2626
#include <ansi-c/c_expr.h>
27-
#include <goto-instrument/contracts/contracts.h>
2827
#include <goto-instrument/contracts/utils.h>
2928
#include <langapi/language_util.h>
3029

@@ -79,7 +78,8 @@ dfcc_contract_handlert::get_contract_functions(const irep_idt &contract_id)
7978
utils,
8079
library,
8180
spec_functions,
82-
contract_clauses_codegen)})
81+
contract_clauses_codegen,
82+
instrument)})
8383
.first->second;
8484
}
8585

0 commit comments

Comments
 (0)