-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathinterval_analysis.cpp
102 lines (84 loc) · 3.18 KB
/
interval_analysis.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*******************************************************************\
Module: Interval Analysis
Author: Daniel Kroening, [email protected]
\*******************************************************************/
/// \file
/// Interval Analysis -- implements the functionality necessary for performing
/// abstract interpretation over interval domain for goto programs. The result
/// of the analysis is an instrumented program.
#include "interval_analysis.h"
#include <util/find_symbols.h>
#include "ai.h"
#include "interval_domain.h"
/// Instruments all "post-branch" instructions with assumptions about variable
/// intervals. For each such instruction, the function evaluates all variables
/// referenced within the input goto_function as intervals, transforms these
/// intervals into expressions and instruments the instruction with their
/// conjunction.
/// Example: interval [5,10] (for variable "x") translates into conjunction
/// 5 <= x && x <= 10.
/// \param interval_analysis: Interval domain to be used for variable evaluation
/// \param [out] goto_function: Goto function to be analysed and instrumented.
void instrument_intervals(
const ait<interval_domaint> &interval_analysis,
goto_functionst::goto_functiont &goto_function)
{
std::set<symbol_exprt> symbols;
for(const auto &i : goto_function.body.instructions)
i.apply([&symbols](const exprt &e) { find_symbols(e, symbols); });
Forall_goto_program_instructions(i_it, goto_function.body)
{
if(i_it==goto_function.body.instructions.begin())
{
// first instruction, we instrument
}
else
{
goto_programt::const_targett previous = std::prev(i_it);
if(
previous->is_goto() &&
(!previous->condition().is_constant() ||
!to_constant_expr(previous->condition()).is_true()))
{
// we follow a branch, instrument
}
else if(previous->is_function_call())
{
// we follow a function call, instrument
}
else if(i_it->is_target() || i_it->is_function_call())
{
// we are a target or a function call, instrument
}
else
continue; // don't instrument
}
const interval_domaint &d=interval_analysis[i_it];
exprt::operandst assertion;
for(const auto &symbol_expr : symbols)
{
exprt tmp=d.make_expression(symbol_expr);
if(!tmp.is_constant() || !to_constant_expr(tmp).is_true())
assertion.push_back(tmp);
}
if(!assertion.empty())
{
goto_programt::targett t=i_it;
goto_function.body.insert_before_swap(i_it);
i_it++; // goes to original instruction
*t = goto_programt::make_assumption(
conjunction(assertion), i_it->source_location());
}
}
}
/// Initialises the abstract interpretation over interval domain and
/// instruments instructions using interval assumptions.
/// \param [out] goto_model: Input code as goto_model.
void interval_analysis(goto_modelt &goto_model)
{
ait<interval_domaint> interval_analysis;
const namespacet ns(goto_model.symbol_table);
interval_analysis(goto_model.goto_functions, ns);
for(auto &gf_entry : goto_model.goto_functions.function_map)
instrument_intervals(interval_analysis, gf_entry.second);
}