Module GlobalBounds
Computation of global bounds.
Require
Import
Errors
.
Require
Import
RTL
.
Require
Import
Registers
.
Require
Import
RTLPaths
.
Require
Import
Scope
.
Require
Import
DLib
.
Require
Import
LocalBounds
.
Require
Import
String
.
Require
Import
Maps
.
Require
Import
RTLWfFunction
.
Require
Import
SliceCFG
.
Open
Scope
Z_scope
.
Definition
opt_error
{
A
} (
x
:
option
A
) (
msg
:
String.string
) :
res
A
:=
match
x
with
|
Some
x
=>
OK
x
|
None
=>
Error
(
MSG
msg
::
nil
)
end
.
Fixpoint
bound_rec
(
f
:
function
) (
fsc
:
Scope.family
f
) (
exit_n
:
node
) (
reg_vint
:
reg
)
(
fuel
:
nat
) (
sc
:
Scope.t
)
(
acc
:
PTree.t
Z
) :
res
(
PTree.t
Z
) :=
match
fuel
with
|
O
=>
Error
(
MSG
("
bound_rec
:
not
enough
fuel
") ::
nil
)
|
S
fuel
' =>
let
h
:=
Scope.header
fsc
sc
in
if
ptree_mem
h
acc
then
Error
(
MSG
("
bound_rec
assert
false
") ::
nil
)
else
if
peq
h
f
.(
fn_entrypoint
)
then
let
acc
' :=
PTree.set
h
1
acc
in
let
sons
:=
Scope.sons
sc
in
fold_left
(
fun
eacc
sc
' =>
do
acc
<-
eacc
;
bound_rec
f
fsc
exit_n
reg_vint
fuel
'
sc
'
acc
)
sons
(
OK
acc
')
else
let
p_h
:=
Scope.header
fsc
(
Scope.parent
fsc
sc
)
in
do
slice
<-
slicer
f
fsc
exit_n
reg_vint
h
;
let
(
tf
,
tfsc
') :=
slice
in
let
(
tfsc
,
_
) :=
tfsc
'
in
match
local_bound
tf
tfsc
h
with
|
OK
local_bound_h
=>
do
bound_p
<-
opt_error
(
PTree.get
p_h
acc
) "
bound_rec
:
parent
not
computed
yet
";
let
bound_h
:= (
local_bound_h
*
bound_p
)%
Z
in
let
acc
' :=
PTree.set
h
bound_h
acc
in
let
sons
:=
Scope.sons
sc
in
fold_left
(
fun
eacc
sc
' =>
do
acc
<-
eacc
;
bound_rec
f
fsc
exit_n
reg_vint
fuel
'
sc
'
acc
)
sons
(
OK
acc
')
|
Error
_
=>
OK
acc
end
end
.
Definition
bound
(
f
:
function
) :
res
(
node
->
option
Z
) :=
match
Scope.build_family
f
with
|
Some
fsc
=>
let
main_sc
:=
Scope.scope
fsc
f
.(
fn_entrypoint
)
in
let
all_sc
:=
Scope.elements
fsc
in
do
(
exit_n
,
reg_vint
) <-
check_wf
f
;
do
bound_headers
<-
bound_rec
f
fsc
exit_n
reg_vint
(
List.length
all_sc
)
main_sc
(
PTree.empty
_
);
OK
(
fun
n
=>
let
h
:=
Scope.header
fsc
(
Scope.scope
fsc
n
)
in
PTree.get
h
bound_headers
)
|
None
=>
Error
(
MSG
("
bound
:
build_scope
failed
") ::
nil
)
end
.
Fixpoint
headers_rec
(
f
:
function
) (
fsc
:
Scope.family
f
) (
fuel
:
nat
) (
sc
:
Scope.t
)
(
acc
:
list
node
) :
res
(
list
node
) :=
match
fuel
with
|
O
=>
Error
(
MSG
("
headers_rec
:
not
enough
fuel
") ::
nil
)
|
S
fuel
' =>
let
h
:=
Scope.header
fsc
sc
in
if
TheoryList.mem
positive_eq_dec
h
acc
then
Error
(
MSG
("
headers_rec
assert
false
") ::
nil
)
else
let
sons
:=
Scope.sons
sc
in
fold_left
(
fun
eacc
sc
' =>
do
acc
<-
eacc
;
headers_rec
f
fsc
fuel
'
sc
'
acc
)
sons
(
OK
(
h
::
acc
))
end
.
Definition
headers
(
f
:
function
) :
res
(
list
node
) :=
match
Scope.build_family
f
with
|
Some
fsc
=>
let
main_sc
:=
Scope.scope
fsc
f
.(
fn_entrypoint
)
in
let
all_sc
:=
Scope.elements
fsc
in
headers_rec
f
fsc
(
List.length
all_sc
)
main_sc
nil
|
None
=>
Error
(
MSG
("
headers
:
build_scope
failed
") ::
nil
)
end
.