Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Fengmin Zhu
RefinedC
Commits
dc744bb2
Commit
dc744bb2
authored
Nov 12, 2020
by
Rodolphe Lepigre
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Check allocation range with new ghost state (MR !3, Fixes #20).
parent
6e747174
Changes
19
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
965 additions
and
406 deletions
+965
-406
examples/proofs/malloc1/generated_code.v
examples/proofs/malloc1/generated_code.v
+14
-14
theories/lang/base.v
theories/lang/base.v
+25
-0
theories/lang/heap.v
theories/lang/heap.v
+275
-69
theories/lang/lang.v
theories/lang/lang.v
+65
-45
theories/lang/lifting.v
theories/lang/lifting.v
+120
-55
theories/typing/adequacy.v
theories/typing/adequacy.v
+72
-35
theories/typing/array.v
theories/typing/array.v
+73
-37
theories/typing/constrained.v
theories/typing/constrained.v
+12
-4
theories/typing/exist.v
theories/typing/exist.v
+15
-3
theories/typing/int.v
theories/typing/int.v
+19
-11
theories/typing/optional.v
theories/typing/optional.v
+74
-47
theories/typing/own.v
theories/typing/own.v
+55
-29
theories/typing/padded.v
theories/typing/padded.v
+30
-15
theories/typing/programs.v
theories/typing/programs.v
+13
-0
theories/typing/struct.v
theories/typing/struct.v
+34
-18
theories/typing/type.v
theories/typing/type.v
+43
-14
theories/typing/uninit.v
theories/typing/uninit.v
+14
-0
theories/typing/union.v
theories/typing/union.v
+2
-2
tutorial/adequacy/adequacy.v
tutorial/adequacy/adequacy.v
+10
-8
No files found.
examples/proofs/malloc1/generated_code.v
View file @
dc744bb2
...
...
@@ -109,20 +109,20 @@ Section code.
Definition
loc_104
:
location_info
:
=
LocationInfo
file_0
59
8
59
9
.
Definition
loc_105
:
location_info
:
=
LocationInfo
file_0
59
19
59
33
.
Definition
loc_108
:
location_info
:
=
LocationInfo
file_0
81
4
81
27
.
Definition
loc_109
:
location_info
:
=
LocationInfo
file_0
8
5
4
8
5
22
.
Definition
loc_110
:
location_info
:
=
LocationInfo
file_0
8
6
4
8
6
16
.
Definition
loc_111
:
location_info
:
=
LocationInfo
file_0
8
6
4
8
6
11
.
Definition
loc_112
:
location_info
:
=
LocationInfo
file_0
8
6
4
8
6
5
.
Definition
loc_113
:
location_info
:
=
LocationInfo
file_0
8
6
4
8
6
5
.
Definition
loc_114
:
location_info
:
=
LocationInfo
file_0
8
6
14
8
6
15
.
Definition
loc_115
:
location_info
:
=
LocationInfo
file_0
8
6
14
8
6
15
.
Definition
loc_116
:
location_info
:
=
LocationInfo
file_0
8
5
4
8
5
11
.
Definition
loc_117
:
location_info
:
=
LocationInfo
file_0
8
5
4
8
5
5
.
Definition
loc_118
:
location_info
:
=
LocationInfo
file_0
8
5
4
8
5
5
.
Definition
loc_119
:
location_info
:
=
LocationInfo
file_0
8
5
14
8
5
21
.
Definition
loc_120
:
location_info
:
=
LocationInfo
file_0
8
5
14
8
5
21
.
Definition
loc_121
:
location_info
:
=
LocationInfo
file_0
8
5
14
8
5
15
.
Definition
loc_122
:
location_info
:
=
LocationInfo
file_0
8
5
14
8
5
15
.
Definition
loc_109
:
location_info
:
=
LocationInfo
file_0
8
3
4
8
3
22
.
Definition
loc_110
:
location_info
:
=
LocationInfo
file_0
8
4
4
8
4
16
.
Definition
loc_111
:
location_info
:
=
LocationInfo
file_0
8
4
4
8
4
11
.
Definition
loc_112
:
location_info
:
=
LocationInfo
file_0
8
4
4
8
4
5
.
Definition
loc_113
:
location_info
:
=
LocationInfo
file_0
8
4
4
8
4
5
.
Definition
loc_114
:
location_info
:
=
LocationInfo
file_0
8
4
14
8
4
15
.
Definition
loc_115
:
location_info
:
=
LocationInfo
file_0
8
4
14
8
4
15
.
Definition
loc_116
:
location_info
:
=
LocationInfo
file_0
8
3
4
8
3
11
.
Definition
loc_117
:
location_info
:
=
LocationInfo
file_0
8
3
4
8
3
5
.
Definition
loc_118
:
location_info
:
=
LocationInfo
file_0
8
3
4
8
3
5
.
Definition
loc_119
:
location_info
:
=
LocationInfo
file_0
8
3
14
8
3
21
.
Definition
loc_120
:
location_info
:
=
LocationInfo
file_0
8
3
14
8
3
21
.
Definition
loc_121
:
location_info
:
=
LocationInfo
file_0
8
3
14
8
3
15
.
Definition
loc_122
:
location_info
:
=
LocationInfo
file_0
8
3
14
8
3
15
.
Definition
loc_123
:
location_info
:
=
LocationInfo
file_0
81
25
81
26
.
Definition
loc_124
:
location_info
:
=
LocationInfo
file_0
81
25
81
26
.
...
...
theories/lang/base.v
View file @
dc744bb2
...
...
@@ -66,6 +66,31 @@ Lemma entails_eq {PROP : bi} (P1 P2 : PROP) :
P1
=
P2
→
P1
-
∗
P2
.
Proof
.
move
=>
->.
reflexivity
.
Qed
.
Section
theorems
.
Context
`
{
FinMapDom
K
M
D
}.
Lemma
dom_list_to_map
{
A
}
(
l
:
list
(
K
*
A
))
:
dom
D
(
list_to_map
(
M
:
=
M
A
)
l
)
≡
list_to_set
l
.*
1
.
Proof
using
Type
*.
elim
:
l
=>
/=.
{
by
apply
dom_empty
.
}
move
=>
?
l
<-.
by
apply
dom_insert
.
Qed
.
Lemma
dom_list_to_map_L
{
A
}
(
l
:
list
(
K
*
A
))
`
{!
LeibnizEquiv
D
}
:
dom
D
(
list_to_map
(
M
:
=
M
A
)
l
)
=
list_to_set
l
.*
1
.
Proof
using
Type
*.
unfold_leibniz
.
apply
:
dom_list_to_map
.
Qed
.
End
theorems
.
Section
list_to_map
.
Context
`
{
FinMap
K
M
}.
Lemma
list_to_map_app
{
A
}
(
l1
l2
:
list
(
K
*
A
))
:
list_to_map
(
M
:
=
M
A
)
(
l1
++
l2
)
=
list_to_map
l1
∪
list_to_map
l2
.
Proof
using
Type
*.
elim
:
l1
=>
/=.
{
by
rewrite
left_id
.
}
move
=>
[??]
?
IH
/=.
by
rewrite
IH
insert_union_l
.
Qed
.
End
list_to_map
.
Inductive
TCOneIsSome
{
A
}
:
option
A
→
option
A
→
Prop
:
=
|
tc_one_is_some_left
n1
o2
:
TCOneIsSome
(
Some
n1
)
o2
...
...
theories/lang/heap.v
View file @
dc744bb2
This diff is collapsed.
Click to expand it.
theories/lang/lang.v
View file @
dc744bb2
...
...
@@ -225,7 +225,13 @@ Inductive lock_state := WSt | RSt (n : nat).
Definition
heap
:
=
gmap
loc
(
lock_state
*
mbyte
).
Definition
blocks
:
=
gset
block_id
.
Record
allocation
:
=
Allocation
{
alloc_start
:
Z
;
(* First valid address. *)
alloc_end
:
Z
;
(* One-past-the-end address. *)
}.
Definition
blocks
:
=
gmap
block_id
allocation
.
...
...
@@ -425,7 +431,7 @@ Proof.
+
rewrite
/
int_modulus
/
bits_per_int
.
lia
.
+
rewrite
/
int_half_modulus
in
HM
.
transitivity
(
2
^
(
bits_per_int
it
-
1
))
;
first
lia
.
rewrite
/
bits_per_int
/
bytes_per_int
/
bits_per_byte
/=.
rewrite
/
bits_per_int
/
bytes_per_int
/
bits_per_byte
/=.
apply
Z
.
pow_lt_mono_r
;
try
lia
.
+
rewrite
/
int_modulus
/
bits_per_int
in
HM
.
lia
.
Qed
.
...
...
@@ -565,6 +571,14 @@ Qed.
(*** Helper functions for accessing the heap *)
(* The address range between [l] and [l +ₗ n] (included) is in range of the
allocation that contains [l]. Note that we consider the 1-past-the-end
pointer to be in range of an allocation. *)
Definition
heap_loc_in_bounds
(
l
:
loc
)
(
n
:
nat
)
(
st
:
state
)
:
Prop
:
=
∃
alloc
,
st
.(
st_used_blocks
)
!!
l
.
1
=
Some
alloc
∧
alloc
.(
alloc_start
)
≤
l
.
2
∧
l
.
2
+
n
≤
alloc
.(
alloc_end
).
Fixpoint
heap_at_go
l
v
flk
h
:
Prop
:
=
match
v
with
|
[]
=>
True
...
...
@@ -658,51 +672,53 @@ Definition ptr_eq l1 l2 h : option bool :=
(* evaluation can be non-deterministic for comparing pointers *)
(* TODO: implement *)
Inductive
eval_bin_op
:
bin_op
→
op_type
→
op_type
→
heap
→
val
→
val
→
val
→
Prop
:
=
|
AddOpPI
v1
v2
h
o
l
:
Inductive
eval_bin_op
:
bin_op
→
op_type
→
op_type
→
state
→
val
→
val
→
val
→
Prop
:
=
|
AddOpPI
v1
v2
σ
o
l
:
val_to_loc
v1
=
Some
l
→
val_to_int
v2
size_t
=
Some
o
→
eval_bin_op
AddOp
PtrOp
(
IntOp
size_t
)
h
v1
v2
(
val_of_loc
(
l
+
ₗ
o
))
|
PtrOffsetOpIP
v1
v2
h
o
l
ly
it
:
eval_bin_op
AddOp
PtrOp
(
IntOp
size_t
)
σ
v1
v2
(
val_of_loc
(
l
+
ₗ
o
))
|
PtrOffsetOpIP
v1
v2
σ
o
l
ly
it
:
val_to_int
v1
it
=
Some
o
→
val_to_loc
v2
=
Some
l
→
(* TODO: should we have an alignment check here? *)
0
≤
o
→
eval_bin_op
(
PtrOffsetOp
ly
)
(
IntOp
it
)
PtrOp
h
v1
v2
(
val_of_loc
(
l
offset
{
ly
}
ₗ
o
))
|
EqOpPNull
v1
v2
h
l
v
:
eval_bin_op
(
PtrOffsetOp
ly
)
(
IntOp
it
)
PtrOp
σ
v1
v2
(
val_of_loc
(
l
offset
{
ly
}
ₗ
o
))
|
EqOpPNull
v1
v2
σ
l
v
:
heap_loc_in_bounds
l
0
%
nat
σ
→
val_to_loc
v1
=
Some
l
→
val_to_int
v2
size_t
=
Some
0
→
(* TODO ( see below ): Should we really hard code i32 here because of C? *)
i2v
(
Z_of_bool
false
)
i32
=
v
→
eval_bin_op
EqOp
PtrOp
PtrOp
h
v1
v2
v
|
NeOpPNull
v1
v2
h
l
v
:
eval_bin_op
EqOp
PtrOp
PtrOp
σ
v1
v2
v
|
NeOpPNull
v1
v2
σ
l
v
:
heap_loc_in_bounds
l
0
%
nat
σ
→
val_to_loc
v1
=
Some
l
→
val_to_int
v2
size_t
=
Some
0
→
i2v
(
Z_of_bool
true
)
i32
=
v
→
eval_bin_op
NeOp
PtrOp
PtrOp
h
v1
v2
v
|
EqOpNullNull
v1
v2
h
v
:
eval_bin_op
NeOp
PtrOp
PtrOp
σ
v1
v2
v
|
EqOpNullNull
v1
v2
σ
v
:
val_to_int
v1
size_t
=
Some
0
→
val_to_int
v2
size_t
=
Some
0
→
i2v
(
Z_of_bool
true
)
i32
=
v
→
eval_bin_op
EqOp
PtrOp
PtrOp
h
v1
v2
v
|
NeOpNullNull
v1
v2
h
v
:
eval_bin_op
EqOp
PtrOp
PtrOp
σ
v1
v2
v
|
NeOpNullNull
v1
v2
σ
v
:
val_to_int
v1
size_t
=
Some
0
→
val_to_int
v2
size_t
=
Some
0
→
i2v
(
Z_of_bool
false
)
i32
=
v
→
eval_bin_op
NeOp
PtrOp
PtrOp
h
v1
v2
v
|
EqOpPP
v1
v2
h
l1
l2
v
b
:
eval_bin_op
NeOp
PtrOp
PtrOp
σ
v1
v2
v
|
EqOpPP
v1
v2
σ
l1
l2
v
b
:
val_to_loc
v1
=
Some
l1
→
val_to_loc
v2
=
Some
l2
→
ptr_eq
l1
l2
h
=
Some
b
→
ptr_eq
l1
l2
σ
.(
st_heap
)
=
Some
b
→
i2v
(
Z_of_bool
b
)
i32
=
v
→
eval_bin_op
EqOp
PtrOp
PtrOp
h
v1
v2
v
|
NeOpPP
v1
v2
h
l1
l2
v
b
:
eval_bin_op
EqOp
PtrOp
PtrOp
σ
v1
v2
v
|
NeOpPP
v1
v2
σ
l1
l2
v
b
:
val_to_loc
v1
=
Some
l1
→
val_to_loc
v2
=
Some
l2
→
ptr_eq
l1
l2
h
=
Some
b
→
ptr_eq
l1
l2
σ
.(
st_heap
)
=
Some
b
→
i2v
(
Z_of_bool
(
negb
b
))
i32
=
v
→
eval_bin_op
NeOp
PtrOp
PtrOp
h
v1
v2
v
|
RelOpII
op
v1
v2
h
n1
n2
it
b
:
eval_bin_op
NeOp
PtrOp
PtrOp
σ
v1
v2
v
|
RelOpII
op
v1
v2
σ
n1
n2
it
b
:
match
op
with
|
EqOp
=>
Some
(
bool_decide
(
n1
=
n2
))
|
NeOp
=>
Some
(
bool_decide
(
n1
≠
n2
))
...
...
@@ -716,10 +732,10 @@ Inductive eval_bin_op : bin_op → op_type → op_type → heap → val → val
val_to_int
v2
it
=
Some
n2
→
(* TODO: What is the right int type of the result here? C seems to
use i32 but maybe we don't want to hard code that. *)
eval_bin_op
op
(
IntOp
it
)
(
IntOp
it
)
h
v1
v2
(
i2v
(
Z_of_bool
b
)
i32
)
eval_bin_op
op
(
IntOp
it
)
(
IntOp
it
)
σ
v1
v2
(
i2v
(
Z_of_bool
b
)
i32
)
(* This defines checked versions of the arithmetic operations which
are UB if the result is out of bounds for it. *)
|
ArithOpII
op
v1
v2
h
n1
n2
it
n
v
:
|
ArithOpII
op
v1
v2
σ
n1
n2
it
n
v
:
match
op
with
|
AddOp
=>
Some
(
n1
+
n2
)
|
SubOp
=>
Some
(
n1
-
n2
)
...
...
@@ -740,23 +756,23 @@ are UB if the result is out of bounds for it. *)
val_to_int
v1
it
=
Some
n1
→
val_to_int
v2
it
=
Some
n2
→
val_of_int
n
it
=
Some
v
→
eval_bin_op
op
(
IntOp
it
)
(
IntOp
it
)
h
v1
v2
v
eval_bin_op
op
(
IntOp
it
)
(
IntOp
it
)
σ
v1
v2
v
.
Inductive
eval_un_op
:
un_op
→
op_type
→
heap
→
val
→
val
→
Prop
:
=
|
CastOpII
itt
its
h
vs
vt
n
:
Inductive
eval_un_op
:
un_op
→
op_type
→
state
→
val
→
val
→
Prop
:
=
|
CastOpII
itt
its
σ
vs
vt
n
:
val_to_int
vs
its
=
Some
n
→
val_of_int
n
itt
=
Some
vt
→
eval_un_op
(
CastOp
(
IntOp
itt
))
(
IntOp
its
)
h
vs
vt
|
CastOpPP
h
vs
vt
l
:
eval_un_op
(
CastOp
(
IntOp
itt
))
(
IntOp
its
)
σ
vs
vt
|
CastOpPP
σ
vs
vt
l
:
val_to_loc
vs
=
Some
l
→
val_of_loc
l
=
vt
→
eval_un_op
(
CastOp
PtrOp
)
PtrOp
h
vs
vt
|
NegOpI
it
h
vs
vt
n
:
eval_un_op
(
CastOp
PtrOp
)
PtrOp
σ
vs
vt
|
NegOpI
it
σ
vs
vt
n
:
val_to_int
vs
it
=
Some
n
→
val_of_int
(-
n
)
it
=
Some
vt
→
eval_un_op
NegOp
(
IntOp
it
)
h
vs
vt
eval_un_op
NegOp
(
IntOp
it
)
σ
vs
vt
.
(*** Evaluation of Expressions *)
...
...
@@ -765,10 +781,10 @@ Inductive expr_step : expr → state → list Empty_set → expr → state → l
|
SkipES
v
σ
:
expr_step
(
SkipE
(
Val
v
))
σ
[]
(
Val
v
)
σ
[]
|
UnOpS
op
v
σ
v'
ot
:
eval_un_op
op
ot
σ
.(
st_heap
)
v
v'
→
eval_un_op
op
ot
σ
v
v'
→
expr_step
(
UnOp
op
ot
(
Val
v
))
σ
[]
(
Val
v'
)
σ
[]
|
BinOpS
op
v1
v2
σ
v'
ot1
ot2
:
eval_bin_op
op
ot1
ot2
σ
.(
st_heap
)
v1
v2
v'
→
eval_bin_op
op
ot1
ot2
σ
v1
v2
v'
→
expr_step
(
BinOp
op
ot1
ot2
(
Val
v1
)
(
Val
v2
))
σ
[]
(
Val
v'
)
σ
[]
|
DerefS
o
v
l
ly
v'
σ
:
let
start_st
st
:
=
∃
n
,
st
=
if
o
is
Na2Ord
then
RSt
(
S
n
)
else
RSt
n
in
...
...
@@ -960,6 +976,9 @@ Definition subst_function (xs : list var_name) (vs : list val) (f : function) :
f_args
:
=
f
.(
f_args
)
;
f_init
:
=
f
.(
f_init
)
;
f_local_vars
:
=
f
.(
f_local_vars
)
;
|}.
Definition
to_allocation
(
off
:
Z
)
(
len
:
nat
)
:
allocation
:
=
Allocation
off
(
off
+
len
).
(*** Evaluation of statements *)
Inductive
stmt_step
:
thread_state
→
state
→
list
Empty_set
→
thread_state
→
state
→
list
thread_state
→
Prop
:
=
|
StmtExprS
ts
σ
σ
'
Ks
e
e'
os
efs
:
...
...
@@ -1007,8 +1026,8 @@ Inductive stmt_step : thread_state → state → list Empty_set → thread_state
Forall
(
heap_block_free
σ
.(
st_heap
))
lsa
→
Forall
(
heap_block_free
σ
.(
st_heap
))
lsv
→
(* ensure that ls blocks are unused *)
Forall
(
λ
l
,
l
.
1
∉
σ
.(
st_used_blocks
))
lsa
→
Forall
(
λ
l
,
l
.
1
∉
σ
.(
st_used_blocks
))
lsv
→
Forall
(
λ
l
,
σ
.(
st_used_blocks
)
!!
l
.
1
=
None
)
lsa
→
Forall
(
λ
l
,
σ
.(
st_used_blocks
)
!!
l
.
1
=
None
)
lsv
→
(* ensure that locations are aligned *)
Forall2
has_layout_loc
lsa
fn
.(
f_args
).*
2
→
Forall2
has_layout_loc
lsv
fn
.(
f_local_vars
).*
2
→
...
...
@@ -1018,7 +1037,8 @@ Inductive stmt_step : thread_state → state → list Empty_set → thread_state
heap_upd_list
lsv
((
λ
p
,
replicate
p
.
2
.(
ly_size
)
MPoison
)
<$>
fn
.(
f_local_vars
))
(
λ
_
,
RSt
0
%
nat
)
σ
.(
st_heap
)
=
h'
→
(* initialize the arguments with the supplied values *)
heap_upd_list
lsa
vs
(
λ
_
,
RSt
0
%
nat
)
h'
=
h''
→
σ
.(
st_used_blocks
)
∪
list_to_set
(
lsa
++
lsv
).*
1
=
ub'
→
(* add used blocks allocations *)
list_to_map
(
zip
(
lsa
.*
1
++
lsv
.*
1
)
(
zip_with
to_allocation
(
lsa
.*
2
++
lsv
.*
2
)
(
ly_size
<$>
(
fn
.(
f_args
).*
2
++
fn
.(
f_local_vars
).*
2
))))
∪
σ
.(
st_used_blocks
)
=
ub'
→
rf
=
{|
rf_fn
:
=
fn'
;
rf_locs
:
=
zip
lsa
fn
.(
f_args
).*
2
++
zip
lsv
fn
.(
f_local_vars
).*
2
;
rf_stmt
:
=
Goto
fn'
.(
f_init
)
;
|}
→
co
=
{|
c_rfn
:
=
(
update_stmt
ts
s
).(
ts_rfn
)
;
c_rvar
:
=
ret
|}
→
stmt_step
ts
σ
[]
{|
ts_conts
:
=
co
::
ts
.(
ts_conts
)
;
ts_rfn
:
=
rf
|}
...
...
@@ -1140,16 +1160,15 @@ Lemma heap_at_inj_val l ly h v v' flk1 flk2:
heap_at
l
ly
v
flk1
h
→
heap_at
l
ly
v'
flk2
h
→
v
=
v'
.
Proof
.
move
=>
[
_
[
Hv1
H1
]]
[
_
[
Hv2
H2
]].
apply
:
heap_at_go_inj_val
=>
//.
congruence
.
Qed
.
Lemma
heap_fresh_blocks
n
(
ub
:
gset
Z
)
lys
:
Lemma
heap_fresh_blocks
n
(
ub
:
blocks
)
lys
:
length
lys
=
n
→
∃
ls
,
length
ls
=
n
∧
Forall
(
λ
l
:
loc
,
l
.
1
∉
ub
)
ls
∧
NoDup
ls
.*
1
∧
Forall2
has_layout_loc
ls
lys
.
∃
ls
,
length
ls
=
n
∧
Forall
(
λ
l
:
loc
,
ub
!!
l
.
1
=
None
)
ls
∧
NoDup
ls
.*
1
∧
Forall2
has_layout_loc
ls
lys
.
Proof
.
eexists
((
λ
x
,
(
x
,
0
))
<$>
fresh_list
n
ub
).
rewrite
fmap_length
fresh_list_length
.
split_and
!
=>
//.
-
apply
Forall_forall
=>
l
.
move
=>
/
elem_of_list_fmap
[?[->?]]/=.
by
apply
:
fresh_list_is_fresh
.
-
rewrite
-
list_fmap_compose
.
eapply
(
NoDup_proper
_
(
fresh_list
n
ub
))
;
last
by
apply
NoDup_fresh_list
.
elim
:
(
fresh_list
n
ub
)
;
naive_solver
.
eexists
((
λ
x
,
(
x
,
0
))
<$>
fresh_list
n
(
dom
(
gset
block_id
)
ub
)).
split_and
!.
-
rewrite
fmap_length
fresh_list_length
//.
-
apply
Forall_forall
=>
l
.
move
=>
/
elem_of_list_fmap
[?[->
He
]]/=.
by
apply
fresh_list_is_fresh
,
not_elem_of_dom
in
He
.
-
rewrite
-
list_fmap_compose
NoDup_fmap
.
by
apply
NoDup_fresh_list
.
-
rewrite
Forall2_fmap_l
.
apply
Forall2_true
;
last
by
rewrite
fresh_list_length
.
move
=>
??
/=.
by
apply
Z
.
divide_0_r
.
Qed
.
...
...
@@ -1227,6 +1246,7 @@ Canonical Structure locO := leibnizO loc.
Canonical
Structure
layoutO
:
=
leibnizO
layout
.
Canonical
Structure
valO
:
=
leibnizO
val
.
Canonical
Structure
exprO
:
=
leibnizO
expr
.
Canonical
Structure
allocationO
:
=
leibnizO
allocation
.
(*** Tests *)
...
...
theories/lang/lifting.v
View file @
dc744bb2
...
...
@@ -50,48 +50,60 @@ Proof. rewrite /Use. solve_atomic. Qed.
Section
expr_lifting
.
Context
`
{!
refinedcG
Σ
}.
Lemma
wp_binop
v'
v1
v2
Φ
op
E
ot1
ot2
:
(
∀
h
,
eval_bin_op
op
ot1
ot2
h
v1
v2
v'
)
→
▷
(
∀
v
h
,
⌜
eval_bin_op
op
ot1
ot2
h
v1
v2
v
⌝
-
∗
Φ
v
)
-
∗
WP
BinOp
op
ot1
ot2
(
Val
v1
)
(
Val
v2
)
@
E
{{
Φ
}}.
Lemma
wp_binop
v1
v2
Φ
op
E
ot1
ot2
:
(
∀
σ
,
state_ctx
σ
-
∗
⌜
∃
v'
,
eval_bin_op
op
ot1
ot2
σ
v1
v2
v'
⌝
∗
▷
(
∀
v'
,
⌜
eval_bin_op
op
ot1
ot2
σ
v1
v2
v'
⌝
-
∗
state_ctx
σ
∗
Φ
v'
))
-
∗
WP
BinOp
op
ot1
ot2
(
Val
v1
)
(
Val
v2
)
@
E
{{
Φ
}}.
Proof
.
iIntros
(
Hop
)
"HΦ"
.
iIntros
"HΦ"
.
iApply
wp_lift_atomic_head_step
;
auto
.
iIntros
(
σ
1
???)
"[Hhctx Hfctx]"
.
iModIntro
.
iSplit
;
first
by
eauto
using
BinOpS
.
iIntros
(
σ
1
???)
"Hctx !>"
.
iDestruct
(
"HΦ"
with
"Hctx"
)
as
([
v'
Heval
])
"HΦ"
.
iSplit
;
first
by
eauto
using
BinOpS
.
iIntros
"!#"
(
e2
σ
2
efs
Hst
).
inv_expr_step
.
iFrame
.
iModIntro
.
iSplitL
=>
//
.
by
iApply
"HΦ"
.
iModIntro
.
rewrite
right_id
.
by
iApply
"HΦ"
.
Qed
.
Lemma
wp_binop_det
v'
v1
v2
Φ
op
E
ot1
ot2
:
(
∀
h
v
,
eval_bin_op
op
ot1
ot2
h
v1
v2
v
↔
v
=
v'
)
→
▷
Φ
v'
-
∗
WP
BinOp
op
ot1
ot2
(
Val
v1
)
(
Val
v2
)
@
E
{{
Φ
}}.
(
∀
σ
v
,
state_ctx
σ
-
∗
⌜
eval_bin_op
op
ot1
ot2
σ
v1
v2
v
↔
v
=
v'
⌝
)
∧
▷
Φ
v'
-
∗
WP
BinOp
op
ot1
ot2
(
Val
v1
)
(
Val
v2
)
@
E
{{
Φ
}}.
Proof
.
iIntros
(
Hop
)
"HΦ"
.
iApply
(
wp_binop
v'
).
by
move
=>
h
;
apply
Hop
.
iIntros
"!#"
(
v
h
).
rewrite
Hop
.
iIntros
(?).
subst
.
by
iApply
"HΦ"
.
iIntros
"H"
.
iApply
wp_binop
.
iIntros
(
σ
)
"Hctx"
.
iSplit
.
{
iExists
v'
.
iDestruct
"H"
as
"[Hσ _]"
.
by
iDestruct
(
"Hσ"
with
"Hctx"
)
as
%->.
}
iIntros
"!>"
(
v
Hbinop
).
iAssert
(
⌜
v
=
v'
⌝
)%
I
as
%->.
{
iDestruct
"H"
as
"[Hσ _]"
.
iDestruct
(
"Hσ"
with
"Hctx"
)
as
%
Hvv'
.
iPureIntro
.
naive_solver
.
}
by
iDestruct
"H"
as
"[_ $]"
.
Qed
.
Lemma
wp_unop
v'
v1
Φ
op
E
ot
:
(
∀
h
,
eval_un_op
op
ot
h
v1
v'
)
→
▷
(
∀
v
h
,
⌜
eval_un_op
op
ot
h
v1
v
⌝
-
∗
Φ
v
)
-
∗
Lemma
wp_unop
v1
Φ
op
E
ot
:
(
∀
σ
,
state_ctx
σ
-
∗
⌜
∃
v'
,
eval_un_op
op
ot
σ
v1
v'
⌝
∗
▷
(
∀
v'
,
⌜
eval_un_op
op
ot
σ
v1
v'
⌝
-
∗
state_ctx
σ
∗
Φ
v'
))
-
∗
WP
UnOp
op
ot
(
Val
v1
)
@
E
{{
Φ
}}.
Proof
.
iIntros
(
Hop
)
"HΦ"
.
iIntros
"HΦ"
.
iApply
wp_lift_atomic_head_step
;
auto
.
iIntros
(
σ
1
???)
"[Hhctx Hfctx]"
.
iModIntro
.
iSplit
;
first
by
eauto
using
UnOpS
.
iIntros
(
σ
1
???)
"Hctx !>"
.
iDestruct
(
"HΦ"
with
"Hctx"
)
as
([
v'
Heval
])
"HΦ"
.
iSplit
;
first
by
eauto
using
UnOpS
.
iIntros
"!#"
(
e2
σ
2
efs
Hst
).
inv_expr_step
.
iFrame
.
iModIntro
.
iSplitL
=>
//
.
by
iApply
"HΦ"
.
iModIntro
.
rewrite
right_id
.
by
iApply
"HΦ"
.
Qed
.
Lemma
wp_unop_det
v'
v1
Φ
op
E
ot
:
(
∀
h
v
,
eval_un_op
op
ot
h
v1
v
↔
v
=
v'
)
→
▷
Φ
v'
-
∗
WP
UnOp
op
ot
(
Val
v1
)
@
E
{{
Φ
}}.
(
∀
σ
v
,
state_ctx
σ
-
∗
⌜
eval_un_op
op
ot
σ
v1
v
↔
v
=
v'
⌝
)
∧
▷
Φ
v'
-
∗
WP
UnOp
op
ot
(
Val
v1
)
@
E
{{
Φ
}}.
Proof
.
iIntros
(
Hop
)
"HΦ"
.
iApply
(
wp_unop
v'
).
by
move
=>
h
;
apply
Hop
.
iIntros
"!#"
(
v
h
).
rewrite
Hop
.
iIntros
(?).
subst
.
by
iApply
"HΦ"
.
iIntros
"H"
.
iApply
wp_unop
.
iIntros
(
σ
)
"Hctx"
.
iSplit
.
{
iExists
v'
.
iDestruct
"H"
as
"[Hσ _]"
.
by
iDestruct
(
"Hσ"
with
"Hctx"
)
as
%->.
}
iIntros
"!>"
(
v
Hbinop
).
iAssert
(
⌜
v
=
v'
⌝
)%
I
as
%->.
{
iDestruct
"H"
as
"[Hσ _]"
.
iDestruct
(
"Hσ"
with
"Hctx"
)
as
%
Hvv'
.
iPureIntro
.
naive_solver
.
}
by
iDestruct
"H"
as
"[_ $]"
.
Qed
.
Lemma
wp_deref
v
Φ
vl
l
ly
q
E
o
:
...
...
@@ -117,13 +129,13 @@ Proof.
iSplit
;
first
by
eauto
7
using
DerefS
.
iIntros
"!#"
(
e2
σ
2
efs
Hst
).
inv_expr_step
.
iMod
"Hclose"
as
"$"
.
iModIntro
.
unfold
end_st
,
end_expr
.
have
<-
:
(
v
=
v'
)
by
apply
:
heap_at_inj_val
.
iFrame
=>
/=.
iSplit
;
first
by
eauto
7
using
block_used_agree_heap_upd
.
iFrame
=>
/=.
iSplit
;
first
by
eauto
7
using
block
s
_used_agree_heap_upd
.
iApply
wp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
([
h2
fn2
]
???)
"(%&Hhctx&Hfctx)"
.
iMod
(
"Hσclose"
with
"Hhctx"
)
as
(?)
"(Hσ & Hv)"
.
iModIntro
;
iSplit
;
first
by
eauto
7
using
DerefS
.
iIntros
"!#"
(
e2
σ
2
efs
Hst
)
"!#"
.
inv_expr_step
.
have
<-
:
(
v
=
v'0
)
by
apply
:
heap_at_inj_val
.
iFrame
.
iSplitR
=>
//=.
iSplit
;
first
by
eauto
7
using
block_used_agree_heap_upd
.
iFrame
.
iSplitR
=>
//=.
iSplit
;
first
by
eauto
7
using
block
s
_used_agree_heap_upd
.
by
iApply
"HΦ"
.
Qed
.
...
...
@@ -153,7 +165,7 @@ Proof.
have
?
:
(
length
ve0
=
length
vo0
)
by
congruence
.
iMod
(
heap_write
with
"Hhctx Hl2"
)
as
"[$ Hl2]"
=>
//.
iFrame
.
iModIntro
.
rewrite
right_id
/=.
iSplit
;
first
by
eauto
using
block_used_agree_heap_upd
.
iSplit
;
first
by
eauto
using
block
s
_used_agree_heap_upd
.
by
iApply
(
"HΦ"
with
"Hl1"
).
Qed
.
...
...
@@ -183,7 +195,7 @@ Proof.
have
?
:
(
length
vo0
=
length
vd
)
by
congruence
.
iMod
(
heap_write
with
"Hhctx Hl1"
)
as
"[$ Hmt]"
=>
//.
iFrame
.
iModIntro
.
rewrite
right_id
/=.
iSplit
;
first
by
eauto
using
block_used_agree_heap_upd
.
iSplit
;
first
by
eauto
using
block
s
_used_agree_heap_upd
.
by
iApply
(
"HΦ"
with
"Hmt"
).
Qed
.
...
...
@@ -193,8 +205,10 @@ Lemma wp_neg_int Φ v v' n E it:
▷
Φ
(
v'
)
-
∗
WP
UnOp
NegOp
(
IntOp
it
)
(
Val
v
)
@
E
{{
Φ
}}.
Proof
.
iIntros
(
Hv
Hv'
)
"HΦ"
.
iApply
wp_unop
;
first
eauto
using
NegOpI
.
iIntros
"!#"
(
v2
h
Hop
).
by
inversion
Hop
;
simplify_eq
.
iApply
wp_unop_det
.
iSplit
=>
//.
iIntros
(
σ
v2
)
"_ !%"
.
split
.
-
by
inversion
1
;
simplify_eq
.
-
move
=>
->.
by
econstructor
.
Qed
.
Lemma
wp_cast_int
Φ
v
v'
n
E
its
itt
:
...
...
@@ -203,8 +217,10 @@ Lemma wp_cast_int Φ v v' n E its itt:
▷
Φ
(
v'
)
-
∗
WP
UnOp
(
CastOp
(
IntOp
itt
))
(
IntOp
its
)
(
Val
v
)
@
E
{{
Φ
}}.
Proof
.
iIntros
(
Hv
Hv'
)
"HΦ"
.
iApply
wp_unop
;
first
eauto
using
CastOpII
.
iIntros
"!#"
(
v2
h
Hop
).
by
inversion
Hop
;
simplify_eq
.
iApply
wp_unop_det
.
iSplit
=>
//.
iIntros
(
σ
v2
)
"_ !%"
.
split
.
-
by
inversion
1
;
simplify_eq
.
-
move
=>
->.
by
econstructor
.
Qed
.
Lemma
wp_cast_loc
Φ
v
l
E
:
...
...
@@ -212,8 +228,10 @@ Lemma wp_cast_loc Φ v l E:
▷
Φ
(
val_of_loc
l
)
-
∗
WP
UnOp
(
CastOp
PtrOp
)
PtrOp
(
Val
v
)
@
E
{{
Φ
}}.
Proof
.
iIntros
(
Hv
)
"HΦ"
.
iApply
wp_unop
;
first
eauto
using
CastOpPP
.
iIntros
"!#"
(
v2
h
Hop
).
by
inversion
Hop
;
simplify_eq
.
iApply
wp_unop_det
.
iSplit
=>
//.
iIntros
(
σ
v2
)
"_ !%"
.
split
.
-
by
inversion
1
;
simplify_eq
.
-
move
=>
->.
by
econstructor
.
Qed
.
Lemma
wp_ptr_offset
Φ
vl
l
E
it
o
ly
vo
:
...
...
@@ -223,8 +241,10 @@ Lemma wp_ptr_offset Φ vl l E it o ly vo:
▷
Φ
(
val_of_loc
(
l
offset
{
ly
}
ₗ
o
))
-
∗
WP
Val
vl
at_offset
{
ly
,
PtrOp
,
IntOp
it
}
Val
vo
@
E
{{
Φ
}}.
Proof
.
iIntros
(
Hvl
Hvo
Ho
)
"HΦ"
.
iApply
wp_binop
;
first
eauto
using
PtrOffsetOpIP
.
iIntros
"!#"
(
v
h
Hbop
).
by
inversion
Hbop
;
simplify_eq
.
iApply
wp_binop_det
.
iSplit
;
last
done
.
iIntros
(
σ
v
)
"_ !%"
.
split
.
-
inversion
1
.
by
simplify_eq
.
-
move
=>
->.
by
apply
PtrOffsetOpIP
.
Qed
.
Lemma
wp_get_member
Φ
vl
l
sl
n
E
:
...
...
@@ -239,8 +259,10 @@ Proof.
by
apply
offset_of_bound
.
}
rewrite
Hs
/=.
move
:
Hs
=>
/
val_to_of_int
Hs
.
iApply
wp_binop
;
first
eauto
using
AddOpPI
.
iIntros
"!#"
(
v
h
Hbop
).
by
inversion
Hbop
;
simplify_eq
.
iApply
wp_binop_det
.
iSplit
;
last
done
.
iIntros
(
σ
v
)
"_ !%"
.
split
.
-
inversion
1
.
by
simplify_eq
.
-
move
=>
->.
by
apply
AddOpPI
.
Qed
.
Lemma
wp_get_member_union
Φ
vl
l
ul
n
E
:
...
...
@@ -426,12 +448,13 @@ Lemma wps_call Q Ψ r vf vl s f fn:
)
-
∗
WPs
(
r
<-
Val
vf
with
Val
<$>
vl
;
s
)
{{
Q
,
Ψ
}}.
Proof
.
rewrite
(
stmt_wp_unfold
(
Call
_
_
_
_
)).
move
=>
Hf
Hly
.
iIntros
"Hf HWP"
(
ts
Φ
->)
"HΨ"
.
move
:
(
Hly
)
=>
/
Forall2_length
.
rewrite
fmap_length
=>
?
.
iApply
wp_lift_step
=>
/=
.
1
:
by
apply
stmt_to_val_non_ret
.
iIntros
(
σ
1
κ
_
_
)
"(H&Hhctx&Hfctx)"
.
iDestruct
"H"
as
%
Hub
.
rewrite
(
stmt_wp_unfold
(
Call
_
_
_
_
))
=>
Hf
Hly
.
move
:
(
Hly
)
=>
/
Forall2_length
;
rewrite
fmap_length
=>
Hlen_vs
.
iIntros
"Hf HWP"
(
ts
Φ
->)
"HΨ"
.
iApply
wp_lift_step
=>
/=
;
first
by
apply
stmt_to_val_non_ret
.
iIntros
(
σ
1
κ
_
_
)
"(H&Hhctx&
Hbctx&
Hfctx)"
.
iDestruct
"H"
as
%
Hub
.
iDestruct
(
fntbl_entry_lookup
with
"Hfctx Hf"
)
as
%
Hfn
.
iMod
(
fupd_intro_mask'
_
∅
)
as
"HE"
;
first
set_solver
.
iModIntro
.
iSplit
.
{
have
[|
ls
[
Hlen
[
Hfree
[
HND
Hlys
]]]]
:
=
heap_fresh_blocks
(
length
fn
.(
f_args
)
+
length
fn
.(
f_local_vars
))
σ
1
.(
st_used_blocks
)
((
f_args
fn
).*
2
++
(
f_local_vars
fn
).*
2
).
by
rewrite
!
app_length
!
fmap_length
.
have
[
lsa
[
lsv
[?
[
Ha
Hv
]]]]
:
(
∃
lsa
lsv
,
ls
=
lsa
++
lsv
∧
length
lsa
=
length
fn
.(
f_args
)
∧
length
lsv
=
length
fn
.(
f_local_vars
)).
{
...
...
@@ -441,29 +464,71 @@ Proof.
subst
ls
.
move
:
Hfree
=>
/
Forall_app
[/
Forall_forall
?
/
Forall_forall
?].
move
:
Hlys
=>
/
Forall2_app_inv
[|??].
by
rewrite
fmap_length
.
iPureIntro
.
eexists
_
,
_
,
_
,
_;
simpl
.
eapply
(
CallS
lsa
lsv
)
=>
//
;
apply
/
Forall_forall
=>
??
;
try
apply
Hub
;
set_solver
.
}
eapply
(
CallS
lsa
lsv
)
=>
//
;
apply
/
Forall_forall
=>
??
;
try
apply
Hub
;
set_solver
.
}
iIntros
"!#"
(
e2
σ
2
efs
Hst
).
inv_stmt_step
.
match
goal
with
|
H
:
NoDup
_
|-
_
=>
rewrite
->
fmap_app
,
NoDup_app
in
H
;
revert
H
end
.
move
=>
[?
[?
?]].
iMod
(
heap_alloc_list
lsv
(((
λ
p
,
replicate
(
ly_size
p
.
2
)
☠
%
V
)
<$>
f_local_vars
fn
))
with
"Hhctx"
)
as
"[Hhctx Hv]"
=>
//.
repeat
match
goal
with
|
H
:
Forall
(
fun
l
=>
_
!!
_
=
None
)
_
|-
_
=>
move
/
Forall_forall
in
H
end
.
revert
select
(
length
lsa
=
_
)
=>
Hlena
.
revert
select
(
length
lsv
=
_
)
=>
Hlenv
.
(* Allocate new allocation blocks for the local variables. *)
iMod
(
allocs_alloc_list
lsv
(((
λ
p
,
replicate
(
ly_size
p
.
2
)
☠
%
V
)
<$>
f_local_vars
fn
))
with
"Hbctx"
)
as
"[Hbctx Hblsv]"
=>
//.
{
apply
elem_of_disjoint
=>
id
Hdom
Hin
.
move
:
Hdom
.
apply
/
not_elem_of_dom
.
set_solver
.
}
{
by
rewrite
fmap_length
.
}