Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
frama-c
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Container Registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
pub
frama-c
Commits
4a4685f3
Commit
4a4685f3
authored
5 years ago
by
David Bühler
Committed by
Andre Maroneze
5 years ago
Browse files
Options
Downloads
Patches
Plain Diff
[Eva] Eval_terms: supports the ACSL extended quantifiers \min and \max.
parent
ee18fc49
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/plugins/value/legacy/eval_terms.ml
+96
-27
96 additions, 27 deletions
src/plugins/value/legacy/eval_terms.ml
with
96 additions
and
27 deletions
src/plugins/value/legacy/eval_terms.ml
+
96
−
27
View file @
4a4685f3
...
@@ -240,6 +240,9 @@ let add_old = add_logic Logic_const.old_label
...
@@ -240,6 +240,9 @@ let add_old = add_logic Logic_const.old_label
let
add_init
state
=
let
add_init
state
=
add_logic
Logic_const
.
init_label
(
Db
.
Value
.
globals_state
()
)
state
add_logic
Logic_const
.
init_label
(
Db
.
Value
.
globals_state
()
)
state
let
add_logic_var
env
lv
cvalue
=
{
env
with
logic_vars
=
LogicVarEnv
.
add
lv
cvalue
env
.
logic_vars
}
let
make_env
logic_env
state
=
let
make_env
logic_env
state
=
let
transfer
label
map
=
let
transfer
label
map
=
Logic_label
.
Map
.
add
label
(
logic_env
.
Abstract_domain
.
states
label
)
map
Logic_label
.
Map
.
add
label
(
logic_env
.
Abstract_domain
.
states
label
)
map
...
@@ -459,6 +462,12 @@ type 'a eval_result = {
...
@@ -459,6 +462,12 @@ type 'a eval_result = {
ldeps
:
logic_deps
;
ldeps
:
logic_deps
;
}
}
let
join_eval_result
r1
r2
=
let
eover
=
Cvalue
.
V
.
join
r2
.
eover
r1
.
eover
in
let
eunder
=
Cvalue
.
V
.
meet
r1
.
eunder
r2
.
eunder
in
let
ldeps
=
join_logic_deps
r1
.
ldeps
r2
.
ldeps
in
{
eover
;
eunder
;
ldeps
;
etype
=
r1
.
etype
;
empty
=
r1
.
empty
||
r2
.
empty
;
}
(* When computing an under-approximation, we make the hypothesis that the state
(* When computing an under-approximation, we make the hypothesis that the state
is not Bottom. Hence, over-approximations of cardinal <= 1 are actually of
is not Bottom. Hence, over-approximations of cardinal <= 1 are actually of
cardinal 1, and are thus exact. *)
cardinal 1, and are thus exact. *)
...
@@ -1361,18 +1370,31 @@ and eval_known_logic_function ~alarm_mode env li labels args =
...
@@ -1361,18 +1370,31 @@ and eval_known_logic_function ~alarm_mode env li labels args =
with
Cvalue
.
V
.
Not_based_on_null
->
c_alarm
()
with
Cvalue
.
V
.
Not_based_on_null
->
c_alarm
()
end
end
|
"
\\
min"
,
Some
Linteger
,
_
,
[
t1
;
t2
]
->
|
(
"
\\
min"
|
"
\\
max"
)
,
Some
typ
,
_
,
t1
::
t2
::
tail_args
->
let
backward
=
Cvalue
.
V
.
backward_comp_int_left
Comp
.
Le
in
begin
eval_extremum
Cil
.
intType
backward
~
alarm_mode
env
t1
t2
let
comp
=
if
lvi
.
lv_name
=
"
\\
min"
then
Comp
.
Le
else
Comp
.
Ge
in
|
"
\\
max"
,
Some
Linteger
,
_
,
[
t1
;
t2
]
->
let
backward
=
let
backward
=
Cvalue
.
V
.
backward_comp_int_left
Comp
.
Ge
in
match
typ
with
eval_extremum
Cil
.
intType
backward
~
alarm_mode
env
t1
t2
|
Linteger
->
Cvalue
.
V
.
backward_comp_int_left
comp
|
"
\\
min"
,
Some
Lreal
,
_
,
[
t1
;
t2
]
->
|
Lreal
->
Cvalue
.
V
.
backward_comp_float_left_true
comp
Fval
.
Real
let
backward
=
Cvalue
.
V
.
backward_comp_float_left_true
Comp
.
Le
Fval
.
Real
in
|
_
->
assert
false
eval_extremum
Cil
.
floatType
backward
~
alarm_mode
env
t1
t2
in
|
"
\\
max"
,
Some
Lreal
,
_
,
[
t1
;
t2
]
->
let
r1
=
eval_term
~
alarm_mode
env
t1
let
backward
=
Cvalue
.
V
.
backward_comp_float_left_true
Comp
.
Ge
Fval
.
Real
in
and
r2
=
eval_term
~
alarm_mode
env
t2
in
eval_extremum
Cil
.
doubleType
backward
~
alarm_mode
env
t1
t2
(* If there are 2 arguments, it is the mathematical function \min or \max.
If there are 3, it is the ACSL extended quantifiers \min or \max. *)
match
tail_args
with
|
[]
->
compute_extremum
backward
r1
r2
|
[
{
term_node
=
Tlambda
([
lv
]
,
term
)
}
]
->
(* Evaluation of [term] when the logic variable [lv] is in [cvalue]. *)
let
eval_term
cvalue
=
let
env
=
add_logic_var
env
lv
cvalue
in
eval_term
~
alarm_mode
env
term
in
eval_quantifier_extremum
backward
~
min
:
r1
~
max
:
r2
eval_term
|
_
->
assert
false
end
|
_
->
assert
false
|
_
->
assert
false
and
eval_float_builtin_arity2
~
alarm_mode
env
name
arg1
arg2
=
and
eval_float_builtin_arity2
~
alarm_mode
env
name
arg1
arg2
=
...
@@ -1401,19 +1423,68 @@ and eval_float_builtin_arity2 ~alarm_mode env name arg1 arg2 =
...
@@ -1401,19 +1423,68 @@ and eval_float_builtin_arity2 ~alarm_mode env name arg1 arg2 =
let
ldeps
=
join_logic_deps
r1
.
ldeps
r2
.
ldeps
in
let
ldeps
=
join_logic_deps
r1
.
ldeps
r2
.
ldeps
in
{
etype
=
r1
.
etype
;
eunder
;
eover
=
v
;
ldeps
;
empty
=
r1
.
empty
||
r2
.
empty
;
}
{
etype
=
r1
.
etype
;
eunder
;
eover
=
v
;
ldeps
;
empty
=
r1
.
empty
||
r2
.
empty
;
}
(* Evaluates the max (resp. the min) between the terms [t1] and [t2],
(* Computes the max (resp. the min) between the evaluation results [r1] and [r2]
according to [backward_left v1 v2] that reduces [v1] by assuming it is
according to [backward_left v1 v2] that reduces [v1] by assuming it is
greater than (resp. lower than) [v2]. *)
greater than (resp. lower than) [v2]. *)
and
eval_extremum
etype
backward_left
~
alarm_mode
env
t1
t2
=
and
compute_extremum
backward_left
r1
r2
=
let
r1
=
eval_term
~
alarm_mode
env
t1
let
r1
=
{
r1
with
eover
=
backward_left
r1
.
eover
r2
.
eover
}
and
r2
=
eval_term
~
alarm_mode
env
t2
in
and
r2
=
{
r2
with
eover
=
backward_left
r2
.
eover
r1
.
eover
}
in
let
reduced_v1
=
backward_left
r1
.
eover
r2
.
eover
join_eval_result
r1
r2
and
reduced_v2
=
backward_left
r2
.
eover
r1
.
eover
in
let
eover
=
Cvalue
.
V
.
join
reduced_v1
reduced_v2
in
(* Evaluates ACSL extended quantifiers \max or \min: computes (an approximation
let
eunder
=
Cvalue
.
V
.
meet
r1
.
eunder
r2
.
eunder
in
of) the max (resp. the min) of [eval_term i] when [i] ranges between [min]
let
ldeps
=
join_logic_deps
r1
.
ldeps
r2
.
ldeps
in
and [max], according to [backward_left v1 v2] that reduces [v1] by assuming
{
eover
;
eunder
;
ldeps
;
etype
;
empty
=
r1
.
empty
||
r2
.
empty
;
}
it is greater (resp. lower) than [v2]. *)
and
eval_quantifier_extremum
backward_left
~
min
~
max
eval_term
=
(* Returns [r] as the result, with updated [empty] and [ldeps] fields. *)
let
return
r
=
let
ldeps
=
join_logic_deps
r
.
ldeps
(
join_logic_deps
min
.
ldeps
max
.
ldeps
)
in
let
empty
=
min
.
empty
||
max
.
empty
||
r
.
empty
in
{
r
with
ldeps
;
empty
;
}
in
let
eval_ival
ival
=
eval_term
(
Cvalue
.
V
.
inject_ival
ival
)
in
let
project
r
=
Cvalue
.
V
.
project_ival
r
.
eover
in
match
Ival
.
min_and_max
(
project
min
)
,
Ival
.
min_and_max
(
project
max
)
with
|
(
min
,
Some
b
)
,
(
Some
e
,
max
)
when
Integer
.
le
b
e
->
(* All integers between [b] and [e] are necessarily in the range to be
considered. If [e-b] is small enough, evaluate [eval_term i] for each [i]
between [b] and [e]. Otherwise, evaluate [eval_term] for the bound [b]
and [e], and for the interval [b+1..e-1]. We could be more precise by
subdividing the interval. *)
let
r
=
if
Integer
.
equal
e
b
then
eval_term
(
Cvalue
.
V
.
inject_int
b
)
else
let
fold
=
if
Integer
.(
le
(
sub
e
b
)
(
of_int
10
))
then
Ival
.
fold_enum
else
Ival
.
fold_int_bounds
in
let
ival
=
Ival
.
inject_range
(
Some
b
)
(
Some
e
)
in
let
list
=
fold
(
fun
i
acc
->
eval_ival
i
::
acc
)
ival
[]
in
(* Reduce each result to only keep the possible extrema. *)
let
hd
,
tl
=
List
.
hd
list
,
List
.
tl
list
in
List
.
fold_left
(
compute_extremum
backward_left
)
hd
tl
in
(* Integers below [b] and above [e] may not be in the range to be considered,
so we can't reduce [r] according to them. However, we must join to [r]
the evaluation of [eval_term] for these integers, and we can reduce
these evaluations to only keep results greater (or lower, according to
[backward_left]) than [r]. *)
let
below
=
eval_ival
(
Ival
.
inject_range
min
(
Some
(
Integer
.
pred
b
)))
and
above
=
eval_ival
(
Ival
.
inject_range
(
Some
(
Integer
.
succ
e
))
max
)
in
let
below
=
{
below
with
eover
=
backward_left
below
.
eover
r
.
eover
}
and
above
=
{
above
with
eover
=
backward_left
above
.
eover
r
.
eover
}
in
join_eval_result
r
(
join_eval_result
below
above
)
|
(
b
,
_
)
,
(
_
,
e
)
->
(* If [min] can be greater than [max], the result is unspecified. *)
let
r
=
eval_ival
(
Ival
.
inject_range
b
e
)
in
return
{
r
with
eover
=
Cvalue
.
V
.
top
;
eunder
=
Cvalue
.
V
.
bottom
}
|
exception
Cvalue
.
V
.
Not_based_on_null
->
let
r
=
eval_term
(
Cvalue
.
V
.
join
min
.
eover
max
.
eover
)
in
return
{
r
with
eover
=
Cvalue
.
V
.
top
;
eunder
=
Cvalue
.
V
.
bottom
}
let
eval_tlval_as_location
~
alarm_mode
env
t
=
let
eval_tlval_as_location
~
alarm_mode
env
t
=
let
r
=
eval_term_as_lval
~
alarm_mode
env
t
in
let
r
=
eval_term_as_lval
~
alarm_mode
env
t
in
...
@@ -1814,8 +1885,7 @@ let reduce_by_left_relation ~alarm_mode env positive tl rel tr =
...
@@ -1814,8 +1885,7 @@ let reduce_by_left_relation ~alarm_mode env positive tl rel tr =
let
reduce
=
Eval_op
.
backward_comp_left_from_type
logic_var
.
lv_type
in
let
reduce
=
Eval_op
.
backward_comp_left_from_type
logic_var
.
lv_type
in
let
cvalue
=
reduce
positive
comp
cvalue
cond_v
in
let
cvalue
=
reduce
positive
comp
cvalue
cond_v
in
if
V
.
is_bottom
cvalue
then
raise
Reduce_to_bottom
;
if
V
.
is_bottom
cvalue
then
raise
Reduce_to_bottom
;
let
logic_vars
=
LogicVarEnv
.
add
logic_var
cvalue
env
.
logic_vars
in
add_logic_var
env
logic_var
cvalue
{
env
with
logic_vars
}
|
Location
(
typ_loc
,
locs
)
->
|
Location
(
typ_loc
,
locs
)
->
let
reduce
=
Eval_op
.
backward_comp_left_from_type
(
Ctype
typ_loc
)
in
let
reduce
=
Eval_op
.
backward_comp_left_from_type
(
Ctype
typ_loc
)
in
if
debug
then
Format
.
printf
"#Val right term %a@."
V
.
pretty
cond_v
;
if
debug
then
Format
.
printf
"#Val right term %a@."
V
.
pretty
cond_v
;
...
@@ -1937,8 +2007,7 @@ let reduce_by_known_papp ~alarm_mode env positive li _labels args =
...
@@ -1937,8 +2007,7 @@ let reduce_by_known_papp ~alarm_mode env positive li _labels args =
let
vl
=
LogicVarEnv
.
find
logic_var
env
.
logic_vars
in
let
vl
=
LogicVarEnv
.
find
logic_var
env
.
logic_vars
in
let
reduced
=
Cvalue
.
V
.
narrow
vl
vr
in
let
reduced
=
Cvalue
.
V
.
narrow
vl
vr
in
if
V
.
equal
V
.
bottom
reduced
then
raise
Reduce_to_bottom
;
if
V
.
equal
V
.
bottom
reduced
then
raise
Reduce_to_bottom
;
let
logic_vars
=
LogicVarEnv
.
add
logic_var
reduced
env
.
logic_vars
in
add_logic_var
env
logic_var
reduced
{
env
with
logic_vars
}
|
Location
(
_typ
,
locsl
)
->
|
Location
(
_typ
,
locsl
)
->
let
aux
locl
env
=
let
aux
locl
env
=
let
state
=
env_current_state
env
in
let
state
=
env_current_state
env
in
...
...
This diff is collapsed.
Click to expand it.
Andre Maroneze
@maroneze
mentioned in issue
#62 (closed)
·
4 years ago
mentioned in issue
#62 (closed)
mentioned in issue #62
Toggle commit list
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment