Skip to content

Commit aeaad9a

Browse files
author
Remi Delmas
committed
CONTRACTS: loop assigns clause inference function
1 parent c43d650 commit aeaad9a

File tree

4 files changed

+134
-0
lines changed

4 files changed

+134
-0
lines changed

src/goto-instrument/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ SRC = accelerate/accelerate.cpp \
2222
contracts/dynamic-frames/dfcc_contract_mode.cpp \
2323
contracts/dynamic-frames/dfcc_loop_contract_mode.cpp \
2424
contracts/dynamic-frames/dfcc_root_object.cpp \
25+
contracts/dynamic-frames/dfcc_infer_loop_assigns.cpp \
2526
contracts/dynamic-frames/dfcc_library.cpp \
2627
contracts/dynamic-frames/dfcc_is_cprover_symbol.cpp \
2728
contracts/dynamic-frames/dfcc_is_fresh.cpp \
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*******************************************************************\
2+
3+
Module: Dynamic frame condition checking
4+
5+
Author: Remi Delmas, [email protected]
6+
7+
\*******************************************************************/
8+
#include "dfcc_infer_loop_assigns.h"
9+
10+
#include <util/expr.h>
11+
#include <util/find_symbols.h>
12+
#include <util/message.h>
13+
#include <util/pointer_expr.h>
14+
#include <util/std_code.h>
15+
16+
#include <goto-instrument/havoc_utils.h>
17+
#include <langapi/language_util.h>
18+
19+
#include "dfcc_root_object.h"
20+
21+
/// Builds a call expression `object_whole(expr)`
22+
static exprt
23+
make_object_whole_call_expr(const exprt &expr, const namespacet &ns)
24+
{
25+
const symbolt &object_whole_sym = ns.lookup(CPROVER_PREFIX "object_whole");
26+
const code_typet &object_whole_code_type = to_code_type(object_whole_sym.type);
27+
exprt::operandst args{{expr}};
28+
return side_effect_expr_function_callt(
29+
object_whole_sym.symbol_expr(),
30+
args,
31+
object_whole_code_type.return_type(),
32+
expr.source_location());
33+
}
34+
35+
/// Returns true iff \p expr contains at least one identifier found in
36+
/// \p identifiers.
37+
static bool
38+
depends_on(const exprt &expr, std::unordered_set<irep_idt> identifiers)
39+
{
40+
const std::unordered_set<irep_idt> ids = find_symbol_identifiers(expr);
41+
for(const auto &id : ids)
42+
{
43+
if(identifiers.find(id) != identifiers.end())
44+
return true;
45+
}
46+
return false;
47+
}
48+
49+
std::set<exprt> dfcc_infer_loop_assigns(
50+
const local_may_aliast &local_may_alias,
51+
const loopt &loop_instructions,
52+
const source_locationt &loop_head_location,
53+
messaget &log,
54+
const namespacet &ns)
55+
{
56+
// infer
57+
assignst assigns;
58+
get_assigns(local_may_alias, loop_instructions, assigns);
59+
60+
// compute locals
61+
std::unordered_set<irep_idt> loop_locals;
62+
for(const auto &target : loop_instructions)
63+
{
64+
if(target->is_decl())
65+
loop_locals.insert(target->decl_symbol().get_identifier());
66+
}
67+
68+
// widen or drop targets that depend on loop-locals or are non-constant
69+
havoc_utils_is_constantt is_constant(assigns, ns);
70+
assignst result;
71+
for(const auto &expr : assigns)
72+
{
73+
if(depends_on(expr, loop_locals))
74+
{
75+
// Target depends on loop locals, attempt widening to the root object
76+
auto root_object = dfcc_assigns_target_single_root_object(expr, ns, log);
77+
if(!depends_on(root_object, loop_locals))
78+
{
79+
address_of_exprt address_of_root_object(root_object);
80+
address_of_root_object.add_source_location() =
81+
root_object.source_location();
82+
result.emplace(make_object_whole_call_expr(address_of_root_object, ns));
83+
}
84+
}
85+
else
86+
{
87+
address_of_exprt address_of_expr(expr);
88+
address_of_expr.add_source_location() = expr.source_location();
89+
if(!is_constant(address_of_expr))
90+
{
91+
// Target address is not constant, widening to the whole object
92+
result.emplace(make_object_whole_call_expr(address_of_expr, ns));
93+
}
94+
else
95+
{
96+
result.emplace(expr);
97+
}
98+
}
99+
}
100+
101+
return result;
102+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*******************************************************************\
2+
3+
Module: Dynamic frame condition checking
4+
5+
Author: Remi Delmas, [email protected]
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Infer a set of assigns clause targets for a natural loop.
11+
12+
#ifndef CPROVER_GOTO_INSTRUMENT_CONTRACTS_DYNAMIC_FRAMES_DFCC_INFER_LOOP_ASSIGNS_H
13+
#define CPROVER_GOTO_INSTRUMENT_CONTRACTS_DYNAMIC_FRAMES_DFCC_INFER_LOOP_ASSIGNS_H
14+
15+
#include <analyses/local_may_alias.h>
16+
#include <goto-instrument/loop_utils.h>
17+
class source_locationt;
18+
class messaget;
19+
class namespacet;
20+
21+
// \brief Infer assigns clause targets for a loop from its instructions and a
22+
// may alias analysis at the function level.
23+
std::set<exprt> dfcc_infer_loop_assigns(
24+
const local_may_aliast &local_may_alias,
25+
const loopt &loop_instructions,
26+
const source_locationt &loop_head_location,
27+
messaget &log,
28+
const namespacet &ns);
29+
30+
#endif

src/goto-instrument/contracts/dynamic-frames/module_dependencies.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
analyses
12
ansi-c
23
goto-instrument/contracts
34
goto-instrument/contracts/dynamic-frames

0 commit comments

Comments
 (0)