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
0bc431da
Commit
0bc431da
authored
5 years ago
by
Allan Blanchard
Committed by
Virgile Prevosto
5 years ago
Browse files
Options
Downloads
Patches
Plain Diff
[ghost] Ghost CFG, no more references
parent
2b0e4954
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/kernel_internals/typing/ghost_cfg.ml
+70
-69
70 additions, 69 deletions
src/kernel_internals/typing/ghost_cfg.ml
with
70 additions
and
69 deletions
src/kernel_internals/typing/ghost_cfg.ml
+
70
−
69
View file @
0bc431da
...
...
@@ -54,89 +54,88 @@ let noGhostBlock b =
end
in
(
visitCilBlock
(
noGhostVisitor
:>
cilVisitor
)
b
)
,
(
noGhostVisitor
#
getBehavior
()
)
let
isSkip
stmt
=
match
stmt
.
skind
with
(* We ignore blocks: their successors are their 1st stmt so we visit them *)
|
Instr
(
Skip
(
_
))
|
Block
(
_
)
|
Continue
(
_
)
|
Break
(
_
)
->
true
|
_
->
false
type
follower
=
(* For a stmt, an "Infinite" follower means that following skip instructions
we just go back to this stmt. *)
|
Infinite
|
Exit
|
Stmt
of
stmt
let
rec
skipSkip
?
(
visited
=
StmtSet
.
empty
)
s
=
if
StmtSet
.
mem
s
visited
then
Infinite
else
match
isSkip
s
with
|
false
->
Stmt
s
|
true
when
s
.
succs
=
[]
->
Exit
|
_
->
skipSkip
~
visited
:
(
StmtSet
.
add
s
visited
)
(
Extlib
.
as_singleton
s
.
succs
)
let
firstNonSkipNonGhosts
stmt
=
let
rec
do_find
~
visited
stmt
=
if
List
.
mem
stmt
!
visited
then
[]
let
sync
stmt
=
match
stmt
.
skind
with
(* We ignore blocks: their successors are their 1st stmt so we visit them *)
|
Instr
(
Skip
(
_
))
|
Block
(
_
)
|
Continue
(
_
)
|
Break
(
_
)
->
false
|
_
->
true
let
nextSync
stmt
=
let
rec
aux
visited
s
=
if
StmtSet
.
mem
s
visited
then
Infinite
else
match
sync
s
with
|
true
->
Stmt
s
|
false
when
s
.
succs
=
[]
->
Exit
|
_
->
aux
(
StmtSet
.
add
s
visited
)
(
Extlib
.
as_singleton
s
.
succs
)
in
aux
StmtSet
.
empty
stmt
let
nextNonGhostSync
stmt
=
let
rec
do_find
(
res
,
visited
)
stmt
=
if
StmtSet
.
mem
stmt
visited
then
res
,
visited
else
begin
visited
:=
stmt
::
!
visited
;
if
isSkip
stmt
then
do_find
~
visited
(
Extlib
.
as_singleton
stmt
.
succs
)
else
if
not
(
stmt
.
ghost
)
then
[
stmt
]
else
List
.
flatten
(
List
.
map
(
do_find
~
visited
)
stmt
.
succs
)
let
visited
=
StmtSet
.
add
stmt
visited
in
if
not
(
sync
stmt
)
then
do_find
(
res
,
visited
)
(
Extlib
.
as_singleton
stmt
.
succs
)
else
if
not
(
stmt
.
ghost
)
then
StmtSet
.
add
stmt
res
,
visited
else
List
.
fold_left
do_find
(
res
,
visited
)
stmt
.
succs
end
in
do_find
~
visited
:
(
ref
[]
)
stmt
fst
(
do_find
(
StmtSet
.
empty
,
StmtSet
.
empty
)
stmt
)
let
alteredCFG
stmt
=
error
~
source
:
(
fst
(
Stmt
.
loc
stmt
))
"Ghost code breaks CFG starting at:@.%a"
Cil_printer
.
pp_stmt
stmt
let
rec
checkGhostCFG
bhv
?
(
visited
=
ref
StmtSet
.
empty
)
withGhostStart
noGhost
=
match
(
skipSkip
withGhostStart
)
,
(
skipSkip
noGhost
)
with
|
Stmt
withGhost
,
Stmt
noGhost
->
begin
if
StmtSet
.
mem
withGhost
!
visited
then
()
else
begin
visited
:=
StmtSet
.
add
withGhost
!
visited
;
let
withGhost
=
List
.
sort_uniq
Stmt
.
compare
(
firstNonSkipNonGhosts
withGhost
)
in
match
withGhost
,
noGhost
with
|
[
s1
]
,
s2
when
not
(
Stmt
.
equal
s1
(
Get_orig
.
stmt
bhv
s2
))
->
alteredCFG
withGhostStart
|
[
{
skind
=
If
(
_
)
}
as
s1
]
,
s2
->
checkIf
bhv
~
visited
s1
s2
|
[
{
skind
=
Switch
(
_
)
}
as
s1
]
,
s2
->
checkSwitch
bhv
~
visited
s1
s2
|
[
{
skind
=
Loop
(
_
)
}
as
s1
]
,
s2
->
checkLoop
bhv
~
visited
s1
s2
|
[
{
succs
=
[
next_s1
]
}
]
,
{
succs
=
[
next_s2
]
}
->
checkGhostCFG
bhv
~
visited
next_s1
next_s2
|
[
{
succs
=
[]
}
]
,
{
succs
=
[]
}
->
()
|
_
,
_
->
alteredCFG
withGhostStart
let
checkGhostCFG
bhv
withGhostStart
noGhost
=
let
rec
do_check
visited
withGhostStart
noGhostStart
=
match
(
nextSync
withGhostStart
)
,
(
nextSync
noGhostStart
)
with
|
Stmt
withGhost
,
Stmt
_
when
StmtSet
.
mem
withGhost
visited
->
visited
|
Stmt
withGhost
,
Stmt
noGhost
->
let
visited
=
StmtSet
.
add
withGhost
visited
in
let
withGhost
=
StmtSet
.
contains_single_elt
(
nextNonGhostSync
withGhost
)
in
begin
match
withGhost
,
noGhost
with
|
Some
s1
,
s2
when
not
(
Stmt
.
equal
s1
(
Get_orig
.
stmt
bhv
s2
))
->
alteredCFG
withGhostStart
;
visited
|
Some
({
skind
=
If
(
_
)
}
as
withGhost
)
,
noGhost
->
let
wgThen
,
wgElse
=
Cil
.
separate_if_succs
withGhost
in
let
ngThen
,
ngElse
=
Cil
.
separate_if_succs
noGhost
in
let
visited
=
do_check
visited
wgThen
ngThen
in
do_check
visited
wgElse
ngElse
|
Some
({
skind
=
Switch
(
_
)
}
as
withGhost
)
,
noGhost
->
let
ngSuccs
,
ngDef
=
Cil
.
separate_switch_succs
noGhost
in
let
wgAllSuccs
,
wgDef
=
Cil
.
separate_switch_succs
withGhost
in
let
wgSuccsG
,
wgSuccsNG
=
List
.
partition
(
fun
s
->
s
.
ghost
)
wgAllSuccs
in
let
mustDefault
=
wgDef
::
wgSuccsG
in
assert
(
List
.
length
ngSuccs
=
List
.
length
wgSuccsNG
)
;
let
visited
=
List
.
fold_left2
do_check
visited
wgSuccsNG
ngSuccs
in
List
.
fold_left
(
fun
v
s
->
do_check
v
s
ngDef
)
visited
mustDefault
|
Some
({
skind
=
Loop
(
_
,
wgb
,_,_,_
)
})
,
{
skind
=
Loop
(
_
,
ngb
,_,_,_
)
}
->
begin
match
wgb
.
bstmts
,
ngb
.
bstmts
with
|
s1
::
_
,
s2
::
_
->
do_check
visited
s1
s2
|
_
,
_
->
visited
end
|
Some
{
succs
=
[
wg
]
}
,
{
succs
=
[
ng
]
}
->
do_check
visited
wg
ng
|
Some
{
succs
=
[]
}
,
{
succs
=
[]
}
->
visited
|
_
,
_
->
alteredCFG
withGhostStart
;
visited
end
end
;
|
Exit
,
Exit
|
Infinite
,
Infinite
->
()
|
_
,
_
->
alteredCFG
withGhostStart
and
checkIf
bhv
~
visited
withGhost
noGhost
=
let
withGhostThen
,
withGhostElse
=
Cil
.
separate_if_succs
withGhost
in
let
noGhostThen
,
noGhostElse
=
Cil
.
separate_if_succs
noGhost
in
checkGhostCFG
bhv
~
visited
withGhostThen
noGhostThen
;
checkGhostCFG
bhv
~
visited
withGhostElse
noGhostElse
and
checkLoop
bhv
~
visited
withGhost
noGhost
=
let
withGhostBlock
,
noGhostBlock
=
match
withGhost
.
skind
,
noGhost
.
skind
with
|
Loop
(
_
,
b1
,
_
,
_
,
_
)
,
Loop
(
_
,
b2
,
_
,
_
,
_
)
->
b1
,
b2
|
_
->
assert
false
in
match
withGhostBlock
.
bstmts
,
noGhostBlock
.
bstmts
with
|
s1
::
_
,
s2
::
_
->
checkGhostCFG
bhv
~
visited
s1
s2
|
_
,
_
->
()
and
checkSwitch
bhv
~
visited
withGhost
noGhost
=
let
noGhostSuccs
,
noGhostDef
=
Cil
.
separate_switch_succs
noGhost
in
let
withGhostAllSuccs
,
withGhostDef
=
Cil
.
separate_switch_succs
withGhost
in
let
withGhostSuccsGhost
,
withGhostSuccsNonGhost
=
List
.
partition
(
fun
s
->
s
.
ghost
)
withGhostAllSuccs
|
Exit
,
Exit
|
Infinite
,
Infinite
->
visited
|
_
,
_
->
alteredCFG
withGhostStart
;
visited
in
let
mustDefault
=
withGhostDef
::
withGhostSuccsGhost
in
assert
(
List
.
length
noGhostSuccs
=
List
.
length
withGhostSuccsNonGhost
)
;
List
.
iter2
(
checkGhostCFG
bhv
~
visited
)
withGhostSuccsNonGhost
noGhostSuccs
;
List
.
iter
(
fun
s
->
checkGhostCFG
bhv
~
visited
s
noGhostDef
)
mustDefault
ignore
(
do_check
StmtSet
.
empty
withGhostStart
noGhost
)
let
checkGhostCFGInFun
(
fd
:
fundec
)
=
if
fd
.
svar
.
vghost
then
()
...
...
@@ -155,7 +154,9 @@ let checkGhostCFGInFun (fd : fundec) =
end
let
checkGhostCFGInFile
(
f
:
file
)
=
Cil
.
iterGlobals
f
(
function
GFun
(
fd
,_
)
->
checkGhostCFGInFun
fd
|
_
->
()
)
Cil
.
iterGlobals
f
(
function
|
GFun
(
fd
,
_
)
->
checkGhostCFGInFun
fd
|
_
->
()
)
let
transform_category
=
File
.
register_code_transformation_category
"Ghost CFG checking"
...
...
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