Skip to content

Commit 01a1122

Browse files
author
Remi Delmas
committed
added generation of havoc functions from assigns clauses
1 parent 45aaaff commit 01a1122

File tree

8 files changed

+385
-83
lines changed

8 files changed

+385
-83
lines changed

src/goto-instrument/contracts/dfcc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ void dfcct::transform_goto_model(
348348
}
349349

350350
goto_model.goto_functions.update();
351-
library.specialize_functions(max_assigns_clause_size);
351+
library.specialize(max_assigns_clause_size);
352352
utils.create_initialize_function();
353353
}
354354

src/goto-instrument/contracts/dfcc_contract_handler.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,25 @@ class goto_programt;
1919
class dfcc_contract_handlert
2020
{
2121
public:
22-
/// Adds instruction modeling contract checking to dest
22+
/// Adds instruction modeling contract checking to dest.
23+
/// \param wrapped_id name of the wrapped function that is being checked
24+
/// \param wrapper_id name of the wrapper function for which the instructions
25+
/// are generated
26+
/// \param contract_id name of the contract to check
27+
/// \param dest destination program where instructions are added
2328
virtual void add_contract_checking_instructions(
2429
const irep_idt &wrapped_id,
2530
const irep_idt &wrapper_id,
2631
const irep_idt &contract_id,
2732
goto_programt &dest) = 0;
2833

29-
/// Adds instruction modeling contract replacement to dest
34+
/// Adds instruction modeling contract replacement to dest.
35+
/// \param wrapper_id name of the wrapper function for which the instructions
36+
/// are generated
37+
/// \param contract_id name of the contract to check
38+
/// \param wrapper_write_set_symbol symbol of the write set against which
39+
/// to check the contract's write set for inclusion
40+
/// \param dest destination program where instructions are added
3041
virtual void add_contract_replacement_instructions(
3142
const irep_idt &wrapper_id,
3243
const irep_idt &contract_id,

src/goto-instrument/contracts/dfcc_library.cpp

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ dfcc_libraryt::dfcc_libraryt(
3333
{
3434
}
3535

36-
/// Enum to type name mapping
36+
/// enum to type name mapping
3737
static const std::map<dfcc_typet, irep_idt> dfcc_type_name = {
3838
{dfcc_typet::FREEABLE, CPROVER_PREFIX "freeable_t"},
3939
{dfcc_typet::ASSIGNABLE, CPROVER_PREFIX "assignable_t"},
@@ -45,7 +45,7 @@ static const std::map<dfcc_typet, irep_idt> dfcc_type_name = {
4545
{dfcc_typet::SET, CPROVER_PREFIX "assignable_set_t"},
4646
{dfcc_typet::SET_PTR, CPROVER_PREFIX "assignable_set_ptr_t"}};
4747

48-
/// Enum to function name mapping
48+
/// enum to function name mapping
4949
static const std::map<dfcc_funt, irep_idt> dfcc_fun_name = {
5050
{dfcc_funt::CAR_CREATE, CPROVER_PREFIX "assignable_car_create"},
5151
{dfcc_funt::CAR_SET_CREATE, CPROVER_PREFIX "assignable_car_set_create"},
@@ -92,9 +92,17 @@ static const std::map<dfcc_funt, irep_idt> dfcc_fun_name = {
9292
{dfcc_funt::SET_CHECK_FREES_CLAUSE_INCLUSION,
9393
CPROVER_PREFIX "assignable_set_check_frees_clause_inclusion"},
9494
{dfcc_funt::SET_DEALLOCATE_FREEABLE,
95-
CPROVER_PREFIX "assignable_set_deallocate_freeable"}};
96-
97-
/// Built-in function name to enum to use for instrumentation
95+
CPROVER_PREFIX "assignable_set_deallocate_freeable"},
96+
{dfcc_funt::SET_HAVOC_GET_ASSIGNABLE_TARGET,
97+
CPROVER_PREFIX "assignable_set_havoc_get_assignable_target"},
98+
{dfcc_funt::SET_HAVOC_WHOLE_OBJECT,
99+
CPROVER_PREFIX "assignable_set_havoc_whole_object"},
100+
{dfcc_funt::SET_HAVOC_OBJECT_FROM,
101+
CPROVER_PREFIX "assignable_set_havoc_object_from"},
102+
{dfcc_funt::SET_HAVOC_OBJECT_UPTO,
103+
CPROVER_PREFIX "assignable_set_havoc_object_upto"}};
104+
105+
/// built-in function name to enum to use for instrumentation
98106
static const std::map<irep_idt, dfcc_funt> dfcc_hook = {
99107
{CPROVER_PREFIX "assignable", dfcc_funt::SET_INSERT_ASSIGNABLE},
100108
{CPROVER_PREFIX "whole_object", dfcc_funt::SET_INSERT_WHOLE_OBJECT},
@@ -111,7 +119,23 @@ optionalt<dfcc_funt> dfcc_libraryt::get_hook(const irep_idt &function_id) const
111119
return {};
112120
}
113121

114-
/// Built-in function names (front-end and instrumentation hooks)
122+
static const std::map<irep_idt, dfcc_funt> havoc_hook = {
123+
{CPROVER_PREFIX "assignable", dfcc_funt::SET_HAVOC_GET_ASSIGNABLE_TARGET},
124+
{CPROVER_PREFIX "whole_object", dfcc_funt::SET_HAVOC_WHOLE_OBJECT},
125+
{CPROVER_PREFIX "object_from", dfcc_funt::SET_HAVOC_OBJECT_FROM},
126+
{CPROVER_PREFIX "object_upto", dfcc_funt::SET_HAVOC_OBJECT_UPTO}};
127+
128+
optionalt<dfcc_funt>
129+
dfcc_libraryt::get_havoc_hook(const irep_idt &function_id) const
130+
{
131+
auto found = havoc_hook.find(function_id);
132+
if(found != havoc_hook.end())
133+
return {found->second};
134+
else
135+
return {};
136+
}
137+
138+
/// built-in function names (front-end and instrumentation hooks)
115139
static const std::set<irep_idt> assignable_builtin_names = {
116140
CPROVER_PREFIX "assignable",
117141
CPROVER_PREFIX "assignable_set_insert_assignable",
@@ -144,7 +168,7 @@ void dfcc_libraryt::get_missing_funs(std::set<irep_idt> &missing)
144168
}
145169
}
146170

147-
// true iff library symbols have been loaded
171+
// true iff library symbols have already been loaded
148172
static bool loaded = false;
149173

150174
void dfcc_libraryt::load()
@@ -198,7 +222,6 @@ void dfcc_libraryt::load()
198222
throw 0;
199223
}
200224
dfcc_fun_symbol[pair.first] = ns.lookup(pair.second);
201-
//dfcc_fun_symbol_expr[pair.first] = ns.lookup(pair.second).symbol_expr();
202225
}
203226

