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
e5e0f11a
Commit
e5e0f11a
authored
4 years ago
by
Loïc Correnson
Browse files
Options
Downloads
Patches
Plain Diff
[wp] fix corner cases for unreachability
parent
61445a7d
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/plugins/wp/wpAnnot.ml
+12
-13
12 additions, 13 deletions
src/plugins/wp/wpAnnot.ml
src/plugins/wp/wpReached.ml
+32
-16
32 additions, 16 deletions
src/plugins/wp/wpReached.ml
src/plugins/wp/wpReached.mli
+4
-4
4 additions, 4 deletions
src/plugins/wp/wpReached.mli
with
48 additions
and
33 deletions
src/plugins/wp/wpAnnot.ml
+
12
−
13
View file @
e5e0f11a
...
@@ -238,7 +238,7 @@ module HdefAnnotBhv = Cil2cfg.HE (struct type t = (stmt * int) end)
...
@@ -238,7 +238,7 @@ module HdefAnnotBhv = Cil2cfg.HE (struct type t = (stmt * int) end)
type
strategy_info
=
{
type
strategy_info
=
{
kf
:
Kernel_function
.
t
;
kf
:
Kernel_function
.
t
;
cfg
:
Cil2cfg
.
t
;
cfg
:
Cil2cfg
.
t
;
reach
ed
:
WpReached
.
reach
ed
option
;
reach
ability
:
WpReached
.
reach
ability
option
;
cur_bhv
:
asked_bhv
;
cur_bhv
:
asked_bhv
;
asked_bhvs
:
asked_bhv
list
;
asked_bhvs
:
asked_bhv
list
;
asked_prop
:
asked_prop
;
asked_prop
:
asked_prop
;
...
@@ -915,7 +915,7 @@ let get_loop_annots config vloop s =
...
@@ -915,7 +915,7 @@ let get_loop_annots config vloop s =
let
add_stmt_deadcode_smoke
config
acc
s
=
let
add_stmt_deadcode_smoke
config
acc
s
=
if
cur_fct_default_bhv
config
if
cur_fct_default_bhv
config
then
then
match
config
.
reach
ed
with
match
config
.
reach
ability
with
|
Some
r
when
WpReached
.
smoking
r
s
->
|
Some
r
when
WpReached
.
smoking
r
s
->
WpStrategy
.
add_prop_dead_code
acc
config
.
kf
s
WpStrategy
.
add_prop_dead_code
acc
config
.
kf
s
|
_
->
acc
|
_
->
acc
...
@@ -1298,6 +1298,8 @@ let process_unreached_annots cfg =
...
@@ -1298,6 +1298,8 @@ let process_unreached_annots cfg =
let
do_annot
s
_
a
acc
=
let
do_annot
s
_
a
acc
=
List
.
fold_left
add_id
acc
(
WpPropId
.
mk_code_annot_ids
kf
s
a
)
List
.
fold_left
add_id
acc
(
WpPropId
.
mk_code_annot_ids
kf
s
a
)
in
in
let
do_stmt
s
acc
=
Annotations
.
fold_code_annot
(
do_annot
s
)
s
acc
in
let
do_node
acc
n
=
let
do_node
acc
n
=
debug
debug
"process annotations of unreachable node %a@."
"process annotations of unreachable node %a@."
...
@@ -1312,13 +1314,13 @@ let process_unreached_annots cfg =
...
@@ -1312,13 +1314,13 @@ let process_unreached_annots cfg =
ignore
Visitor
.(
visitFramacKf
(
visitor
:>
frama_c_visitor
)
kf
)
;
ignore
Visitor
.(
visitFramacKf
(
visitor
:>
frama_c_visitor
)
kf
)
;
visitor
#
acc
visitor
#
acc
|
Cil2cfg
.
Vcall
(
s
,
_
,
call
,
_
)
->
|
Cil2cfg
.
Vcall
(
s
,
_
,
call
,
_
)
->
Annotations
.
fold_code_annot
(
do_annot
s
)
s
acc
@
do_stmt
s
acc
@
preconditions_at_call
s
call
preconditions_at_call
s
call
|
Cil2cfg
.
Vstmt
s
|
Cil2cfg
.
Vstmt
s
|
Cil2cfg
.
VblkIn
(
Cil2cfg
.
Bstmt
s
,
_
)
|
Cil2cfg
.
VblkIn
(
Cil2cfg
.
Bstmt
s
,
_
)
|
Cil2cfg
.
VblkOut
(
Cil2cfg
.
Bstmt
s
,
_
)
|
Cil2cfg
.
VblkOut
(
Cil2cfg
.
Bstmt
s
,
_
)
|
Cil2cfg
.
Vtest
(
true
,
s
,
_
)
|
Cil2cfg
.
Vloop
(
_
,
s
)
|
Cil2cfg
.
Vswitch
(
s
,_
)
|
Cil2cfg
.
Vtest
(
true
,
s
,
_
)
|
Cil2cfg
.
Vloop
(
_
,
s
)
|
Cil2cfg
.
Vswitch
(
s
,_
)
->
Annotations
.
fold_code_annot
(
do_annot
s
)
s
acc
->
do_stmt
s
acc
|
Cil2cfg
.
Vtest
(
false
,
_
,
_
)
|
Cil2cfg
.
Vloop2
_
|
Cil2cfg
.
Vtest
(
false
,
_
,
_
)
|
Cil2cfg
.
Vloop2
_
|
Cil2cfg
.
VblkIn
_
|
Cil2cfg
.
VblkOut
_
|
Cil2cfg
.
Vend
->
acc
|
Cil2cfg
.
VblkIn
_
|
Cil2cfg
.
VblkOut
_
|
Cil2cfg
.
Vend
->
acc
in
in
...
@@ -1330,11 +1332,6 @@ let process_unreached_annots cfg =
...
@@ -1330,11 +1332,6 @@ let process_unreached_annots cfg =
(* Everything must go through here. *)
(* Everything must go through here. *)
(*----------------------------------------------------------------------------*)
(*----------------------------------------------------------------------------*)
let
get_cfg
kf
model
=
if
Wp_parameters
.
RTE
.
get
()
then
WpRTE
.
generate
model
kf
;
let
cfg
=
Cil2cfg
.
get
kf
in
let
_
=
process_unreached_annots
cfg
in
cfg
let
build_configs
assigns
kf
model
behaviors
ki
property
=
let
build_configs
assigns
kf
model
behaviors
ki
property
=
debug
"[get_strategies] for behaviors names: %a@."
debug
"[get_strategies] for behaviors names: %a@."
(
Wp_error
.
pp_string_list
~
sep
:
" "
~
empty
:
"<none>"
)
(
Wp_error
.
pp_string_list
~
sep
:
" "
~
empty
:
"<none>"
)
...
@@ -1348,16 +1345,18 @@ let build_configs assigns kf model behaviors ki property =
...
@@ -1348,16 +1345,18 @@ let build_configs assigns kf model behaviors ki property =
debug
debug
"[get_strategies] select stmt %d properties@."
s
.
sid
"[get_strategies] select stmt %d properties@."
s
.
sid
in
in
let
cfg
=
get_cfg
kf
model
in
if
Wp_parameters
.
RTE
.
get
()
then
WpRTE
.
generate
model
kf
;
let
reached
=
let
cfg
=
Cil2cfg
.
get
kf
in
let
reachability
=
if
Wp_parameters
.
SmokeTests
.
get
()
if
Wp_parameters
.
SmokeTests
.
get
()
&&
Wp_parameters
.
SmokeDeadcode
.
get
()
&&
Wp_parameters
.
SmokeDeadcode
.
get
()
then
Some
(
WpReached
.
reach
ed
kf
)
then
Some
(
WpReached
.
reach
ability
kf
)
else
None
in
else
None
in
process_unreached_annots
cfg
;
let
def_annot_bhv
,
bhvs
=
find_behaviors
kf
cfg
ki
behaviors
in
let
def_annot_bhv
,
bhvs
=
find_behaviors
kf
cfg
ki
behaviors
in
if
bhvs
<>
[]
then
debug
"[get_strategies] %d behaviors"
(
List
.
length
bhvs
);
if
bhvs
<>
[]
then
debug
"[get_strategies] %d behaviors"
(
List
.
length
bhvs
);
let
mk_bhv_config
bhv
=
{
let
mk_bhv_config
bhv
=
{
kf
;
reach
ed
;
cfg
;
kf
;
reach
ability
;
cfg
;
cur_bhv
=
bhv
;
cur_bhv
=
bhv
;
asked_prop
=
property
;
asked_prop
=
property
;
asked_bhvs
=
bhvs
;
asked_bhvs
=
bhvs
;
...
...
This diff is collapsed.
Click to expand it.
src/plugins/wp/wpReached.ml
+
32
−
16
View file @
e5e0f11a
...
@@ -41,13 +41,14 @@ type node = {
...
@@ -41,13 +41,14 @@ type node = {
mutable
flow
:
flow
;
mutable
flow
:
flow
;
mutable
prev
:
node
list
;
mutable
prev
:
node
list
;
mutable
reached
:
bool
option
;
mutable
reached
:
bool
option
;
mutable
alive
:
bool
option
;
}
}
let
kid
=
ref
0
let
kid
=
ref
0
let
node
()
=
let
node
()
=
incr
kid
;
incr
kid
;
{
id
=
!
kid
;
prev
=
[]
;
reached
=
None
;
flow
=
F_goto
}
{
id
=
!
kid
;
prev
=
[]
;
alive
=
None
;
reached
=
None
;
flow
=
F_goto
}
(* -------------------------------------------------------------------------- *)
(* -------------------------------------------------------------------------- *)
(* --- Unrolled Loop --- *)
(* --- Unrolled Loop --- *)
...
@@ -83,7 +84,7 @@ let rec is_predicate cond p =
...
@@ -83,7 +84,7 @@ let rec is_predicate cond p =
let
is_dead_annot
ca
=
let
is_dead_annot
ca
=
match
ca
.
annot_content
with
match
ca
.
annot_content
with
|
APragma
(
Loop_pragma
(
Unroll_specs
[
spec
;
_
]))
->
|
APragma
(
Loop_pragma
(
Unroll_specs
[
spec
;
_
]))
->
false
&&
is_unrolled_completely
spec
is_unrolled_completely
spec
|
AAssert
([]
,
p
)
|
AAssert
([]
,
p
)
|
AInvariant
([]
,_,
p
)
->
|
AInvariant
([]
,_,
p
)
->
not
p
.
tp_only_check
&&
is_predicate
false
p
.
tp_statement
not
p
.
tp_only_check
&&
is_predicate
false
p
.
tp_statement
...
@@ -102,8 +103,8 @@ let is_dead_code stmt =
...
@@ -102,8 +103,8 @@ let is_dead_code stmt =
(* --- Compute CFG --- *)
(* --- Compute CFG --- *)
(* -------------------------------------------------------------------------- *)
(* -------------------------------------------------------------------------- *)
type
reach
ed
=
node
Stmt
.
Map
.
t
type
reach
ability
=
node
Stmt
.
Map
.
t
type
cfg
=
reach
ed
ref
type
cfg
=
reach
ability
ref
(* working cfg during compilation *)
let
of_stmt
cfg
s
=
let
of_stmt
cfg
s
=
try
Stmt
.
Map
.
find
s
!
cfg
with
Not_found
->
try
Stmt
.
Map
.
find
s
!
cfg
with
Not_found
->
...
@@ -133,11 +134,8 @@ type env = {
...
@@ -133,11 +134,8 @@ type env = {
let
rec
stmt
env
s
b
=
let
rec
stmt
env
s
b
=
let
a
=
of_stmt
env
.
cfg
s
in
let
a
=
of_stmt
env
.
cfg
s
in
if
is_dead_code
s
then
let
f
=
skind
env
a
b
s
.
skind
in
a
.
flow
<-
F_dead
a
.
flow
<-
if
is_dead_code
s
then
F_dead
else
f
;
a
else
a
.
flow
<-
skind
env
a
b
s
.
skind
;
a
and
skind
env
a
b
=
function
and
skind
env
a
b
=
function
|
Instr
i
->
flow
i
(
goto
a
b
)
|
Instr
i
->
flow
i
(
goto
a
b
)
...
@@ -182,7 +180,12 @@ let rec reached node =
...
@@ -182,7 +180,12 @@ let rec reached node =
|
Some
r
->
r
|
Some
r
->
r
|
None
->
|
None
->
node
.
reached
<-
Some
true
;
(* cut loops *)
node
.
reached
<-
Some
true
;
(* cut loops *)
let
r
=
List
.
for_all
reached_after
node
.
prev
in
let
r
=
match
node
.
flow
with
|
F_dead
|
F_entry
->
true
|
F_goto
|
F_effect
|
F_return
|
F_branch
|
F_call
->
List
.
for_all
reached_after
node
.
prev
in
node
.
reached
<-
Some
r
;
r
node
.
reached
<-
Some
r
;
r
and
reached_after
node
=
and
reached_after
node
=
...
@@ -191,14 +194,26 @@ and reached_after node =
...
@@ -191,14 +194,26 @@ and reached_after node =
|
F_effect
|
F_entry
|
F_dead
->
true
|
F_effect
|
F_entry
|
F_dead
->
true
|
F_return
|
F_branch
|
F_call
->
false
|
F_return
|
F_branch
|
F_call
->
false
let
rec
alive
node
=
match
node
.
alive
with
|
Some
a
->
a
|
None
->
match
node
.
flow
with
|
F_dead
->
false
|
F_entry
->
true
|
_
->
node
.
alive
<-
Some
false
;
let
a
=
List
.
exists
alive
node
.
prev
in
node
.
alive
<-
Some
a
;
a
let
smoking_node
n
=
let
smoking_node
n
=
match
n
.
flow
with
match
n
.
flow
with
|
F_effect
|
F_call
|
F_return
->
not
(
reached
n
)
|
F_effect
|
F_call
|
F_return
->
alive
n
&&
not
(
reached
n
)
|
F_goto
|
F_branch
|
F_entry
|
F_dead
->
false
|
F_goto
|
F_branch
|
F_entry
|
F_dead
->
false
(* returns true if the stmt requires a reachability smoke test *)
(* returns true if the stmt requires a reachability smoke test *)
let
smoking
nodes
stmt
=
let
smoking
reachability
stmt
=
try
Stmt
.
Map
.
find
stmt
nodes
|>
smoking_node
try
Stmt
.
Map
.
find
stmt
reachability
|>
smoking_node
with
Not_found
->
false
with
Not_found
->
false
let
compute
kf
=
let
compute
kf
=
...
@@ -262,7 +277,8 @@ let dump ~dir kf reached =
...
@@ -262,7 +277,8 @@ let dump ~dir kf reached =
|
UnspecifiedSequence
_
->
Printf
.
sprintf
"Seq. s%d"
s
.
sid
|
UnspecifiedSequence
_
->
Printf
.
sprintf
"Seq. s%d"
s
.
sid
|
Throw
_
|
TryExcept
_
|
TryCatch
_
|
TryFinally
_
->
|
Throw
_
|
TryExcept
_
|
TryCatch
_
|
TryFinally
_
->
Printf
.
sprintf
"Exn. s%d"
s
.
sid
Printf
.
sprintf
"Exn. s%d"
s
.
sid
in
G
.
node
dot
(
N
.
get
n
)
[
`Box
;
`Label
label
])
in
G
.
node
dot
(
N
.
get
n
)
[
`Box
;
`Label
(
Printf
.
sprintf
"s%d n%d: %s"
s
.
sid
n
.
id
label
)])
reached
;
reached
;
G
.
run
dot
;
G
.
run
dot
;
G
.
close
dot
;
G
.
close
dot
;
...
@@ -276,7 +292,7 @@ let dump ~dir kf reached =
...
@@ -276,7 +292,7 @@ let dump ~dir kf reached =
module
FRmap
=
Kernel_function
.
Make_Table
module
FRmap
=
Kernel_function
.
Make_Table
(
Datatype
.
Make
(
Datatype
.
Make
(
struct
(
struct
type
t
=
reach
ed
type
t
=
reach
ability
include
Datatype
.
Serializable_undefined
include
Datatype
.
Serializable_undefined
let
reprs
=
[
Stmt
.
Map
.
empty
]
let
reprs
=
[
Stmt
.
Map
.
empty
]
let
name
=
"WpReachable.reached"
let
name
=
"WpReachable.reached"
...
@@ -289,7 +305,7 @@ module FRmap = Kernel_function.Make_Table
...
@@ -289,7 +305,7 @@ module FRmap = Kernel_function.Make_Table
let
dkey
=
Wp_parameters
.
register_category
"reached"
let
dkey
=
Wp_parameters
.
register_category
"reached"
let
reach
ed
=
FRmap
.
memo
let
reach
ability
=
FRmap
.
memo
begin
fun
kf
->
begin
fun
kf
->
let
r
=
compute
kf
in
let
r
=
compute
kf
in
(
if
Wp_parameters
.
has_dkey
dkey
then
(
if
Wp_parameters
.
has_dkey
dkey
then
...
...
This diff is collapsed.
Click to expand it.
src/plugins/wp/wpReached.mli
+
4
−
4
View file @
e5e0f11a
...
@@ -26,7 +26,7 @@
...
@@ -26,7 +26,7 @@
open
Cil_types
open
Cil_types
type
reach
ed
type
reach
ability
(** control flow graph dedicated to smoke tests *)
(** control flow graph dedicated to smoke tests *)
val
is_predicate
:
bool
->
predicate
->
bool
val
is_predicate
:
bool
->
predicate
->
bool
...
@@ -39,14 +39,14 @@ val is_dead_annot : code_annotation -> bool
...
@@ -39,14 +39,14 @@ val is_dead_annot : code_annotation -> bool
val
is_dead_code
:
stmt
->
bool
val
is_dead_code
:
stmt
->
bool
(** Checks whether the stmt has a dead-code annotation. *)
(** Checks whether the stmt has a dead-code annotation. *)
val
reach
ed
:
Kernel_function
.
t
->
reach
ed
val
reach
ability
:
Kernel_function
.
t
->
reach
ability
(** memoized reached cfg for function *)
(** memoized reached cfg for function *)
val
smoking
:
reach
ed
->
Cil_types
.
stmt
->
bool
val
smoking
:
reach
ability
->
Cil_types
.
stmt
->
bool
(** Returns whether a stmt need a smoke tests to avoid being unreachable.
(** Returns whether a stmt need a smoke tests to avoid being unreachable.
This is restricted to assignments, returns and calls not dominated
This is restricted to assignments, returns and calls not dominated
another smoking statement. *)
another smoking statement. *)
val
dump
:
dir
:
Datatype
.
Filepath
.
t
->
Kernel_function
.
t
->
reach
ed
->
unit
val
dump
:
dir
:
Datatype
.
Filepath
.
t
->
Kernel_function
.
t
->
reach
ability
->
unit
(* -------------------------------------------------------------------------- *)
(* -------------------------------------------------------------------------- *)
This diff is collapsed.
Click to expand it.
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