Require Import Coqlib Integers Values AST Memory.
Require Import Footprint MemOpFP val_casted.
Local Notation footprint :=
FP.t.
Local Notation empfp :=
FP.emp.
Inductive load_frame:
Type :=
|
mk_load_frame:
forall (
sp:
block)
(* pointer to argument frame *)
(
args:
list val)
(* initial program arguments *)
(
tys:
list typ)
(* initial argument types *)
(
sigres:
option typ),
(* optional return type *)
load_frame.
Require Mach.
Definition store_stack :=
Mach.store_stack.
Definition load_stack :=
Mach.load_stack.
Definition load_stack_fp (
sp:
val) (
ty:
typ) (
ofs:
ptrofs) :
footprint :=
loadv_fp (
chunk_of_type ty) (
Val.offset_ptr sp ofs).
Definition store_stack_fp (
sp:
val) (
ty:
typ) (
ofs:
ptrofs) :
footprint :=
storev_fp (
chunk_of_type ty) (
Val.offset_ptr sp ofs).
Note: Tlong has to be 8 aligned...
ofs : byte offset
Fixpoint store_args_rec (
m:
mem) (
sp:
val) (
ofs:
Z) (
args:
list val) (
tys:
list typ)
:
option mem :=
match args,
tys with
|
nil,
nil =>
Some m
|
a::
args',
ty::
tys' =>
match ty,
a with
|
Tlong,
Vlong n =>
match store_stack m sp Tint (
Ptrofs.repr (
Stacklayout.fe_ofs_arg +
ofs + 4)) (
Vint (
Int64.hiword n))
with
|
Some m' =>
match store_stack m'
sp Tint (
Ptrofs.repr (
Stacklayout.fe_ofs_arg +
ofs)) (
Vint (
Int64.loword n))
with
|
Some m'' =>
store_args_rec m''
sp (
ofs +
typesize ty)
args'
tys'
|
Non =>
None
end
|
None =>
None
end
|
Tlong,
_ =>
None
|
_,
_ =>
match store_stack m sp ty (
Ptrofs.repr (
Stacklayout.fe_ofs_arg +
ofs))
a with
|
None =>
None
|
Some m' =>
store_args_rec m'
sp (
ofs +
typesize ty)
args'
tys'
end
end
|
_,
_ =>
None
end.
Fixpoint args_bytes_rec args tys :
option Z :=
match tys,
args with
|
nil,
nil =>
Some 0
|
ty'::
tys',
a'::
args' =>
if val_has_type_func a'
ty'
then match args_bytes_rec args'
tys'
with
|
Some z =>
Some (
AST.typesize ty' +
z)
|
None =>
None
end
else None
|
_,
_ =>
None
end.
Fixpoint args_len_rec args tys :
option Z :=
match tys,
args with
|
nil,
nil =>
Some 0
|
ty'::
tys',
a'::
args' =>
if val_has_type_func a'
ty'
then match args_len_rec args'
tys'
with
|
Some z =>
Some (
Locations.typesize ty' +
z)
|
None =>
None
end
else None
|
_,
_ =>
None
end.
Lemma typesize_agree:
forall t, (
Locations.typesize t) * 4 =
typesize t.
Proof.
intros. destruct t; simpl; auto. Qed.
Lemma args_bytes_length:
forall args tys z,
args_bytes_rec args tys =
Some z ->
(4 |
z) /\
args_len_rec args tys =
Some (
z / 4).
Proof.
induction args;
intros;
destruct tys;
inv H.
split; [
apply Z.divide_0_r|
auto].
repeat match goal with
|
H:
match ?
x with _ =>
_ end =
_ |-
_ =>
destruct x eqn:?;
inv H
end.
apply IHargs in Heqo.
destruct Heqo.
assert (4 |
typesize t)
by
(
destruct t;
simpl;
try replace 8
with (4 * 2)
by omega;
try apply Z.divide_mul_l;
try apply Z.divide_refl).
split; [
apply Z.divide_add_r;
auto|].
simpl.
rewrite Heqb.
rewrite H0.
f_equal.
rewrite <-
typesize_agree,
Z_div_plus_full_l;
auto.
omega.
Qed.
Lemma args_length_bytes:
forall args tys z,
args_len_rec args tys =
Some z ->
args_bytes_rec args tys =
Some (4 *
z).
Proof.
induction args;
intros;
destruct tys;
inv H;
auto.
repeat match goal with
|
H:
match ?
x with _ =>
_ end =
_ |-
_ =>
destruct x eqn:?;
inv H
end.
apply IHargs in Heqo.
rewrite Z.mul_add_distr_l,
Z.mul_comm,
typesize_agree.
simpl.
rewrite Heqo,
Heqb.
auto.
Qed.
Lemma args_len_rec_non_neg:
forall args tyl z,
args_len_rec args tyl =
Some z ->
z >= 0.
Proof.
Lemma args_len_rec_exists:
forall args0 tyl0,
wd_args args0 tyl0 =
true ->
exists z,
args_len_rec args0 tyl0 =
Some z.
Proof.
clear.
induction args0;
unfold wd_args;
intros ?;
repeat rewrite andb_true_iff.
intuition.
destruct tyl0;
simpl;
eauto.
inversion H.
intuition.
destruct tyl0;
simpl.
inversion H.
simpl in H.
rewrite andb_true_iff in H.
destruct H.
rewrite H.
clear H.
unfold wd_args in IHargs0.
specialize (
IHargs0 tyl0).
rewrite H0 in IHargs0.
clear H0.
assert (
vals_defined args0 =
true)
by (
destruct a;
auto;
discriminate).
rewrite H in IHargs0;
clear H.
destruct zlt.
exploit IHargs0;
auto.
intros (
z &
Hz).
rewrite Hz.
eauto.
generalize g H1;
clear.
intros.
exfalso.
destruct zlt;
inv H1.
rewrite Zlength_cons in l.
omega.
Qed.
Lemma args_len_rec_bound:
forall args0 tyl0 z,
args_len_rec args0 tyl0 =
Some z ->
z <= (2 *
Zlength args0).
Proof.
clear.
induction args0;
intros.
simpl in H.
destruct tyl0;
inv H.
simpl.
omega.
simpl in H.
destruct tyl0;
inv H.
destruct val_has_type_func;
inv H1.
destruct args_len_rec eqn:
C;
inv H0.
apply IHargs0 in C;
clear IHargs0.
rewrite Zlength_cons.
destruct t;
unfold Locations.typesize;
try omega.
Qed.
Lemma store_args_rec_exists:
forall tyl0 args0 z m sp0 ofs,
args_len_rec args0 tyl0 =
Some z ->
vals_defined args0 =
true ->
(4 |
ofs) ->
0 <=
ofs ->
ofs + 4 *
z <
Ptrofs.max_unsigned ->
Mem.range_perm m sp0 ofs (
ofs + 4 *
z)
Cur Writable ->
exists m',
store_args_rec m (
Vptr sp0 Ptrofs.zero)
ofs args0 tyl0 =
Some m'.
Proof.
clear.
induction tyl0;
intros.
destruct args0;
inv H.
simpl.
eauto.
destruct args0;
inv H.
destruct val_has_type_func eqn:?;
inv H6.
destruct args_len_rec eqn:?;
inv H5.
pose proof (
args_len_rec_non_neg _ _ _ Heqo)
as ZGE0.
apply val_has_type_funcP in Heqb.
simpl;
unfold store_stack,
Mach.store_stack,
Mem.storev.
destruct a;
simpl.
{
edestruct (
Mem.valid_access_store m Mint32 sp0 ofs v).
unfold Mem.valid_access.
simpl.
split;
auto.
intros ? ?;
apply H4;
unfold Locations.typesize;
try omega.
eapply IHtyl0 in Heqo.
destruct Heqo.
exists x0.
rewrite Ptrofs.add_zero_l,
Ptrofs.unsigned_repr.
rewrite e,
H;
auto.
unfold Locations.typesize in *.
omega.
destruct v;
auto;
inv H0.
apply Z.divide_add_r;
auto.
apply Z.divide_refl.
omega.
unfold Locations.typesize in *.
omega.
replace (
ofs + 4 * (
Locations.typesize Tint +
z0))
with (
ofs + 4 + 4 *
z0)
in H4 by (
unfold Locations.typesize;
omega).
intros ofs'
RANGE.
eapply Mem.perm_store_1,
H4;
eauto.
omega. }
{
edestruct (
Mem.valid_access_store m Mfloat64 sp0 ofs v).
unfold Mem.valid_access.
simpl.
split;
auto.
intros ? ?;
apply H4;
unfold Locations.typesize;
try omega.
eapply IHtyl0 in Heqo.
destruct Heqo.
exists x0.
rewrite Ptrofs.add_zero_l,
Ptrofs.unsigned_repr.
rewrite e,
H;
auto.
unfold Locations.typesize in *.
omega.
destruct v;
auto;
inv H0.
apply Z.divide_add_r;
auto.
replace 8
with (4 * 2)
by omega.
apply Z.divide_mul_l,
Z.divide_refl.
omega.
unfold Locations.typesize in *.
omega.
replace (
ofs + 4 * (
Locations.typesize Tfloat +
z0))
with (
ofs + 8 + 4 *
z0)
in H3 by (
unfold Locations.typesize;
omega).
intros ofs'
RANGE.
eapply Mem.perm_store_1,
H4;
eauto.
unfold Locations.typesize.
omega. }
{
destruct v;
inv Heqb.
inv H0.
edestruct (
Mem.valid_access_store m Mint32 sp0 (
ofs + 4) (
Vint (
Int64.hiword i))).
unfold Mem.valid_access.
simpl.
split;
auto.
intros ? ?;
apply H4;
unfold Locations.typesize;
try omega.
apply Z.divide_add_r;
auto.
apply Z.divide_refl.
edestruct (
Mem.valid_access_store x Mint32 sp0 ofs (
Vint (
Int64.loword i))).
unfold Mem.valid_access.
simpl.
split;
auto.
intros ? ?;
eapply Mem.perm_store_1,
H4;
eauto;
unfold Locations.typesize;
try omega.
eapply IHtyl0 in Heqo.
destruct Heqo.
exists x1.
repeat rewrite Ptrofs.add_zero_l,
Ptrofs.unsigned_repr.
rewrite e,
e0;
eauto.
unfold Locations.typesize in *.
omega.
unfold Locations.typesize in *.
omega.
auto.
apply Z.divide_add_r;
auto.
replace 8
with (4 * 2)
by omega.
apply Z.divide_mul_l,
Z.divide_refl.
omega.
unfold Locations.typesize in *;
omega.
replace (
ofs + 4 * (
Locations.typesize Tlong +
z0))
with (
ofs + 8 + 4 *
z0)
in H4 by (
unfold Locations.typesize;
omega).
intros ofs'
RANGE.
eapply Mem.perm_store_1,
Mem.perm_store_1,
H4;
eauto.
omega. }
{
edestruct (
Mem.valid_access_store m Mfloat32 sp0 ofs v).
unfold Mem.valid_access.
simpl.
split;
auto.
intros ? ?;
apply H4;
unfold Locations.typesize;
try omega.
eapply IHtyl0 in Heqo.
destruct Heqo.
exists x0.
rewrite Ptrofs.add_zero_l,
Ptrofs.unsigned_repr.
rewrite e,
H;
auto.
unfold Locations.typesize in *.
omega.
destruct v;
inv Heqb.
inv H0.
auto.
apply Z.divide_add_r;
auto.
apply Z.divide_refl.
omega.
unfold Locations.typesize in *.
omega.
replace (
ofs + 4 * (
Locations.typesize Tsingle +
z0))
with (
ofs + 4 + 4 *
z0)
in H4 by (
unfold Locations.typesize;
omega).
intros ofs'
RANGE.
eapply Mem.perm_store_1,
H4;
eauto.
omega. }
{
edestruct (
Mem.valid_access_store m Many32 sp0 ofs v).
unfold Mem.valid_access.
simpl.
split;
auto.
intros ? ?;
apply H4;
unfold Locations.typesize;
try omega.
eapply IHtyl0 in Heqo.
destruct Heqo.
exists x0.
rewrite Ptrofs.add_zero_l,
Ptrofs.unsigned_repr.
rewrite e,
H;
auto.
unfold Locations.typesize in *.
omega.
destruct v;
inv Heqb;
inv H0;
auto.
apply Z.divide_add_r;
auto.
apply Z.divide_refl.
omega.
unfold Locations.typesize in *.
omega.
replace (
ofs + 4 * (
Locations.typesize Tint +
z0))
with (
ofs + 4 + 4 *
z0)
in H3 by (
unfold Locations.typesize;
omega).
intros ofs'
RANGE.
eapply Mem.perm_store_1,
H4;
eauto.
unfold Locations.typesize;
omega. }
{
edestruct (
Mem.valid_access_store m Many64 sp0 ofs v).
unfold Mem.valid_access.
simpl.
split;
auto.
intros ? ?;
apply H4;
unfold Locations.typesize;
try omega.
eapply IHtyl0 in Heqo.
destruct Heqo.
exists x0.
rewrite Ptrofs.add_zero_l,
Ptrofs.unsigned_repr.
rewrite e,
H;
auto.
unfold Locations.typesize in *.
omega.
destruct v;
inv Heqb;
inv H0;
auto.
apply Z.divide_add_r;
auto.
replace 8
with (4 * 2)
by omega.
apply Z.divide_mul_l,
Z.divide_refl.
omega.
unfold Locations.typesize in *.
omega.
replace (
ofs + 4 * (
Locations.typesize Tany64 +
z0))
with (
ofs + 8 + 4 *
z0)
in H3 by (
unfold Locations.typesize;
omega).
intros ofs'
RANGE.
eapply Mem.perm_store_1,
H4;
eauto.
unfold Locations.typesize;
omega. }
Qed.
Lemma args_len_rec_inject:
forall j args args'
tyl z,
Val.inject_list j args args' ->
vals_defined args =
true ->
args_len_rec args tyl =
Some z ->
args_len_rec args'
tyl =
Some z.
Proof.
clear.
induction args;
intros.
inv H.
auto.
inv H.
inv H1.
inv H0.
destruct tyl as [|
ty'
tys'];[
discriminate|
destruct (
val_has_type_func a ty')
eqn:?;
try discriminate].
simpl.
inv H4;
destruct ty';
cbv in Heqb;
try discriminate;
simpl;
(
destruct args_len_rec eqn:?;
try discriminate;
inv H1;
eapply IHargs in Heqo;
eauto;
rewrite Heqo;
auto).
Qed.
Fixpoint tyl_length (
tyl:
list typ) :
Z :=
match tyl with
|
nil => 0
|
ty' ::
tyl' =>
Locations.typesize ty' + (
tyl_length tyl')
end.
Fixpoint tyl_bytes (
tyl:
list typ) :
Z :=
match tyl with
|
nil => 0
|
ty'::
tyl' =>
AST.typesize ty' + (
tyl_bytes tyl')
end.
Lemma tyl_length_agree:
forall tyl, (
tyl_length tyl) * 4 =
tyl_bytes tyl.
Proof.
Lemma tyl_length_size_arguments_32:
forall tyl,
Conventions1.size_arguments_32 tyl 0 =
tyl_length tyl.
Proof.
Lemma tyl_bytes_app:
forall tyl tyl',
tyl_bytes (
tyl ++
tyl') =
tyl_bytes tyl +
tyl_bytes tyl'.
Proof.
clear. induction tyl; simpl; intros; auto. rewrite IHtyl. omega.
Qed.
Lemma tyl_bytes_non_neg:
forall tyl,
tyl_bytes tyl >= 0.
Proof.
clear.
induction tyl as[|
ty tyl];
simpl; [|
pose proof (
AST.typesize_pos ty)];
omega.
Qed.
Definition store_arg m sp ofs ty'
a' :=
store_args_rec m sp ofs a'
ty'.
Definition store_args m sp args tys :=
store_args_rec m (
Vptr sp Ptrofs.zero) 0
args tys.
Lemma store_args_exists:
forall tyl0 args0 z m m'
sp0,
wd_args args0 tyl0 =
true ->
args_len_rec args0 tyl0 =
Some z ->
Mem.alloc m 0 (4 *
z) = (
m',
sp0) ->
exists m'',
store_args m'
sp0 args0 tyl0 =
Some m''.
Proof.
Lemma store_args_rec_unchanged_on:
forall sp args tyl z m m',
store_args_rec m (
Vptr sp Ptrofs.zero)
z args tyl =
Some m' ->
Mem.unchanged_on (
fun b _ =>
b <>
sp)
m m'.
Proof.
Lemma store_args_unchanged_on:
forall m sp args tyl m',
store_args m sp args tyl =
Some m' ->
Mem.unchanged_on (
fun b _ =>
b <>
sp)
m m'.
Proof.
Fixpoint store_args_rec_fp (
sp:
block) (
ofs:
Z) (
tys:
list typ) :
footprint :=
let vsp :=
Vptr sp Ptrofs.zero in
match tys with
|
nil =>
empfp
|
ty::
tys' =>
match ty with
|
Tlong =>
FP.union (
FP.union (
store_stack_fp vsp Tint (
Ptrofs.repr (
Stacklayout.fe_ofs_arg +
ofs)))
(
store_stack_fp vsp Tint (
Ptrofs.repr (
Stacklayout.fe_ofs_arg +
ofs + 4))))
(
store_args_rec_fp sp (
ofs +
typesize ty)
tys')
|
_ =>
FP.union (
store_stack_fp vsp ty (
Ptrofs.repr (
Stacklayout.fe_ofs_arg +
ofs)))
(
store_args_rec_fp sp (
ofs +
typesize ty)
tys')
end
end.
Definition store_args_fp sp tyl :=
store_args_rec_fp sp 0
tyl.
Ltac red_ptr :=
match goal with
|
H:
context[
Ptrofs.add Ptrofs.zero _] |-
_ =>
rewrite Ptrofs.add_zero_l in H
| |-
context[
Ptrofs.add Ptrofs.zero _] =>
rewrite Ptrofs.add_zero_l
| |-
context[
Ptrofs.unsigned (
Ptrofs.repr _)] =>
try (
rewrite Ptrofs.unsigned_repr; [|
unfold Ptrofs.max_unsigned;
try omega;
fail])
|
H:
context[
Ptrofs.unsigned (
Ptrofs.repr _)] |-
_ =>
try (
rewrite Ptrofs.unsigned_repr in H;[|
unfold Ptrofs.max_unsigned;
try omega;
fail])
end.
Ltac red_triv :=
match goal with
|
H:
match ?
x with _ =>
_ end =
_ |-
_ =>
destruct x eqn:?;
try (
inv H;
fail)
|
H:
match ?
x with _ =>
_ end |-
_ =>
destruct x eqn:?;
try (
congruence;
fail)
end.
Ltac Cintro :=
match goal with
| |-
not ?
x =>
intro
end.
store_args -> unchanged on ...
Lemma store_stack_unchanged_on:
forall m sp ty ofs v m',
store_stack m (
Vptr sp Ptrofs.zero)
ty ofs v =
Some m' ->
Mem.unchanged_on
(
fun b i => ~ (
b =
sp /\ (
Ptrofs.unsigned ofs <=
i <
Ptrofs.unsigned ofs +
AST.typesize ty)))
m m'.
Proof.
Lemma store_args_rec_unchanged_on_weak:
forall m sp ofs args tyl m',
0 <=
ofs ->
ofs + (4 * (2 *
Zlength args)) <
Ptrofs.modulus ->
store_args_rec m (
Vptr sp Ptrofs.zero)
ofs args tyl =
Some m' ->
Mem.unchanged_on
(
fun b i =>
if eq_block b sp then i < (
Ptrofs.unsigned (
Ptrofs.repr ofs))
else True)
m m'.
Proof.
agreements between args and stack contents
Fixpoint agree_args_contains_aux m sp0 ofs args tys :
Prop :=
let vsp :=
Vptr sp0 Ptrofs.zero in
match tys,
args with
|
nil,
nil =>
True
|
ty ::
tys',
a ::
args' =>
match ty,
a with
|
Tlong ,
Vlong n =>
load_stack m vsp Tint (
Ptrofs.repr (
Stacklayout.fe_ofs_arg +
ofs + 4)) =
Some (
Vint (
Int64.hiword n))
/\
load_stack m vsp Tint (
Ptrofs.repr (
Stacklayout.fe_ofs_arg +
ofs)) =
Some (
Vint (
Int64.loword n))
/\
agree_args_contains_aux m sp0 (
ofs +
typesize ty)
args'
tys'
|
Tlong,
_ =>
False
|
_ ,
_ =>
load_stack m vsp ty (
Ptrofs.repr ofs) =
Some a
/\
agree_args_contains_aux m sp0 (
ofs +
typesize ty)
args'
tys'
end
|
_,
_ =>
False
end.
Definition agree_args_contains m sp0 args tys :
Prop :=
agree_args_contains_aux m sp0 0
args tys.
Lemma store_args_rec_agree_args_contains_aux:
forall tyl m sp ofs args m',
wd_args args tyl =
true ->
0 <=
ofs ->
ofs + (4 * (2 *
Zlength args)) <
Ptrofs.modulus ->
store_args_rec m (
Vptr sp Ptrofs.zero)
ofs args tyl =
Some m' ->
agree_args_contains_aux m'
sp ofs args tyl.
Proof.
Lemma agree_args_contains_aux_invariant:
forall tys m sp ofs args m',
agree_args_contains_aux m sp ofs args tys ->
Mem.unchanged_on (
fun b ofs =>
b=
sp)
m m' ->
agree_args_contains_aux m'
sp ofs args tys.
Proof.
induction tys.
destruct args;
simpl;
auto.
intros m';
destruct args;
simpl;
auto.
intros m''.
destruct a;
try (
intros (
LOAD0 &
AGREE)
UNCHG;
split;
[
eapply Mem.load_unchanged_on;
eauto;
simpl;
auto|
eauto]).
destruct v;
try (
intro C;
inv C;
fail).
intros (
LOAD1 &
LOAD2 &
AGREE)
UNCHG.
split; [|
split;[|
eauto]];
eapply Mem.load_unchanged_on;
eauto;
simpl;
auto.
Qed.
FMem version of store_args
Require Import FMemory.
Definition store_stack_fmem (
m:
mem) (
sp:
val) (
ty:
typ) (
ofs:
ptrofs) (
v:
val) :
option mem :=
Mem.storev (
chunk_of_type ty)
m (
Val.offset_ptr sp ofs)
v.
Fixpoint store_args_rec_fmem (
m:
mem) (
sp:
val) (
ofs:
Z) (
args:
list val) (
tys:
list typ)
:
option mem :=
match args,
tys with
|
nil,
nil =>
Some m
|
a::
args',
ty::
tys' =>
match ty,
a with
|
Tlong,
Vlong n =>
match store_stack_fmem m sp Tint (
Ptrofs.repr (
Stacklayout.fe_ofs_arg +
ofs + 4)) (
Vint (
Int64.hiword n))
with
|
Some m' =>
match store_stack_fmem m'
sp Tint (
Ptrofs.repr (
Stacklayout.fe_ofs_arg +
ofs)) (
Vint (
Int64.loword n))
with
|
Some m'' =>
store_args_rec_fmem m''
sp (
ofs +
typesize ty)
args'
tys'
|
Non =>
None
end
|
None =>
None
end
|
Tlong,
_ =>
None
|
_,
_ =>
match store_stack_fmem m sp ty (
Ptrofs.repr (
Stacklayout.fe_ofs_arg +
ofs))
a with
|
None =>
None
|
Some m' =>
store_args_rec_fmem m'
sp (
ofs +
typesize ty)
args'
tys'
end
end
|
_,
_ =>
None
end.
Definition store_args_fmem (
m:
mem) (
sp:
block) (
args:
list val) (
tys:
list typ) :
option mem :=
store_args_rec_fmem m (
Vptr sp Ptrofs.zero) 0
args tys.