204227
// populate symbol maps for easy access to symbols during translation
@@ -221,7 +244,7 @@ bool dfcc_libraryt::is_special_builtin(const irep_idt &id) const
221244
return special_builtins.find(id) != special_builtins.end();
222245
}
223246

224-
/// Set of functions that need to be inlined for specialisation
247+
/// set of functions that need to be inlined for specialisation
225248
static const std::set<dfcc_funt> to_inline = {
226249
dfcc_funt::SET_CREATE,
227250
dfcc_funt::SET_INSERT_ASSIGNABLE,
@@ -242,7 +265,9 @@ static const std::set<dfcc_funt> to_inline = {
242265
dfcc_funt::SET_CHECK_FREES_CLAUSE_INCLUSION,
243266
dfcc_funt::SET_DEALLOCATE_FREEABLE};
244267

268+
/// true iff the library functions have already been inlined
245269
static bool inlined = false;
270+
246271
void dfcc_libraryt::inline_functions()
247272
{
248273
INVARIANT(!inlined, "inlined_functions can only be called once");
@@ -253,7 +278,7 @@ void dfcc_libraryt::inline_functions()
253278
}
254279
}
255280

256-
/// Set of functions that need to be unwound to assigns clause size with
281+
/// set of functions that need to be unwound to assigns clause size with
257282
/// corresponding loop labels.
258283
static const std::map<dfcc_funt, irep_idt> to_unwind = {
259284
{dfcc_funt::SET_REMOVE_DEALLOCATED, "CAR_SET_REMOVE_LOOP"},
@@ -266,7 +291,7 @@ static const std::map<dfcc_funt, irep_idt> to_unwind = {
266291
/// true iff the library functions have already been specialized
267292
static bool specialized = false;
268293

269-
void dfcc_libraryt::specialize_functions(const int contract_assigns_size_hint)
294+
void dfcc_libraryt::specialize(const int contract_assigns_size_hint)
270295
{
271296
INVARIANT(
272297
!specialized,

src/goto-instrument/contracts/dfcc_library.h

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@ Author: Remi Delmas, [email protected]
1212
#ifndef CPROVER_GOTO_INSTRUMENT_CONTRACTS_DFCC_LIBRARY_H
1313
#define CPROVER_GOTO_INSTRUMENT_CONTRACTS_DFCC_LIBRARY_H
1414

15+
#include <util/irep.h>
1516
#include <util/optional.h>
1617

17-
/// Library types used in the instrumentation
18+
#include <map>
19+
#include <set>
20+
21+
/// One enum value per type defined by the `cprover_dfcc.c` library file.
1822
enum class dfcc_typet
1923
{
2024
FREEABLE,
@@ -28,7 +32,7 @@ enum class dfcc_typet
2832
SET_PTR
2933
};
3034

31-
/// Library functions used in the instrumentation
35+
/// One enum value per function defined by the `cprover_dfcc.c` library file.
3236
enum class dfcc_funt
3337
{
3438
CAR_CREATE,
@@ -60,7 +64,11 @@ enum class dfcc_funt
6064
SET_CHECK_DEALLOCATE,
6165
SET_CHECK_ASSIGNS_CLAUSE_INCLUSION,
6266
SET_CHECK_FREES_CLAUSE_INCLUSION,
63-
SET_DEALLOCATE_FREEABLE
67+
SET_DEALLOCATE_FREEABLE,
68+
SET_HAVOC_GET_ASSIGNABLE_TARGET,
69+
SET_HAVOC_WHOLE_OBJECT,
70+
SET_HAVOC_OBJECT_FROM,
71+
SET_HAVOC_OBJECT_UPTO
6472
};
6573

6674
class goto_modelt;
@@ -72,13 +80,8 @@ class symbol_exprt;
7280
class typet;
7381
class dfcc_utilst;
7482

75-
#include <util/irep.h>
76-
77-
#include <map>
78-
#include <set>
79-
80-
/// A programmatic interface to library types and functions
81-
/// defined in `src/ansi-c/library/cprover_dfcc.c`.
83+
/// Programmatic interface to library types and functions defined in
84+
/// `cprover_dfcc.c`.
8285
class dfcc_libraryt
8386
{
8487
public:
@@ -90,52 +93,45 @@ class dfcc_libraryt
9093
messaget &log;
9194
message_handlert &message_handler;
9295

93-
/// Collects the names of all currently missing dfcc functions
94-
/// in the goto_model
96+
/// Collects the names of all library functions currently missing from the
97+
/// goto_model into missing.
9598
void get_missing_funs(std::set<irep_idt> &missing);
9699

100+
/// Inlines library functions that need to be inlined before use
101+
void inline_functions();
102+
97103
public:
98-
/// enum-to-typet mapping (dynamically loaded)
104+
/// Maps enum values to the actual types (dynamically loaded)
99105
std::map<dfcc_typet, typet> dfcc_type;
100106

101-
/// enum-to-symbol mapping (dynamically loaded)
107+
/// Maps enum values to the actual function symbols (dynamically loaded)
102108
std::map<dfcc_funt, symbolt> dfcc_fun_symbol;
103109

104-
/// enum-to-symbol_exprt mapping (dynamically loaded)
105-
std::map<dfcc_funt, symbol_exprt> dfcc_fun_symbol_expr;
106-
107-
/// Adds all the `cprover_dfcc.c` library types and functions to the model
110+
/// After calling this function, all library types and functions are present
111+
/// in the the goto_model.
108112
void load();
109113

110114
/// True iff the id starts with CPROVER_PREFIX
111-
/// that we do not want to instrument
112115
bool is_cprover_symbol(const irep_idt &id) const;
113116

114-
/// True iff the id is one of the special builtins
115-
/// that we do not want to instrument
117+
/// True iff the id is one of the special builtins that musnt be instrumented
116118
bool is_special_builtin(const irep_idt &id) const;
117119

118-
/// Inlines library functions as specified in the `inline_and_unwind` map.
119-
void inline_functions();
120+
/// Specializes the library by unwinding loops in library functions
121+
/// to the given assigns clause size.
122+
/// \param contract_assigns_size_hint size of the assigns clause being checked
123+
void specialize(const int contract_assigns_size_hint);
120124

121-
/// Specialises the library function code to a specific contract
122-
/// by inlining and unwinding loops in library functions that require it,
123-
/// based on the given size hints for the assigns clause and the frees clause
124-
/// of the checked contract.
125-
void unwind_functions(const int assigns_size_hint, const int frees_size_hint);
126-
127-
/// Specialises the library function code to a specific contract unwinding
128-
/// loops in library functions using the given hint for assigns clause size.
129-
/// \param contract_assigns_size_hint assigns clause size to unwind to
130-
/// \param continue_as_loops value of the goto-instrument command line switch
131-
/// (to detect incompatibility with unwind assertions)
132-
void specialize_functions(const int contract_assigns_size_hint);
133-
134-
/// returns the library instrumentation hook for the given built-in
135-
/// function_id must be one of
136-
/// {__CPROVER_assignable, __CPROVER_whole_object, __CPROVER_object_from,
137-
/// __CPROVER_object_upto, __CPROVER_freeable }
125+
/// Returns the library instrumentation hook for the given built-in.
126+
/// function_id must be one of `__CPROVER_assignable`,
127+
/// `__CPROVER_whole_object`, `__CPROVER_object_from`,
128+
/// `__CPROVER_object_upto`, `__CPROVER_freeable`
138129
optionalt<dfcc_funt> get_hook(const irep_idt &function_id) const;
130+
131+
/// Returns the library instrumentation hook for the given built-in.
132+
/// function_id must be one of `__CPROVER_assignable`,
133+
/// `__CPROVER_whole_object`, `__CPROVER_object_from`, `__CPROVER_object_upto`
134+
optionalt<dfcc_funt> get_havoc_hook(const irep_idt &function_id) const;
139135
};
140136

141137
#endif

0 commit comments

Comments
 (0)