Require Import Smallstep.
Require Import Machregs.
Require Import Asm.
Require Import Integers.
Require Import List.
Require Import ZArith.
Require Import Memtype.
Require Import Memory.
Require Import Archi.
Require Import Coqlib.
Require Import AST.
Require Import Globalenvs.
Require Import Events.
Require Import Values.
Require Import Conventions1.
Require Import AsmFacts AsmRegs.
Require Import RawAsm.
Section WITHMEMORYMODEL.
Context `{
memory_model:
Mem.MemoryModel }.
Existing Instance inject_perm_upto_writable.
Context `{
external_calls_ops : !
ExternalCallsOps mem }.
Context `{!
EnableBuiltins mem}.
Existing Instance mem_accessors_default.
Existing Instance symbols_inject_instance.
Context `{
external_calls_props : !
ExternalCallsProps mem
(
memory_model_ops :=
memory_model_ops)
}.
Variable prog:
Asm.program.
Let ge :=
Genv.globalenv prog.
Definition bstack :=
Genv.genv_next ge.
Section PRESERVATION.
Variable init_stk:
stack.
Definition init_sp:
val :=
current_sp init_stk.
Variable binit_sp:
block.
Hypothesis init_sp_ptr:
init_sp =
Vptr binit_sp Ptrofs.zero.
Lemma type_init_sp:
Val.has_type init_sp Tptr.
Proof.
Lemma init_sp_zero:
forall b o,
init_sp =
Vptr b o ->
o =
Ptrofs.zero.
Proof.
Definition is_unchanged (
i:
instruction) :=
match i with
Pallocframe _ _ _
|
Pfreeframe _ _
|
Pload_parent_pointer _ _
|
Pcall _ _
|
Pret =>
false
|
_ =>
true
end.
Lemma is_unchanged_exec:
forall (
ge:
Genv.t Asm.fundef unit)
f rs m i istk,
is_unchanged i =
true ->
exec_instr ge f i rs m =
Asm.exec_instr istk ge f i rs m.
Proof.
destruct i; simpl; intros; try reflexivity; try congruence.
Qed.
Definition no_inject_below j m thr:=
forall b delta o k p,
j b =
Some (
bstack,
delta) ->
Mem.perm m b o k p ->
thr <=
o +
delta /\
in_stack (
Mem.stack m)
b.
Fixpoint size_active_stack (
s:
stack) :
Z :=
match s with
nil => 0
|
fr::
r =>
size_active_stack r +
opt_size_frame (
fst fr)
end.
Definition agree_sp m1 rs2:=
forall ostack,
rs2 #
RSP =
Vptr bstack ostack ->
Ptrofs.unsigned ostack =
Mem.stack_limit +
align (
size_chunk Mptr) 8 -
size_active_stack (
Mem.stack m1).
Definition perm_bstack m2:=
forall (
ofs :
Z) (
k :
perm_kind) (
p :
permission),
Mem.perm m2 bstack ofs k p -> 0 <=
ofs <
Ptrofs.max_unsigned /\
perm_order Writable p.
Definition perm_bstack_stack_limit m2:=
forall (
ofs :
Z) (
k :
perm_kind),
0 <=
ofs <
Mem.stack_limit +
align (
size_chunk Mptr) 8 ->
Mem.perm m2 bstack ofs k Writable.
Definition sp_aligned rs2:=
forall ostack,
rs2 #
RSP =
Vptr bstack ostack ->
(8 |
Ptrofs.unsigned ostack).
Definition no_stack m2 :=
exists fr fi r,
Mem.stack m2 = (
Some fr,
nil) ::
r /\
(
bstack,
fi)::
nil =
frame_adt_blocks fr /\
0 =
frame_adt_size fr /\
(
forall o,
frame_perm fi o =
Public) /\
frame_size fi =
Mem.stack_limit +
align (
size_chunk Mptr) 8.
Lemma no_stack_no_nil m:
no_stack m ->
Mem.stack m <>
nil.
Proof.
intros (frstack & fstack & r & EQstk & BLOCKS & ZERO & PUB & SZ).
rewrite EQstk. congruence.
Qed.
Inductive inject_perm_stack (
j:
meminj) (
P:
perm_type):
stack ->
Prop :=
|
inject_perm_stack_nil:
inject_perm_stack j P nil
|
inject_perm_stack_cons_nil l (
IPS_REC:
inject_perm_stack j P l)
r:
inject_perm_stack j P ((
None,
r)::
l)
|
inject_perm_stack_cons
l fr b fi (
IPS_REC:
inject_perm_stack j P l)
r
(
JB:
j b =
Some (
bstack,
Mem.stack_limit +
align (
size_chunk Mptr) 8 -
size_active_stack l -
align (
frame_size fi) 8))
(
BLOCKS:
frame_adt_blocks fr = (
b,
fi)::
nil)
(
SIZE:
frame_adt_size fr =
frame_size fi)
(
PERM:
forall o k p, 0 <=
o <
frame_size fi ->
P b o k p):
inject_perm_stack j P ((
Some fr,
r)::
l).
Definition inject_padding (
j:
meminj) (
m:
mem) :
Prop :=
forall b fi delta,
in_stack' (
Mem.stack m) (
b,
fi) ->
j b =
Some (
bstack,
delta) ->
forall b'
o delta'
k p,
j b' =
Some (
bstack,
delta') ->
Mem.perm m b'
o k p ->
~ (
delta +
frame_size fi <=
o +
delta' <
delta +
align (
frame_size fi) 8).
Inductive match_states:
meminj ->
Z ->
state ->
state ->
Prop :=
|
match_states_intro:
forall j (
rs:
regset) (
m:
mem) (
rs':
regset)
m'
g
(
MINJ:
Mem.inject j g m m')
lprog
(
STK:
Mem.stack m =
lprog ++
init_stk)
(
GSPEC:
g =
S (
length lprog) ::
flat_frameinj (
pred (
length init_stk)))
(
RSPzero:
exists b,
rs #
RSP =
Vptr b Ptrofs.zero )
(
RINJ:
forall r,
Val.inject j (
rs #
r) (
rs' #
r))
(
VB:
Mem.valid_block m'
bstack)
(
AGSP:
agree_sp m rs')
(
SPAL:
sp_aligned rs')
(
PBS:
perm_bstack m')
(
PBSL:
perm_bstack_stack_limit m')
(
NS:
no_stack m')
ostack
(
RSPEQ:
rs'
RSP =
Vptr bstack ostack)
(
NIB:
no_inject_below j m (
Ptrofs.unsigned ostack))
(
IS:
inject_perm_stack j (
Mem.perm m) (
Mem.stack m))
(
IP:
inject_padding j m)
(
GLOBFUN_INJ:
forall b f,
Genv.find_funct_ptr ge b =
Some f ->
j b =
Some (
b,0))
(
GLOBDEF_INJ:
forall b f,
Genv.find_def ge b =
Some f ->
j b =
Some (
b,0))
(
GLOBSYMB_INJ:
meminj_preserves_globals'
ge j)
(
GlobInjInv:
forall b1 b2 delta,
Plt b2 (
Genv.genv_next ge) ->
j b1 =
Some (
b2,
delta) ->
b1 =
b2)
(
GlobLe: (
Genv.genv_next ge <=
Mem.nextblock m)%
positive)
(
GlobLeT: (
Genv.genv_next ge <=
Mem.nextblock m')%
positive)
(
SPinstack:
in_stack' (
Mem.stack m) (
binit_sp,
public_frame_info 0)),
match_states j (
Ptrofs.unsigned ostack) (
State rs m) (
State rs'
m').
Lemma inject_stack_incr:
forall j j'
P (
INCR:
inject_incr j j')
l (
IS:
inject_perm_stack j P l),
inject_perm_stack j'
P l.
Proof.
induction 2; econstructor; eauto.
Qed.
Lemma inject_stack_more_perm:
forall j (
P P':
perm_type) (
INCR:
forall b o k p,
P b o k p ->
P'
b o k p)
l (
IS:
inject_perm_stack j P l),
inject_perm_stack j P'
l.
Proof.
induction 2; econstructor; eauto.
Qed.
Lemma perm_stack_inv:
forall j (
P P':
perm_type)
l (
IS:
inject_perm_stack j P l)
(
INCR:
forall b o k p,
in_stack l b ->
P b o k p ->
P'
b o k p),
inject_perm_stack j P'
l.
Proof.
induction 1;
econstructor;
eauto.
-
eapply IHIS;
eauto.
intros;
eapply INCR;
eauto.
rewrite in_stack_cons;
auto.
-
intros;
eapply INCR;
eauto.
rewrite in_stack_cons.
left;
rewrite in_frames_cons.
eexists;
split;
eauto.
eapply in_frame'
_in_frame.
red.
rewrite BLOCKS.
left.
reflexivity.
Qed.
Lemma symbol_address_inject:
forall j id i0,
meminj_preserves_globals'
ge j ->
Val.inject j (
Genv.symbol_address ge id i0) (
Genv.symbol_address ge id i0).
Proof.
Lemma eval_addrmode32_inject:
forall a rs1 rs2 j,
meminj_preserves_globals'
ge j ->
(
forall r,
Val.inject j (
rs1 r) (
rs2 r)) ->
Val.inject j (
eval_addrmode32 ge a rs1) (
eval_addrmode32 ge a rs2).
Proof.
Lemma eval_addrmode64_inject:
forall a rs1 rs2 j,
meminj_preserves_globals'
ge j ->
(
forall r,
Val.inject j (
rs1 r) (
rs2 r)) ->
Val.inject j (
eval_addrmode64 ge a rs1) (
eval_addrmode64 ge a rs2).
Proof.
Lemma eval_addrmode_inject:
forall a rs1 rs2 j,
meminj_preserves_globals'
ge j ->
(
forall r,
Val.inject j (
rs1 r) (
rs2 r)) ->
Val.inject j (
eval_addrmode ge a rs1) (
eval_addrmode ge a rs2).
Proof.
Lemma exec_load_inject:
forall κ
m1 a rs1 rd ofs rs1'
m1'
rs2 m2 j g,
meminj_preserves_globals'
ge j ->
Mem.inject j g m1 m2 ->
(
forall r,
Val.inject j (
rs1 r) (
rs2 r)) ->
exec_load ge κ
m1 a rs1 rd ofs =
Next rs1'
m1' ->
exists rs2'
m2',
exec_load ge κ
m2 a rs2 rd ofs =
Next rs2'
m2' /\
Mem.inject j g m1'
m2' /\
forall r,
Val.inject j (
rs1'
r) (
rs2'
r).
Proof.
Lemma exec_store_inject:
forall κ
m1 a rs1 rd ofs rs1'
m1'
rs2 m2 j g destroyed,
meminj_preserves_globals'
ge j ->
Mem.inject j g m1 m2 ->
(
forall r,
Val.inject j (
rs1 r) (
rs2 r)) ->
exec_store ge κ
m1 a rs1 rd destroyed ofs =
Next rs1'
m1' ->
exists rs2'
m2',
exec_store ge κ
m2 a rs2 rd destroyed ofs =
Next rs2'
m2' /\
Mem.inject j g m1'
m2' /\
forall r,
Val.inject j (
rs1'
r) (
rs2'
r).
Proof.
Definition cmpu_bool_inject :=
fun j g m m' (
MINJ:
Mem.inject j g m m') =>
Val.cmpu_bool_inject j (
Mem.valid_pointer m) (
Mem.valid_pointer m')
(
fun b1 ofs b2 delta FB =>
Mem.valid_pointer_inject'
j g m m'
b1 ofs b2 delta FB MINJ)
(
fun b1 ofs b2 delta FB =>
Mem.weak_valid_pointer_inject'
j g m m'
b1 ofs b2 delta FB MINJ)
(
fun b ofs b'
delta FB MVP =>
Mem.weak_valid_pointer_inject_no_overflow j g m m'
b ofs b'
delta MINJ MVP FB)
(
fun b1 ofs1 b2 ofs2 b1'
delta1 b2'
delta2 =>
Mem.different_pointers_inject j g m m'
b1 ofs1 b2 ofs2 b1'
delta1 b2'
delta2 MINJ).
Lemma cmpu_inject
:
forall (
j :
meminj) (
g :
frameinj) (
m m' :
mem),
Mem.inject j g m m' ->
forall (
c :
comparison) (
v1 v2 v1'
v2' :
val),
Val.inject j v1 v1' ->
Val.inject j v2 v2' ->
Val.inject j (
Val.cmpu (
Mem.valid_pointer m)
c v1 v2)
(
Val.cmpu (
Mem.valid_pointer m')
c v1'
v2').
Proof.
Definition cmplu_bool_inject :=
fun j g m m' (
MINJ:
Mem.inject j g m m') =>
Val.cmplu_bool_inject j (
Mem.valid_pointer m) (
Mem.valid_pointer m')
(
fun b1 ofs b2 delta FB =>
Mem.valid_pointer_inject'
j g m m'
b1 ofs b2 delta FB MINJ)
(
fun b1 ofs b2 delta FB =>
Mem.weak_valid_pointer_inject'
j g m m'
b1 ofs b2 delta FB MINJ)
(
fun b ofs b'
delta FB MVP =>
Mem.weak_valid_pointer_inject_no_overflow j g m m'
b ofs b'
delta MINJ MVP FB)
(
fun b1 ofs1 b2 ofs2 b1'
delta1 b2'
delta2 =>
Mem.different_pointers_inject j g m m'
b1 ofs1 b2 ofs2 b1'
delta1 b2'
delta2 MINJ).
Lemma cmplu_inject
:
forall (
j :
meminj) (
g :
frameinj) (
m m' :
mem),
Mem.inject j g m m' ->
forall (
c :
comparison) (
v1 v2 v1'
v2' :
val),
Val.inject j v1 v1' ->
Val.inject j v2 v2' ->
Val.opt_val_inject j (
Val.cmplu (
Mem.valid_pointer m)
c v1 v2)
(
Val.cmplu (
Mem.valid_pointer m')
c v1'
v2').
Proof.
Lemma negative_inject:
forall j v v',
Val.inject j v v' ->
Val.inject j (
Val.negative v) (
Val.negative v').
Proof.
Lemma negativel_inject:
forall j v v',
Val.inject j v v' ->
Val.inject j (
Val.negativel v) (
Val.negativel v').
Proof.
Lemma sub_overflow_inject:
forall j v1 v2 v3 v4,
Val.inject j v1 v2 ->
Val.inject j v3 v4 ->
Val.inject j (
Val.sub_overflow v1 v3) (
Val.sub_overflow v2 v4).
Proof.
unfold Val.sub_overflow;
intros.
destr;
auto.
inv H.
destr;
auto;
inv H0.
auto.
Qed.
Lemma subl_overflow_inject:
forall j v1 v2 v3 v4,
Val.inject j v1 v2 ->
Val.inject j v3 v4 ->
Val.inject j (
Val.subl_overflow v1 v3) (
Val.subl_overflow v2 v4).
Proof.
unfold Val.subl_overflow;
intros.
destr;
auto.
inv H.
destr;
auto;
inv H0.
auto.
Qed.
Lemma eval_testcond_inject:
forall j rs1 rs2
(
RINJ :
forall r :
PregEq.t,
Val.inject j (
rs1 r) (
rs2 r))
c b,
eval_testcond c rs1 =
Some b ->
eval_testcond c rs2 =
Some b.
Proof.
unfold eval_testcond.
intros.
generalize (
RINJ ZF), (
RINJ CF), (
RINJ OF), (
RINJ SF), (
RINJ PF).
intros A B C D E.
repeat destr_in H;
repeat match goal with
|
H:
Val.inject _ (
Vint _)
_ |-
_ =>
inv H
| |-
_ =>
simpl;
auto
end.
Qed.
Lemma eval_testcond_of_optbool_inject:
forall j rs1 rs2
(
RINJ :
forall r :
PregEq.t,
Val.inject j (
rs1 r) (
rs2 r))
c,
Val.inject j (
Val.of_optbool (
eval_testcond c rs1)) (
Val.of_optbool (
eval_testcond c rs2)).
Proof.
Ltac simpl_inject :=
first [
apply val_inject_nextinstr
|
apply val_inject_nextinstr_nf
|
apply val_inject_set
|
apply val_inject_undef_regs
|
apply Val.offset_ptr_inject
|
apply Val.sign_ext_inject
|
apply Val.zero_ext_inject
|
apply Val.longofintu_inject
|
apply Val.longofint_inject
|
apply Val.singleoffloat_inject
|
apply Val.floatofsingle_inject
|
apply Val.maketotal_inject
|
apply Val.intoffloat_inject
|
apply Val.floatofint_inject
|
apply Val.longoffloat_inject
|
apply Val.floatoflong_inject
|
apply Val.intofsingle_inject
|
apply Val.singleofint_inject
|
apply Val.longofsingle_inject
|
apply Val.singleoflong_inject
|
apply Val.loword_inject
|
apply Val.hiword_inject
|
apply Val.neg_inject
|
apply Val.negl_inject
|
apply Val.add_inject
|
apply Val.sub_inject
|
apply Val.mul_inject
|
apply Val.addl_inject
|
apply Val.subl_inject
|
apply Val.mull_inject
|
apply Val.mulhs_inject
|
apply Val.mullhs_inject
|
apply Val.mulhu_inject
|
apply Val.mullhu_inject
|
apply Val.shr_inject
|
apply Val.shrl_inject
|
apply Val.shl_inject
|
apply Val.shll_inject
|
apply Val.shru_inject
|
apply Val.shrlu_inject
|
apply Val.and_inject
|
apply Val.andl_inject
|
apply Val.or_inject
|
apply Val.orl_inject
|
apply Val.xor_inject
|
apply Val.xorl_inject
|
apply Val.notint_inject
|
apply Val.notl_inject
|
apply Val.ror_inject
|
apply Val.rorl_inject
|
apply eval_addrmode32_inject
|
apply eval_addrmode64_inject
|
apply eval_addrmode_inject
|
apply symbol_address_inject
|
eapply cmpu_inject;
eauto
|
eapply cmplu_inject;
eauto
|
apply negative_inject
|
apply negativel_inject
|
apply sub_overflow_inject
|
apply subl_overflow_inject
|
apply Val.addf_inject
|
apply Val.subf_inject
|
apply Val.mulf_inject
|
apply Val.divf_inject
|
apply Val.negf_inject
|
apply Val.absf_inject
|
apply Val.addfs_inject
|
apply Val.subfs_inject
|
apply Val.mulfs_inject
|
apply Val.divfs_inject
|
apply Val.negfs_inject
|
apply Val.absfs_inject
|
unfold Vzero;
auto
].
Lemma compare_floats_inject:
forall j rs1 rs2
(
RINJ :
forall r :
PregEq.t,
Val.inject j (
rs1 r) (
rs2 r))
a b c d
(
INJ1:
Val.inject j a c) (
INJ2:
Val.inject j b d)
r,
Val.inject j (
compare_floats a b rs1 r) (
compare_floats c d rs2 r).
Proof.
Lemma compare_floats32_inject:
forall j rs1 rs2
(
RINJ :
forall r :
PregEq.t,
Val.inject j (
rs1 r) (
rs2 r))
a b c d
(
INJ1:
Val.inject j a c) (
INJ2:
Val.inject j b d)
r,
Val.inject j (
compare_floats32 a b rs1 r) (
compare_floats32 c d rs2 r).
Proof.
Lemma goto_label_inject:
forall j g rs1 rs2 m1 m2
(
GLOBFUN_INJ:
forall b f,
Genv.find_funct_ptr ge b =
Some f ->
j b =
Some (
b,0))
(
MINJ:
Mem.inject j g m1 m2)
(
RINJ :
forall r :
PregEq.t,
Val.inject j (
rs1 r) (
rs2 r))
l f rs1'
m1',
goto_label ge f l rs1 m1 =
Next rs1'
m1' ->
exists rs2'
m2',
goto_label ge f l rs2 m2 =
Next rs2'
m2' /\
Mem.inject j g m1'
m2' /\
forall r,
Val.inject j (
rs1'
r) (
rs2'
r).
Proof.
unfold goto_label.
intros.
repeat destr_in H.
generalize (
RINJ PC);
rewrite Heqv.
intro A;
inv A.
erewrite GLOBFUN_INJ in H2;
eauto.
inv H2.
rewrite Heqo0.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
econstructor;
eauto.
rewrite Ptrofs.add_zero.
auto.
Qed.
Lemma eval_ros_inject:
forall j rs1 rs2
(
MPG:
meminj_preserves_globals'
ge j)
(
RINJ :
forall r :
PregEq.t,
Val.inject j (
rs1 r) (
rs2 r))
ros,
Val.inject j (
eval_ros ge ros rs1) (
eval_ros ge ros rs2).
Proof.
unfold eval_ros.
intros.
destr;
auto.
repeat simpl_inject.
Qed.
Lemma exec_instr_inject:
forall j g m1 m2 rs1 rs2 f i rs1'
m1'
(
GLOBFUN_INJ:
forall b f,
Genv.find_funct_ptr ge b =
Some f ->
j b =
Some (
b,0))
(
MINJ:
Mem.inject j g m1 m2)
(
RINJ:
forall r,
Val.inject j (
rs1 #
r) (
rs2 #
r))
(
IU:
is_unchanged i =
true)
(
MPG:
meminj_preserves_globals'
ge j)
istk1 istk2
(
EXEC:
Asm.exec_instr istk1 ge f i rs1 m1 =
Next rs1'
m1'),
exists rs2'
m2',
Asm.exec_instr istk2 ge f i rs2 m2 =
Next rs2'
m2'
/\
Mem.inject j g m1'
m2'
/\ (
forall r,
Val.inject j (
rs1' #
r) (
rs2' #
r)).
Proof.
intros j g m1 m2 rs1 rs2 f i rs1'
m1'
GLOBFUN_INJ MINJ RINJ IU MPG istk1 istk2 EXEC.
destruct i; (
simpl in *;
repeat destr_in EXEC;
try congruence;
match goal with
| |-
exists _ _,
Next _ _ =
Next _ _ /\
_ /\
_ =>
try (
do 2
eexists;
split; [
now eauto |
split; [
eauto with mem
|
repeat
simpl_inject
]
]
)
| |-
_ =>
try first [
now (
eapply exec_load_inject;
eauto)
|
now (
eapply exec_store_inject;
eauto)
]
end
).
generalize (
RINJ RDX);
rewrite Heqv;
inversion 1;
subst.
generalize (
RINJ RAX);
rewrite Heqv0;
inversion 1;
subst.
generalize (
RINJ r1);
rewrite Heqv1;
inversion 1;
subst.
rewrite Heqo.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
generalize (
RINJ RDX);
rewrite Heqv;
inversion 1;
subst.
generalize (
RINJ RAX);
rewrite Heqv0;
inversion 1;
subst.
generalize (
RINJ r1);
rewrite Heqv1;
inversion 1;
subst.
rewrite Heqo.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
generalize (
RINJ RDX);
rewrite Heqv;
inversion 1;
subst.
generalize (
RINJ RAX);
rewrite Heqv0;
inversion 1;
subst.
generalize (
RINJ r1);
rewrite Heqv1;
inversion 1;
subst.
rewrite Heqo.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
generalize (
RINJ RDX);
rewrite Heqv;
inversion 1;
subst.
generalize (
RINJ RAX);
rewrite Heqv0;
inversion 1;
subst.
generalize (
RINJ r1);
rewrite Heqv1;
inversion 1;
subst.
rewrite Heqo.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
erewrite eval_testcond_inject;
eauto.
simpl.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
erewrite eval_testcond_inject;
eauto.
simpl.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
destr.
destr.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
intros.
setoid_rewrite Pregmap.gsspec.
destr;
auto.
unfold Pregmap.get.
auto.
setoid_rewrite Pregmap.gsspec.
destr;
auto.
unfold Pregmap.get.
auto.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
eapply eval_testcond_of_optbool_inject;
eauto.
eapply eval_testcond_of_optbool_inject;
eauto.
apply compare_floats_inject;
auto.
apply compare_floats_inject;
auto.
apply compare_floats32_inject;
auto.
apply compare_floats32_inject;
auto.
eapply goto_label_inject;
eauto.
exploit eval_ros_inject;
eauto.
unfold Genv.find_funct in *.
repeat destr_in Heqo.
rewrite Heqv.
intro A;
inv A.
erewrite GLOBFUN_INJ in H3;
eauto.
inv H3.
rewrite pred_dec_true.
rewrite H0.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
econstructor;
eauto.
apply Ptrofs.add_zero.
erewrite eval_testcond_inject;
eauto.
simpl.
eapply goto_label_inject;
eauto.
erewrite eval_testcond_inject;
eauto.
simpl.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
erewrite eval_testcond_inject;
eauto.
simpl.
erewrite eval_testcond_inject;
eauto.
simpl.
eapply goto_label_inject;
eauto.
erewrite eval_testcond_inject;
eauto.
simpl.
erewrite eval_testcond_inject;
eauto.
simpl.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
erewrite eval_testcond_inject;
eauto.
simpl.
erewrite eval_testcond_inject;
eauto.
do 2
eexists;
split;
eauto.
split;
eauto.
repeat simpl_inject.
generalize (
RINJ r);
rewrite Heqv;
intro A;
inv A.
rewrite Heqo.
eapply goto_label_inject;
eauto.
repeat simpl_inject.
Qed.
Lemma ZEQ:
forall a b,
proj_sumbool (
zeq a b) =
true ->
a =
b.
Proof.
intros;
destruct zeq;
auto.
discriminate.
Qed.
Lemma ZLE:
forall a b c d,
zle a b ||
zle c d =
true ->
a <=
b \/
c <=
d.
Proof.
intros;
destruct (
zle a b), (
zle c d);
try congruence;
try omega.
simpl in H;
congruence.
Qed.
Lemma perm_stack_eq':
forall l m b fi j
(
SAP:
stack_agree_perms (
Mem.perm m)
l)
(
PS:
inject_perm_stack j (
Mem.perm m)
l)
(
INBLOCKS:
in_stack'
l (
b,
fi))
o k p,
Mem.perm m b o k p <-> 0 <=
o <
frame_size fi.
Proof.
induction 2; simpl; intros; eauto.
- easy.
- destruct INBLOCKS as [EQ | INSTK]. easy.
eapply IHPS; eauto. red; intros; eapply SAP; eauto. right; eauto.
- destruct INBLOCKS as [EQ | INSTK].
+ red in EQ. simpl in EQ.
red in EQ. rewrite BLOCKS in EQ. destruct EQ as [A|[]]; inv A.
split. 2: apply PERM. eapply SAP. left. reflexivity. reflexivity.
rewrite BLOCKS. left; reflexivity.
+ eapply IHPS; eauto. red; intros; eapply SAP; eauto. right; eauto.
Qed.
Lemma perm_stack_eq:
forall m b fi j
(
PS:
inject_perm_stack j (
Mem.perm m) (
Mem.stack m))
(
INBLOCKS:
in_stack' (
Mem.stack m) (
b,
fi))
o k p,
Mem.perm m b o k p <-> 0 <=
o <
frame_size fi.
Proof.
Lemma size_stack_app:
forall l1 l2,
StackADT.size_stack (
l1 ++
l2) =
StackADT.size_stack l1 +
StackADT.size_stack l2.
Proof.
induction l1; simpl; intros; eauto.
rewrite IHl1. omega.
Qed.
Lemma val_inject_set:
forall j rs1 rs2 r0 r1
(
RINJ:
r0 <>
r1 ->
Val.inject j (
rs1 r0) (
rs2 r0))
v v' (
VINJ:
Val.inject j v v'),
Val.inject j ((
rs1 #
r1 <-
v)
r0) ((
rs2 #
r1 <-
v')
r0).
Proof.
Lemma val_inject_undef_regs:
forall l j rs1 rs2
(
RINJ:
forall r,
Val.inject j (
rs1 r) (
rs2 r))
r,
Val.inject j (
undef_regs l rs1 r) (
undef_regs l rs2 r).
Proof.
induction l;
simpl;
intros;
eauto.
apply IHl.
intros;
apply val_inject_set;
auto.
Qed.
Lemma val_inject_nextinstr:
forall j rs1 rs2 r sz
(
RINJ:
forall r0,
r0 =
r \/
r0 =
PC ->
Val.inject j (
rs1 r0) (
rs2 r0)),
Val.inject j (
nextinstr rs1 sz r) (
nextinstr rs2 sz r).
Proof.
Lemma find_var_info_none_ge:
forall b,
(
Genv.genv_next ge <=
b)%
positive ->
Genv.find_var_info ge b =
None.
Proof.
Lemma load_record_stack_blocks:
forall m fi m',
Mem.record_stack_blocks m fi =
Some m' ->
forall chunk b ofs,
Mem.load chunk m'
b ofs =
Mem.load chunk m b ofs.
Proof.
Lemma size_frames_nil:
size_frames (
None,
nil) = 0.
Proof.
reflexivity.
Qed.
Lemma size_frames_one:
forall f,
size_frames (
Some f ,
nil) =
align (
frame_adt_size f) 8.
Proof.
Opaque Mem.stack_limit.
Lemma in_stack_inj_below:
forall j P l
(
IS:
inject_perm_stack j P l)
b fi
(
INFRAMES:
in_stack'
l (
b,
fi)),
exists l1 l2,
l =
l1 ++
l2 /\
j b =
Some (
bstack,
Mem.stack_limit +
align (
size_chunk Mptr) 8 -
size_active_stack l2).
Proof.
induction 1;
simpl;
intros;
eauto.
easy.
-
destruct INFRAMES as [[]|
INFRAMES].
edestruct IHIS as (
l1 &
l2 &
EQ &
JB);
eauto.
exists ((
None,
r)::
l1),
l2;
split;
auto.
simpl.
subst.
reflexivity.
-
destruct INFRAMES as [
IFR|
INSTACK].
+
red in IFR.
simpl in IFR.
red in IFR.
rewrite BLOCKS in IFR.
destruct IFR as [
EQ|[]].
inv EQ.
rewrite JB.
exists nil, ((
Some fr,
r)::
l).
simpl.
split;
auto.
unfold size_frame.
rewrite SIZE.
f_equal.
f_equal.
omega.
+
edestruct IHIS as (
l1 &
l2 &
EQ &
JB');
eauto.
exists ((
Some fr,
r)::
l1),
l2;
split;
auto.
simpl.
subst.
reflexivity.
Qed.
Lemma size_active_smaller:
forall s,
size_active_stack s <=
size_stack s.
Proof.
Lemma size_active_stack_below:
forall m,
size_active_stack (
Mem.stack m) <
Mem.stack_limit.
Proof.
Lemma size_active_stack_pos:
forall s,
0 <=
size_active_stack s.
Proof.
Lemma size_frame_rew:
forall b fi fr,
size_frame (
make_singleton_frame_adt'
b fi (
frame_size fr)) =
align (
frame_size fr) 8.
Proof.
Lemma align_frame_size_pos:
forall fr,
0 <=
align (
frame_size fr) 8.
Proof.
Lemma size_active_stack_app:
forall l1 l2,
size_active_stack (
l1 ++
l2) =
size_active_stack l1 +
size_active_stack l2.
Proof.
induction l1; simpl; intros; eauto.
rewrite IHl1. omega.
Qed.
Lemma alloc_inject:
forall j ostack m1 (
rs1 rs1':
regset)
fi b m1'
m5 ofs_ra m2 m4 sz,
match_states j (
Ptrofs.unsigned ostack) (
State rs1 m1) (
State rs1'
m1') ->
top_tframe_tc (
Mem.stack m1) ->
Mem.alloc m1 0 (
frame_size fi) = (
m2,
b) ->
Mem.store Mptr m2 b ofs_ra rs1#
RA =
Some m4 ->
Mem.record_stack_blocks m4 (
make_singleton_frame_adt'
b fi (
frame_size fi)) =
Some m5 ->
0 <=
ofs_ra <=
Ptrofs.max_unsigned ->
0 <
frame_size fi ->
let sp :=
Val.offset_ptr (
rs1'
RSP) (
Ptrofs.neg (
Ptrofs.repr (
align (
frame_size fi) 8)))
in
let newostack :=
Ptrofs.unsigned ostack -
align (
frame_size fi) 8
in
let rs2 :=
nextinstr (
rs1 #
RAX <- (
rs1#
RSP) #
RSP <- (
Vptr b Ptrofs.zero))
sz in
let rs2' :=
nextinstr (
rs1' #
RAX <- (
rs1'#
RSP) #
RSP <-
sp)
sz in
exists j',
(
forall bb,
j'
bb =
if peq bb b then Some (
bstack,
newostack)
else j bb)
/\
inject_incr j j'
/\
exists m4',
Mem.storev Mptr m1' (
Val.offset_ptr sp (
Ptrofs.repr ofs_ra))
rs1'#
RA =
Some m4'
/\
match_states j'
newostack (
State rs2 m5) (
State rs2'
m4').
Proof.
intros j ostack m1 rs1 rs1'
fi b m1'
m5 ofs_ra m2 m4 sz
MS TIN ALLOC STORE RSB REPRretaddr sizepos
sp newostack rs2 rs2'.
inv MS.
assert (
RNGframe: 0 <=
align (
frame_size fi) 8 <=
Ptrofs.max_unsigned).
{
split.
apply align_frame_size_pos.
etransitivity. 2:
eapply Z.lt_le_incl,
Z.lt_le_trans.
2:
apply (
size_active_stack_below m5).
repeat rewrite_stack_blocks.
simpl.
rewrite size_frame_rew.
generalize (
size_active_stack_pos r).
intros;
omega.
apply Mem.stack_limit_range.
}
assert (
SP:
sp =
Vptr bstack (
Ptrofs.repr newostack)).
{
unfold sp.
rewrite RSPEQ.
simpl.
f_equal.
rewrite <-
Ptrofs.sub_add_opp.
unfold newostack.
unfold Ptrofs.sub.
rewrite H1.
rewrite Ptrofs.unsigned_repr;
auto.
}
assert (
REPRcur:
align (
frame_size fi) 8 <=
Ptrofs.unsigned ostack0 <=
Ptrofs.max_unsigned).
{
split. 2:
apply Ptrofs.unsigned_range_2.
red in AGSP.
specialize (
AGSP _ RSPEQ).
rewrite AGSP.
apply Z.le_add_le_sub_r.
eapply Z.lt_le_incl,
Z.le_lt_trans.
2:
instantiate (1 :=
size_active_stack (
Mem.stack m5));
generalize (
size_active_stack_below m5) (
align_Mptr_pos);
omega.
repeat rewrite_stack_blocks.
intro.
simpl.
rewrite EQ1.
simpl.
rewrite size_frame_rew.
omega.
}
assert (
REPR: 0 <=
newostack <=
Ptrofs.max_unsigned).
{
unfold newostack.
omega.
}
generalize (
Mem.alloc_left_mapped_inject _ _ _ _ _ _ _ _ _ newostack MINJ ALLOC VB).
intro A.
trim A.
now omega.
trim A.
intros;
right;
eapply PBS;
now eauto.
trim A.
{
intros;
eapply Mem.perm_implies.
eapply PBSL;
eauto.
split.
omega.
unfold newostack.
eapply Z.lt_le_trans with (
Ptrofs.unsigned ostack).
cut (
frame_size fi <=
align (
frame_size fi) 8).
omega.
apply align_le.
omega.
erewrite <-
H1, (
AGSP _ RSPEQ);
eauto.
generalize (
size_active_stack_pos (
Mem.stack m1));
intros.
omega.
simpl in H0.
auto.
}
trim A.
{
red.
intros.
unfold newostack.
eapply Zdivides_trans with 8.
destruct chunk;
try (
exists 8;
reflexivity);
try (
exists 4;
reflexivity);
try (
exists 2;
reflexivity);
try (
exists 1;
reflexivity).
apply Z.divide_sub_r.
rewrite <-
H1.
apply SPAL;
auto.
apply align_divides.
omega.
}
trim A.
{
intros b0 delta'
ofs k p JB PERM RNG.
generalize (
NIB _ _ _ _ _ JB PERM).
generalize (
align_le (
frame_size fi) 8).
unfold newostack in RNG.
simpl in RNG.
omega.
}
trim A.
{
revert NS.
unfold no_stack.
intros (
fr &
fi0 &
rr &
EQS &
BLOCKS &
ZERO &
PUBLIC &
SIZE).
rewrite EQS.
simpl.
intros fi1 [
INFR|
INS];
subst.
-
red in INFR.
simpl in INFR.
red in INFR;
revert INFR.
rewrite <-
BLOCKS.
intros [
EQ|[]].
inv EQ.
intros;
apply PUBLIC.
-
exploit Mem.stack_norepet.
rewrite EQS.
intro ND;
inv ND.
exfalso;
eapply H3. 2:
eapply in_stack'
_in_stack;
apply INS.
red;
simpl.
unfold get_frame_blocks.
rewrite <-
BLOCKS.
left;
reflexivity.
}
destruct A as (
f' &
MINJ' &
INCR &
EQ1 &
EQ2).
exists f'.
split.
{
intros.
destruct peq;
subst;
eauto.
}
split;
auto.
store return address *)
exploit Mem.store_mapped_inject.
apply MINJ'.
simpl in *;
eauto.
eauto.
eapply val_inject_incr;
eauto.
intros (
m4' &
STORE' &
MINJ3).
assert (
Ptrofs.unsigned (
Ptrofs.add (
Ptrofs.repr newostack) (
Ptrofs.repr ofs_ra)) =
ofs_ra +
newostack)
as EQ'.
2:
simpl.
rewrite Ptrofs.add_commut.
erewrite Mem.address_inject;
eauto.
rewrite Ptrofs.unsigned_repr;
omega.
exploit Mem.store_valid_access_3.
exact STORE.
intro VA;
eapply Mem.store_valid_access_1 in VA;
eauto.
destruct VA.
eapply H.
rewrite Ptrofs.unsigned_repr;
generalize (
size_chunk_pos Mptr);
omega.
rewrite SP.
simpl.
unfold Ptrofs.add.
rewrite (
Ptrofs.unsigned_repr _ REPR).
rewrite (
Ptrofs.unsigned_repr _ REPRretaddr)
in *.
rewrite Ptrofs.unsigned_repr.
rewrite Z.add_comm.
rewrite STORE'.
eexists;
split;
eauto.
record the stack block *)
destruct NS as (
frstack &
fstack &
rr &
EQstk &
BLOCKS &
ZERO &
PUB &
SZ).
exploit Mem.record_stack_block_inject_left_zero.
apply MINJ3. 3:
eauto.
repeat rewrite_stack_blocks.
rewrite EQstk.
constructor;
reflexivity.
{
red.
simpl.
intros ?
EQ HPF.
inv EQ.
exists frstack;
split;
auto.
red.
simpl.
constructor;
auto.
simpl.
rewrite EQ1.
intros b2 delta A;
inv A.
rewrite <-
BLOCKS.
simpl.
eexists;
split.
eauto.
constructor.
intros;
eapply stack_perm_le_public.
intros;
apply PUB.
intros;
rewrite SZ.
unfold newostack.
rewrite <-
H1.
red in AGSP.
apply AGSP in RSPEQ.
rewrite RSPEQ.
cut (
frame_size fi <=
align (
frame_size fi) 8).
generalize (
size_active_stack_pos (
Mem.stack m1)).
omega.
apply align_le;
omega.
}
intro MINJ4.
proving the final match_states *)
rewrite <- (
Ptrofs.unsigned_repr newostack)
by omega.
destruct lprog.
{
revert init_sp_ptr.
unfold init_sp.
simpl in STK.
subst.
clear STK.
inv TIN.
simpl.
unfold current_frame_sp;
rewrite H0.
inversion 1.
}
simpl in STK.
assert (
Mem.stack m5 = (
Some (
make_singleton_frame_adt'
b fi (
frame_size fi)),
opt_cons (
fst t) (
snd t)) ::
lprog ++
init_stk
/\
Mem.stack m1 = (
None, (
snd t)) ::
lprog ++
init_stk
).
{
repeat rewrite_stack_blocks.
rewrite STK.
inversion 1;
subst.
simpl.
auto.
}
destruct H as (
STK5 &
STK1).
econstructor.
eauto.
-
rewrite STK5.
rewrite app_comm_cons.
reflexivity.
-
simpl.
reflexivity.
-
unfold rs2.
rewrite nextinstr_rsp,
Pregmap.gss.
eauto.
-
intros r.
unfold rs2,
rs2'.
apply val_inject_nextinstr.
intros.
apply val_inject_set;
eauto.
intro.
apply val_inject_set.
intros;
eauto.
eapply val_inject_incr;
eauto.
subst sp.
simpl.
rewrite RSPEQ.
econstructor;
eauto.
rewrite Ptrofs.add_zero_l;
auto.
unfold newostack.
rewrite <-
Ptrofs.sub_add_opp.
unfold Ptrofs.sub.
rewrite <-
H1.
rewrite Ptrofs.unsigned_repr;
auto.
-
red.
rewnb.
eauto.
-
red.
unfold rs2'.
rewrite nextinstr_rsp.
rewrite Pregmap.gss.
rewrite SP.
inversion 1.
subst.
repeat rewrite_stack_blocks.
rewrite Ptrofs.unsigned_repr by auto.
unfold newostack in *.
rewrite <-
H1.
rewrite (
AGSP _ RSPEQ).
intro EQ0;
rewrite EQ0.
simpl.
rewrite size_frame_rew.
omega.
-
red.
intros ostack1 A.
unfold rs2'
in A.
rewrite nextinstr_rsp in A.
rewrite Pregmap.gss in A.
rewrite SP in A.
inversion A.
subst.
rewrite Ptrofs.unsigned_repr by omega.
unfold newostack.
apply Z.divide_sub_r.
rewrite <-
H1.
apply SPAL.
auto.
apply align_divides.
omega.
-
red.
intros ofs k p PERM.
repeat rewrite_perms_bw PERM.
eauto.
-
red;
intros.
repeat rewrite_perms_fw.
eauto.
-
red.
repeat rewrite_stack_blocks.
exists frstack,
fstack,
rr;
rewrite EQstk, <-
BLOCKS, <-
ZERO.
eauto.
-
unfold rs2'.
rewrite nextinstr_rsp,
Pregmap.gss.
auto.
-
rewrite Ptrofs.unsigned_repr by omega.
red.
intros b0 delta o k p JB PERM.
repeat rewrite_perms_bw PERM.
destruct peq.
*
subst.
rewrite EQ1 in JB.
clear EQstk.
inv JB.
split.
omega.
rewrite STK5.
rewrite in_stack_cons.
rewrite in_frames_cons.
left.
eexists;
split;
eauto.
unfold in_frame;
simpl;
auto.
*
split.
unfold newostack.
transitivity (
Ptrofs.unsigned ostack).
--
generalize (
align_le ((
frame_size fi)) 8).
omega.
--
rewrite <-
H1.
rewrite EQ2 in JB;
auto.
exploit NIB;
eauto.
tauto.
--
rewrite STK5.
rewrite in_stack_cons.
right.
edestruct NIB;
eauto.
rewrite <-
EQ2;
eauto.
rewrite STK1 in H0.
rewrite in_stack_cons in H0.
destruct H0;
auto.
easy.
-
rewrite STK5.
rewrite STK1 in IS.
inv IS.
econstructor;
try reflexivity;
eauto.
eapply inject_stack_incr;
eauto.
eapply inject_stack_more_perm with (
P:=
Mem.perm m1).
intros;
repeat rewrite_perms.
exploit Mem.perm_valid_block;
eauto.
intro VB'.
generalize (
Mem.fresh_block_alloc _ _ _ _ _ ALLOC).
destr.
auto.
rewrite EQ1.
f_equal.
f_equal.
unfold newostack.
rewrite <-
H1.
rewrite AGSP.
rewrite STK1.
simpl.
omega.
auto.
simpl.
rewrite Z.max_r;
auto.
omega.
intros.
repeat rewrite_perms.
destr.
-
intros b0 fi0 delta INSTK FB0 b'
o delta'
k p FB1 P1.
revert INSTK.
rewrite STK5.
intro INSTK.
simpl in INSTK.
repeat rewrite_perms_bw P1.
destruct INSTK as [
IFR|
INSTK].
+
red in IFR.
simpl in IFR.
red in IFR.
simpl in IFR.
destruct IFR as [
EQ|[]].
inv EQ.
rewrite FB0 in EQ1;
inv EQ1.
destr_in P1.
*
subst.
rewrite FB0 in FB1;
inv FB1.
omega.
*
rewrite EQ2 in FB1 by auto.
eapply NIB in P1;
eauto.
destruct P1 as (
LE &
IN).
unfold newostack.
rewrite <-
H1.
omega.
+
assert (
b0 <>
b).
intro;
subst.
exploit Mem.stack_norepet.
rewrite STK5.
intro ND;
inv ND.
eapply in_stack'
_in_stack in INSTK;
eauto.
eapply H3 in INSTK;
eauto.
left.
reflexivity.
rewrite EQ2 in FB0 by auto.
intro RNG.
assert (0 <
frame_size fi0).
destruct (
zlt 0 (
frame_size fi0));
auto.
assert (
frame_size fi0 = 0).
generalize (
frame_size_pos fi0);
omega.
rewrite H0 in RNG.
change (
align 0 8)
with 0
in RNG.
omega.
destr_in P1.
*
subst.
rewrite EQ1 in FB1;
inv FB1.
cut (
newostack + (
frame_size fi) <=
delta).
omega.
unfold newostack.
rewrite <-
H1.
rewrite AGSP;
auto.
rewrite STK1 in IS.
inv IS.
eapply in_stack_inj_below in INSTK;
eauto.
destruct INSTK as (
l1 &
l2 &
EQADT &
JB0).
rewrite FB0 in JB0.
inv JB0.
rewrite STK1.
simpl.
rewrite EQADT.
rewrite size_active_stack_app.
generalize (
size_active_stack_pos l1).
cut (
frame_size fi <=
align (
frame_size fi) 8).
omega.
apply align_le;
omega.
*
eapply IP.
rewrite STK1.
right.
eauto.
eauto.
rewrite <-
EQ2.
apply FB1.
auto.
eauto.
omega.
-
eauto.
-
eauto.
-
destruct GLOBSYMB_INJ;
split.
+
intros.
eapply INCR.
eauto.
+
intros.
destruct (
peq b1 b).
subst;
rewrite EQ1 in H2.
clear EQstk.
inv H2.
simpl.
unfold Genv.block_is_volatile.
unfold Genv.find_var_info.
replace (
Genv.find_def ge bstack)
with (
None (
A:=
globdef Asm.fundef unit)).
replace (
Genv.find_def ge b)
with (
None (
A:=
globdef Asm.fundef unit)).
auto.
unfold Genv.find_def.
destruct (
Maps.PTree.get b (
Genv.genv_defs ge))
eqn:
EQdef;
auto.
apply Genv.genv_defs_range in EQdef.
exploit Mem.fresh_block_alloc.
eauto.
red.
xomega.
easy.
unfold Genv.find_def.
destruct (
Maps.PTree.get bstack (
Genv.genv_defs ge))
eqn:
EQdef;
auto.
apply Genv.genv_defs_range in EQdef.
unfold bstack in EQdef.
xomega.
rewrite EQ2 in H2.
eauto.
auto.
-
intros.
destruct (
j b1)
eqn:
JB1.
destruct p.
exploit INCR.
apply JB1.
rewrite H0.
intro A;
inv A.
eauto.
destruct (
peq b b1).
subst.
rewrite EQ1 in H0;
inv H0.
unfold bstack in H.
xomega.
rewrite EQ2 in H0;
eauto.
-
erewrite Mem.record_stack_block_nextblock. 2:
eauto.
erewrite Mem.nextblock_store. 2 :
eauto.
erewrite Mem.nextblock_alloc. 2:
eauto.
xomega.
-
erewrite Mem.nextblock_store. 2 :
eauto.
xomega.
-
rewrite STK5.
simpl.
right.
rewrite STK1 in SPinstack.
destruct SPinstack;
auto.
easy.
-
rewrite Z.add_comm, <-
EQ'.
apply Ptrofs.unsigned_range_2.
Qed.
Lemma max_l_divide l: (8 |
max_l (
map size_frame l)).
Proof.
Lemma opt_size_frame_divides f:
(8 |
opt_size_frame f).
Proof.
destruct f.
apply align_divides.
omega.
exists 0;
simpl;
omega.
Qed.
Lemma size_frames_divides f:
(8 |
size_frames f).
Proof.
Lemma size_stack_divides l:
(8 |
size_stack l).
Proof.
Lemma size_active_stack_divides l:
(8 |
size_active_stack l).
Proof.
Lemma inject_stack_init_sp:
forall j P l,
inject_perm_stack j P l ->
forall b,
in_stack l b ->
exists o,
j b =
Some (
bstack,
o).
Proof.
induction 1;
simpl;
intros bb INS.
easy.
rewrite in_stack_cons in INS.
destruct INS as [
INF|
INS].
easy.
eauto.
rewrite in_stack_cons in INS.
destruct INS as [
INF|
INS].
rewrite in_frames_cons in INF.
destruct INF as (
f1 &
EQ &
IFR);
inv EQ.
edestruct in_frame_info as (
ffi &
IFRR).
eauto.
rewrite BLOCKS in IFRR.
destruct IFRR as [
IFRR|[]].
inv IFRR.
eauto.
eauto.
Qed.
Lemma init_sp_inj:
forall j P l,
inject_perm_stack j P l ->
in_stack l binit_sp ->
exists o,
Val.inject j init_sp (
Vptr bstack o).
Proof.
Ltac use_ains :=
repeat match goal with
|
AINS:
asm_instr_no_stack ?
i,
UNC:
stack_invar ?
i =
true,
EI:
Asm.exec_instr ?
init_stk _ _ ?
i _ ?
m1 =
Next _ ?
m2 |-
context [
Mem.stack ?
m2] =>
let AINS_stack :=
fresh "
AINS_stack"
in
edestruct (
AINS UNC _ _ _ _ _ _ _ EI)
as (
AINS_stack &
_);
rewrite !
AINS_stack;
clear AINS_stack
|
AINS:
asm_instr_no_stack ?
i,
UNC:
stack_invar ?
i =
true,
EI:
Asm.exec_instr ?
init_stk _ _ ?
i _ ?
m1 =
Next _ ?
m2,
H:
context [
Mem.stack ?
m2] |-
_ =>
let AINS_stack :=
fresh "
AINS_stack"
in
edestruct (
AINS UNC _ _ _ _ _ _ _ EI)
as (
AINS_stack &
_);
rewrite !
AINS_stack in H;
clear AINS_stack
|
AINS:
asm_instr_no_stack ?
i,
UNC:
stack_invar ?
i =
true,
EI:
Asm.exec_instr ?
init_stk _ _ ?
i _ ?
m1 =
Next _ ?
m2 |-
context [
Mem.perm ?
m2 _ _ _ _] =>
let AINS_perm :=
fresh "
AINS_perm"
in
edestruct (
AINS UNC _ _ _ _ _ _ _ EI)
as (
_ &
AINS_perm);
rewrite !
AINS_perm;
clear AINS_perm
|
AINS:
asm_instr_no_stack ?
i,
UNC:
stack_invar ?
i =
true,
EI:
Asm.exec_instr ?
init_stk _ _ ?
i _ ?
m1 =
Next _ ?
m2,
H :
context [
Mem.perm ?
m2 _ _ _ _] |-
_ =>
let AINS_perm :=
fresh "
AINS_perm"
in
edestruct (
AINS UNC _ _ _ _ _ _ _ EI)
as (
_ &
AINS_perm);
rewrite !
AINS_perm in H;
clear AINS_perm
|
AINR:
asm_instr_no_rsp ?
i,
UNC:
stack_invar ?
i =
true,
EI:
Asm.exec_instr ?
init_stk _ _ ?
i ?
rs1 _ =
Next ?
rs2 _ |-
context [?
rs2 (
IR RSP)] =>
rewrite (
AINR UNC _ _ _ _ _ _ _ EI)
|
AINR:
asm_instr_no_rsp ?
i,
UNC:
stack_invar ?
i =
true,
EI:
Asm.exec_instr ?
init_stk _ _ ?
i ?
rs1 _ =
Next ?
rs2 _,
H:
context [?
rs2 (
IR RSP)] |-
_ =>
rewrite (
AINR UNC _ _ _ _ _ _ _ EI)
in H
end.
Lemma is_unchanged_stack_invar:
forall i,
is_unchanged i =
true ->
stack_invar i =
true.
Proof.
intros. destruct i eqn:?; simpl in *; try congruence.
Qed.
Lemma zle_zlt:
forall lo hi o,
zle lo o &&
zlt o hi =
true <->
lo <=
o <
hi.
Proof.
intros.
destruct (
zle lo o), (
zlt o hi);
intuition;
try congruence;
try omega.
Qed.
Lemma max_align:
forall x, 0 <=
x ->
Z.max 0 (
align x 8) =
align (
Z.max 0
x) 8.
Proof.
intros.
rewrite !
Z.max_r;
auto.
etransitivity. 2:
apply align_le.
auto.
omega.
Qed.
Lemma mod_divides:
forall a b c,
c <> 0 ->
(
a |
c) ->
(
a |
b) ->
(
a |
b mod c).
Proof.
Lemma ra_after_call_inj:
forall j ostack rs1 m1 rs2 m2,
match_states j ostack (
State rs1 m1) (
State rs2 m2) ->
ra_after_call ge (
rs1 RA) ->
ra_after_call ge (
rs2 RA).
Proof.
red.
intros j ostack rs1 m1 rs2 m2 MS (
RAU &
IAC).
inv MS.
generalize (
RINJ RA).
intro RAINJ.
split.
inv RAINJ;
try congruence.
intros b o RA2 f0 FFP.
rewrite RA2 in RAINJ.
inv RAINJ;
try congruence.
assert (
b1 =
b ).
eapply GlobInjInv in H2;
eauto.
unfold Genv.find_funct_ptr in FFP;
destr_in FFP.
eapply Genv.genv_defs_range.
eauto.
subst.
erewrite GLOBFUN_INJ in H2;
eauto.
inv H2.
specialize (
IAC _ _ (
eq_sym H)
_ FFP).
rewrite Ptrofs.add_zero.
auto.
Qed.
Lemma eval_ros_match:
forall j ostack rs1 m1 rs2 m2
(
MS :
match_states j ostack (
State rs1 m1) (
State rs2 m2))
ros,
Val.inject j (
eval_ros ge ros rs1) (
eval_ros ge ros rs2).
Proof.
intros.
inv MS.
unfold eval_ros.
destr.
-
generalize (
RINJ i).
intro A;
inv A;
try congruence;
auto.
econstructor;
eauto.
-
unfold Genv.symbol_address.
destr;
auto.
econstructor;
eauto.
destruct GLOBSYMB_INJ.
eapply e;
eauto.
reflexivity.
Qed.
Lemma exec_instr_inject':
forall j ostack m1 m2 rs1 rs2 f i rs1'
m1'
(
MS:
match_states j ostack (
State rs1 m1) (
State rs2 m2))
(
AINR:
asm_instr_no_rsp i)
(
AINS:
asm_instr_no_stack i)
(
EI:
Asm.exec_instr init_stk ge f i rs1 m1 =
Next rs1'
m1'),
exists j'
ostack'
rs2'
m2',
exec_instr ge f i rs2 m2 =
Next rs2'
m2'
/\
match_states j'
ostack' (
State rs1'
m1') (
State rs2'
m2')
/\
inject_incr j j'.
Proof.
intros.
destruct (
is_unchanged i)
eqn:
ISUNCH.
-
inversion MS.
edestruct exec_instr_inject as (
rs2' &
m2' &
EXEC' &
MINJ' &
RINJ');
eauto.
exists j,
ostack,
rs2',
m2';
split; [|
split];
eauto.
destruct i;
simpl in *;
eauto;
try congruence.
generalize (
is_unchanged_stack_invar _ ISUNCH)
as SINVAR.
intro.
subst.
eapply match_states_intro;
eauto;
try now ((
intros;
use_ains;
eauto) || (
red;
intros;
use_ains;
eauto)).
+
eapply asmgen_nextblock_forward in EXEC'.
red in VB |- *.
xomega.
+
use_ains.
eapply perm_stack_inv.
eauto.
intros;
use_ains.
tauto.
+
etransitivity.
apply GlobLe.
eapply asmgen_nextblock_forward;
eauto.
+
etransitivity.
apply GlobLeT.
eapply asmgen_nextblock_forward;
eauto.
-
destruct i;
simpl in *;
try congruence.
+
destr_in EI.
inv EI.
generalize (
eval_ros_match _ _ _ _ _ _ MS ros).
inv MS.
intro INJ;
revert Heqo;
inv INJ;
simpl;
try congruence.
destr.
subst.
intros;
erewrite GLOBFUN_INJ in H1;
eauto.
inv H1.
rewrite pred_dec_true,
Heqo. 2:
reflexivity.
do 4
eexists.
split.
eauto.
split.
econstructor;
eauto.
*
instantiate (1:=
_::
_).
simpl.
eapply Mem.inject_push_new_stage_left;
eauto.
*
rewrite_stack_blocks.
rewrite STK.
simpl.
reflexivity.
*
intros;
apply val_inject_set;
auto.
intros;
apply val_inject_set;
auto.
apply Val.offset_ptr_inject;
auto.
destruct GLOBSYMB_INJ.
econstructor;
eauto.
*
red.
rewrite_stack_blocks.
simpl.
repeat rewrite Pregmap.gso by congruence.
rewrite Z.add_0_r.
eauto.
*
red.
intros bb delta o k p.
rewrite_perms.
rewrite_stack_blocks.
rewrite in_stack_cons.
intros.
exploit NIB;
eauto.
tauto.
*
rewrite_stack_blocks.
constructor.
eapply inject_stack_more_perm. 2:
eauto.
intros.
rewrite_perms.
auto.
*
red.
rewrite_stack_blocks.
simpl.
intros bb fi delta INS JB b'
o delta'
k p.
rewrite_perms.
eapply IP;
eauto.
tauto.
*
rewnb.
auto.
*
rewrite_stack_blocks.
simpl;
auto.
*
red.
auto.
+
unfold Asm.exec_instr in EI.
simpl in EI.
repeat destr_in EI.
rewrite pred_dec_true.
eexists j,
ostack,
_,
_;
split;
eauto.
split;
auto.
inv MS.
assert (
exists f rprog,
lprog =
f ::
rprog).
{
inv t.
rewrite <-
H in IS.
destruct lprog.
exfalso.
revert init_sp_ptr;
unfold init_sp;
simpl in STK;
rewrite <-
STK.
rewrite <-
H.
simpl.
unfold current_frame_sp.
rewrite H0.
inversion 1.
eauto.
}
destruct H as (
ff &
rprog &
EQ).
subst.
simpl in MINJ.
econstructor;
eauto.
*
eapply Mem.unrecord_stack_block_inject_left_zero;
eauto.
red.
inv t.
constructor.
unfold in_frames;
rewrite H0.
easy.
omega.
*
rewrite_stack_blocks.
rewrite STK.
simpl.
eauto.
*
simpl;
intros.
apply val_inject_set;
auto.
intros;
apply val_inject_set;
auto.
*
red.
repeat rewrite Pregmap.gso by congruence.
rewrite_stack_blocks.
inv t.
rewrite EQ in H;
inv H.
simpl.
intros;
erewrite AGSP;
eauto.
rewrite EQ.
simpl.
rewrite H0.
simpl.
omega.
*
red;
intros.
rewrite_stack_blocks.
revert EQ.
inv t.
inversion 1;
subst.
simpl.
red in NIB.
rewrite <-
H1 in NIB.
revert H0.
rewrite_perms.
intro.
exploit NIB;
eauto.
rewrite in_stack_cons;
unfold in_frames;
rewrite H2.
simpl.
tauto.
*
rewrite_stack_blocks.
revert EQ.
inv t.
inversion 1;
subst.
simpl.
rewrite <-
H in IS.
inv IS.
eapply inject_stack_more_perm. 2:
eauto.
intros;
rewrite_perms.
auto.
inv H0.
*
red.
rewrite_stack_blocks.
revert EQ.
inv t.
inversion 1;
subst.
simpl.
red in IP.
rewrite <-
H in IP.
intros.
revert H4;
rewrite_perms.
eapply IP;
eauto.
right.
auto.
*
rewnb.
auto.
*
rewrite_stack_blocks.
revert EQ.
inv t.
inversion 1;
subst.
rewrite <-
H in SPinstack.
simpl.
simpl in SPinstack.
destruct SPinstack.
red in H1.
rewrite H0 in H1;
easy.
auto.
*
eapply ra_after_call_inj;
eauto.
+
clear ISUNCH.
unfold Asm.exec_instr in EI;
simpl in EI.
repeat destr_in EI.
inversion MS;
subst.
assert (
SZ:
sz =
frame_size f0 /\ 0 <
sz).
{
unfold frame_info_of_size_and_pubrange in Heqo;
repeat destr_in Heqo.
split.
reflexivity.
auto.
}
destruct SZ;
subst.
edestruct alloc_inject as (
j' &
JSPEC &
INCR &
m4' &
STORE2 &
MS') ;
eauto.
apply Ptrofs.unsigned_range_2.
simpl in *.
rewrite Ptrofs.repr_unsigned in STORE2.
setoid_rewrite STORE2.
eexists j',
_,
_,
_;
split;
eauto.
+
unfold Asm.exec_instr in EI;
simpl in EI.
repeat (
destr_in EI; [
idtac]).
clear ISUNCH.
rename Heqv0 into RS1RSP.
rename Heqo into LOADRA.
rename Heqb0 into CHECKFRAME.
rename Heqo0 into FREE.
rename Heqo1 into UNRECORD.
rename Heqo2 into ISDEF.
inv MS.
rewrite RS1RSP in RSPzero.
destruct RSPzero as [
bb EQ];
inv EQ.
exploit Mem.loadbytesv_inject. 3:
apply LOADRA.
eauto.
apply Val.offset_ptr_inject.
rewrite <-
RS1RSP;
auto.
intros (
ra' &
LOADRA' &
INJra).
rewrite LOADRA'.
unfold check_top_frame in CHECKFRAME.
repeat destr_in CHECKFRAME.
repeat destr_in AGSP1. *)
repeat rewrite andb_true_iff in H0.
destruct H0 as (
A &
B).
destruct Forall_dec;
simpl in A;
try congruence.
clear A.
apply ZEQ in B.
set (
newostack :=
Ptrofs.unsigned ostack0 +
align ((
frame_adt_size f0)) 8).
assert (
RNGframe: 0 <=
align (
frame_adt_size f0) 8 <
Ptrofs.max_unsigned).
{
generalize (
size_active_stack_below m1).
generalize (
size_active_stack_pos (
Mem.stack m1)).
rewrite Heqs.
generalize (
size_active_stack_pos s).
generalize (
Mem.stack_limit_range).
simpl.
unfold size_frame.
split.
apply size_frame_pos.
omega.
}
exploit Mem.free_left_inject.
apply MINJ.
eauto.
intro MINJ'.
exploit Mem.tailcall_stage_inject_left.
apply MINJ'.
eauto.
intros INJ.
exists j,
newostack;
eexists;
eexists;
split; [|
split];
eauto.
generalize (
RINJ RSP).
rewrite RS1RSP.
inversion 1
as [
ff|
ff|
ff|
ff|? ? ? ? ?
INJB ?
x EQRSP|
ff];
subst.
symmetry in EQRSP.
rewrite Ptrofs.add_zero_l in *.
inversion IS.
subst.
rewrite BLOCKS in f1.
inv f1.
red in H2;
simpl in H2;
destruct H2 as [?
_];
subst.
clear H3.
rewrite JB in INJB;
inv INJB.
specialize (
AGSP _ EQRSP).
specialize (
SPAL _ EQRSP).
rewrite EQRSP in RSPEQ.
inv RSPEQ.
assert (0 <=
Mem.stack_limit +
align (
size_chunk Mptr) 8 -
size_active_stack (
Mem.stack m1') <=
Ptrofs.max_unsigned)
as RNGnewofs.
{
generalize (
size_active_stack_below m1').
generalize (
size_active_stack_pos (
Mem.stack m1')).
generalize (
Mem.stack_limit_range)
Mem.stack_limit_range'.
generalize align_Mptr_pos.
intros;
omega.
}
assert (0 <=
newostack <=
Ptrofs.max_unsigned)
as RNGnew.
{
unfold newostack.
rewrite AGSP.
rewrite Heqs.
simpl.
revert RNGnewofs.
repeat rewrite_stack_blocks.
simpl.
rewrite Heqs.
inversion 1;
subst.
unfold size_frame.
intros;
omega.
}
rewrite <- (
Ptrofs.unsigned_repr newostack)
by omega.
destruct lprog.
{
simpl in STK.
revert init_sp_ptr;
unfold init_sp;
simpl in STK;
rewrite <-
STK.
simpl.
unfold current_frame_sp.
simpl.
repeat destr.
inv BLOCKS.
red in c.
simpl in c.
revert c.
unfold current_frame_sp.
simpl.
rewrite Heql0.
repeat rewrite_stack_blocks.
rewrite in_stack_cons.
rewrite Heqs.
inversion 1.
subst s f1.
intros [[]|
INS].
inversion 1.
subst b.
exploit Mem.stack_norepet;
rewrite Heqs.
clear STK.
intro ND;
inv ND.
edestruct (
H4 binit_sp).
red.
simpl.
eapply in_frame'
_in_frame.
red;
rewrite Heql0.
left;
reflexivity.
eauto.
}
eapply match_states_intro with (
lprog := (
None,
f0::
l) ::
lprog );
eauto.
*
repeat rewrite_stack_blocks.
rewrite Heqs.
simpl.
inversion 1;
subst.
inv STK.
simpl.
reflexivity.
*
rewrite nextinstr_rsp.
rewrite Pregmap.gso by congruence.
rewrite Pregmap.gss.
simpl in ISDEF.
unfold Mem.is_ptr in ISDEF.
destr_in ISDEF.
inv ISDEF.
unfold current_sp,
current_frame_sp in Heqv1.
revert Heqv1.
repeat destr;
inversion 1.
eauto.
*
intros;
apply val_inject_nextinstr.
intros;
apply val_inject_set;
auto.
intros;
apply val_inject_set;
auto.
assert (
v0 =
parent_sp (
Mem.stack m1)).
revert ISDEF.
rewrite Heqs.
simpl.
unfold Mem.is_ptr.
destr.
simpl.
revert ISDEF.
simpl.
unfold Mem.is_ptr.
destr.
inversion 1;
subst.
inv ISDEF.
inv IPS_REC.
--
simpl in Heqv1.
inv Heqv1.
--
simpl in Heqv1.
inv Heqv1.
--
simpl in Heqv1.
unfold current_frame_sp in Heqv1;
simpl in Heqv1.
rewrite BLOCKS0 in Heqv1.
inv Heqv1.
econstructor.
eauto.
rewrite Ptrofs.add_zero_l.
rewrite Ptrofs.add_unsigned.
f_equal.
setoid_rewrite Ptrofs.unsigned_repr.
simpl.
unfold size_frame;
rewrite SIZE0,
SIZE.
rewrite Z.max_r by (
apply frame_size_pos).
omega.
generalize (
size_active_stack_below m1).
generalize (
size_active_stack_pos (
Mem.stack m1)).
generalize (
Mem.stack_limit_range')
align_Mptr_pos.
rewrite Heqs.
simpl.
unfold size_frame.
rewrite SIZE,
SIZE0.
generalize Mem.stack_limit_range.
intros;
omega.
rewrite Z.max_r by apply frame_adt_size_pos.
omega.
*
red.
rewrite nextinstr_rsp.
rewrite !
Pregmap.gso by congruence.
rewrite Pregmap.gss.
simpl.
inversion 1;
subst.
repeat rewrite_stack_blocks.
rewrite Ptrofs.add_unsigned.
rewrite AGSP.
rewrite Heqs.
simpl.
inversion 1.
subst.
rewrite Z.max_r by apply frame_adt_size_pos.
unfold size_frame.
rewrite Ptrofs.unsigned_repr.
rewrite Ptrofs.unsigned_repr by omega.
omega.
rewrite Ptrofs.unsigned_repr by omega.
generalize (
size_active_stack_below m1).
rewrite Heqs.
simpl.
generalize (
size_active_stack_pos r).
generalize Mem.stack_limit_range Mem.stack_limit_range'
align_Mptr_pos.
unfold size_frame.
intros.
omega.
*
red.
rewrite nextinstr_rsp.
rewrite !
Pregmap.gso by congruence.
rewrite Pregmap.gss.
simpl.
inversion 1.
subst.
clear H0.
rewrite Ptrofs.add_unsigned.
rewrite Ptrofs.unsigned_repr_eq.
rewrite AGSP.
rewrite Z.max_r by apply frame_adt_size_pos.
rewrite Ptrofs.unsigned_repr by omega.
apply mod_divides.
vm_compute.
congruence.
rewrite Ptrofs.modulus_power.
exists (
two_p (
Ptrofs.zwordsize - 3)).
change 8
with (
two_p 3).
rewrite <-
two_p_is_exp.
f_equal.
vm_compute.
congruence.
omega.
apply Z.divide_add_r.
apply Z.divide_sub_r.
apply Z.divide_add_r.
apply Mem.stack_limit_aligned.
apply align_divides.
omega.
apply size_active_stack_divides.
apply align_divides.
omega.
*
rewrite nextinstr_rsp.
rewrite !
Pregmap.gso by congruence.
rewrite Pregmap.gss.
f_equal.
unfold newostack.
simpl.
rewrite Z.max_r.
rewrite Ptrofs.add_unsigned.
rewrite AGSP.
rewrite Ptrofs.unsigned_repr by omega.
reflexivity.
apply frame_adt_size_pos.
*
red.
intros b'
delta0 o k p JB0.
repeat rewrite_perms.
destr.
intro PERMS.
generalize (
NIB b'
delta0 o k p JB0 PERMS).
intros (
LE &
INS).
destruct (
peq b b').
--
subst.
rewrite perm_stack_eq in PERMS;
eauto.
2:
rewrite Heqs;
econstructor;
eauto.
2:
rewrite Heqs. 2:
left. 2:
red;
simpl. 2:
red;
rewrite BLOCKS;
left;
reflexivity.
rewrite <-
SIZE in PERMS.
apply zle_zlt in PERMS.
rewrite <-
andb_assoc in Heqb0.
rewrite PERMS in Heqb0.
inv Heqb0.
--
repeat rewrite_stack_blocks.
rewrite Heqs.
simpl.
rewrite Heqs in INS.
rewrite in_stack_cons in INS.
destruct INS.
red in H0.
simpl in H0.
unfold get_frame_blocks in H0.
rewrite BLOCKS in H0.
simpl in H0.
destruct H0;[|
easy].
subst.
intuition.
rewrite in_stack_cons.
split;
auto.
rewrite Ptrofs.unsigned_repr by omega.
unfold newostack.
rewrite SIZE.
destruct (
zle (
Ptrofs.unsigned (
Ptrofs.repr (
Mem.stack_limit +
align (
size_chunk Mptr) 8 -
size_active_stack s -
align ((
frame_size fi)) 8)) +
align ((
frame_size fi)) 8) (
o +
delta0));
auto.
exfalso.
apply Z.gt_lt in g.
rewrite AGSP in LE,
g.
assert (
max_perm:
forall m b o k p,
Mem.perm m b o k p ->
Mem.perm m b o Max Nonempty).
{
intros.
eapply Mem.perm_implies.
eapply Mem.perm_max.
eauto.
constructor.
}
generalize (
Mem.free_range_perm _ _ _ _ _ FREE).
intro FP.
assert (
LT: 0 <
frame_size fi).
{
destruct (
zlt 0 (
frame_size fi));
auto.
assert (
frame_size fi = 0).
generalize (
frame_size_pos fi);
omega.
rewrite H2 in g.
change (
align 0 8)
with 0
in g.
omega.
}
revert LE g.
rewrite Heqs.
simpl.
inv H1.
unfold size_frame.
rewrite SIZE.
rewrite Z.sub_add_distr.
intros.
set (
delta :=
Mem.stack_limit +
align (
size_chunk Mptr) 8 -
size_active_stack r -
align ((
frame_size fi)) 8)
in *.
destruct (
zlt (
o +
delta0) (
delta +
frame_size fi)).
++
assert (
DISJ:
forall ofs ,
Mem.perm m1 b ofs Cur Freeable ->
bstack <>
bstack \/
o +
delta0 <>
ofs +
delta).
intros;
eapply Mem.mi_no_overlap.
apply MINJ.
apply not_eq_sym.
apply n.
auto.
auto.
eapply max_perm;
eauto.
eapply max_perm;
eauto.
assert (
exists o2, 0 <=
o2 <
frame_size fi /\
o +
delta0 =
o2 +
delta)
as EX.
{
exists (
o +
delta0 -
delta).
omega.
}
destruct EX as (
o2 &
RNG &
EQ').
edestruct DISJ;
eauto.
++
assert (
delta +
frame_size fi <=
o +
delta0 <
delta +
align (
frame_size fi) 8).
omega.
assert (
exists o2,
frame_size fi <=
o2 <
align (
frame_size fi) 8 /\
o +
delta0 =
o2 +
delta)
as EX.
{
exists (
o +
delta0 -
delta).
omega.
}
destruct EX as (
o2 &
RNG &
EQ').
eapply IP. 4:
apply PERMS. 3:
eauto. 2:
apply JB.
rewrite Heqs.
left.
red.
simpl.
red;
rewrite BLOCKS.
left;
reflexivity.
omega.
++
intuition congruence.
*
repeat rewrite_stack_blocks.
rewrite Heqs.
simpl.
inversion 1.
subst.
constructor.
eapply perm_stack_inv.
eauto.
intros.
repeat rewrite_perms.
destr.
repeat rewrite andb_true_iff in Heqb1.
destruct Heqb1 as ((
A &
B) &
C).
destruct (
peq b b0);
simpl in *;
try congruence.
subst.
exploit Mem.stack_norepet.
rewrite Heqs.
intro ND;
inv ND.
eapply H5 in H0;
eauto.
*
red.
intros b0 fi0 delta'
INSTK JB0 b2 o delta2 k p JB2 PERMS.
revert INSTK.
repeat rewrite_stack_blocks.
rewrite Heqs.
inversion 1;
subst.
simpl.
intros [[]|
INSTK].
eapply IP with (
k:=
k) (
p:=
p);
eauto.
rewrite Heqs.
simpl.
right;
eauto.
revert PERMS.
repeat rewrite_perms.
destr.
*
rewnb.
xomega.
*
repeat rewrite_stack_blocks.
rewrite Heqs.
simpl.
auto.
inversion 1;
subst.
simpl in SPinstack.
unfold current_frame_sp in SPinstack.
simpl in SPinstack.
destruct SPinstack;
auto.
simpl.
right.
red in H0.
simpl in H0.
red in H0.
rewrite BLOCKS in H0.
destruct H0 as [
IFR|[]].
inv IFR.
red in c.
revert c.
rewrite EQ2.
unfold Asm.init_sp.
revert init_sp_ptr.
unfold init_sp.
intro A;
rewrite A.
rewrite in_stack_cons.
intros [[]|
INS].
exploit Mem.stack_norepet.
rewrite Heqs.
intro ND;
exfalso;
inv ND.
apply (
H3 binit_sp).
red;
simpl.
eapply in_frame'
_in_frame;
eauto.
red;
rewrite BLOCKS;
left;
eauto.
auto.
+
unfold Asm.exec_instr in EI;
simpl in EI.
unfold check_top_frame in EI.
destruct (
Mem.stack m1)
eqn:
S1;
try congruence.
repeat destr_in EI.
repeat destr_in Heqb.
apply andb_true_iff in H0;
destruct H0 as (
A &
B).
apply ZEQ in B.
subst.
destruct Forall_dec;
simpl in A;
try congruence.
clear A.
assert (
RNGframe: 0 <=
align (
frame_adt_size f0) 8 <
Ptrofs.max_unsigned).
{
generalize (
size_active_stack_below m1').
generalize (
size_active_stack_pos (
Mem.stack m1')).
rewrite S1.
generalize (
Mem.stack_limit_range).
generalize (
frame_adt_size_pos f0) (
align_le (
frame_adt_size f0) 8) (
size_stack_pos s).
generalize (
size_active_stack_pos s).
simpl.
unfold size_frame.
split.
omega.
omega.
}
exists j,
ostack;
eexists;
eexists;
split.
eauto.
split;
auto.
inversion MS;
subst;
econstructor;
eauto.
*
rewrite nextinstr_rsp.
destruct (
preg_eq RSP rd).
rewrite e.
rewrite Pregmap.gss.
congruence.
rewrite Pregmap.gso.
eauto.
auto.
*
intros;
apply val_inject_nextinstr.
intros;
apply val_inject_set;
auto.
rewrite S1 in *.
simpl in Heqo.
unfold Mem.is_ptr in Heqo;
destr_in Heqo.
inv Heqo.
inv IS.
rewrite <-
Heqv0.
unfold current_sp.
destr.
inv Heqv0.
inv IPS_REC.
inv Heqv0.
simpl in *.
repeat destr_in Heqv0.
inv BLOCKS0.
rewrite RSPEQ.
simpl.
unfold current_frame_sp.
simpl.
rewrite H2.
econstructor;
eauto.
rewrite Ptrofs.add_zero_l.
rewrite Ptrofs.add_unsigned.
rewrite AGSP.
rewrite S1.
simpl.
simpl.
unfold size_frame.
rewrite <-
SIZE0.
repeat rewrite Z.max_r by (
apply frame_adt_size_pos).
f_equal.
rewrite Ptrofs.unsigned_repr.
omega.
omega.
auto.
*
red.
rewrite nextinstr_rsp.
rewrite Pregmap.gso;
eauto.
*
red.
rewrite nextinstr_rsp.
rewrite Pregmap.gso;
eauto.
*
rewrite nextinstr_rsp.
rewrite Pregmap.gso;
eauto.
Unshelve.
apply nil.
Qed.
Definition asm_prog_no_rsp (
ge:
Genv.t Asm.fundef unit):=
forall b f,
Genv.find_funct_ptr ge b =
Some (
Internal f) ->
asm_code_no_rsp (
fn_code f).
Hypothesis prog_no_rsp:
asm_prog_no_rsp ge.
Context `{
ecprops: !
ExternalCallsProps mem}.
Lemma inj_incr_sep_same:
forall j j'
m1 m2 b1 b2 delta,
inject_incr j j' ->
inject_separated j j'
m1 m2 ->
j'
b1 =
Some (
b2,
delta) ->
Mem.valid_block m2 b2 ->
j b1 =
Some (
b2,
delta).
Proof.
intros.
destruct (j b1) eqn:JB.
destruct p. eapply H in JB; eauto.
congruence.
exploit H0; eauto. intuition congruence.
Qed.
Lemma set_res_no_rsp:
forall res vres rs,
no_rsp_builtin_preg res ->
set_res res vres rs RSP =
rs RSP.
Proof.
induction res;
simpl.
-
intros.
eapply Pregmap.gso.
auto.
-
auto.
-
intros vres rs (
NR1 &
NR2).
rewrite IHres2;
auto.
Qed.
Lemma val_inject_set_res:
forall r rs1 rs2 v1 v2 j,
Val.inject j v1 v2 ->
(
forall r0,
Val.inject j (
rs1 r0) (
rs2 r0)) ->
forall r0,
Val.inject j (
set_res r v1 rs1 r0) (
set_res r v2 rs2 r0).
Proof.
Definition init_data_diff (
id:
init_data) (
i:
ident) :=
match id with
Init_addrof ii _ =>
ii <>
i
|
_ =>
True
end.
Lemma store_init_data_eq:
forall F V m (
ge:
_ F V)
id gv b o i,
init_data_diff i id ->
Genv.store_init_data (
Genv.add_global ge (
id,
gv))
m b o i =
Genv.store_init_data ge m b o i.
Proof.
Lemma store_init_data_list_eq:
forall F V id i,
Forall (
fun x =>
init_data_diff x id)
i ->
forall m (
ge:
_ F V)
gv b o,
Genv.store_init_data_list (
Genv.add_global ge (
id,
gv))
m b o i =
Genv.store_init_data_list ge m b o i.
Proof.
Lemma alloc_global_eq:
forall F V (
l: (
ident *
option (
globdef F V)))
m (
ge:
_ F V)
id gv,
(
forall v,
snd l =
Some (
Gvar v) ->
Forall (
fun x =>
init_data_diff x id) (
gvar_init v)) ->
Genv.alloc_global (
Genv.add_global ge (
id,
gv))
m l =
Genv.alloc_global ge m l .
Proof.
Lemma alloc_globals_eq:
forall F V (
l:
list (
ident *
option (
globdef F V)))
m (
ge:
_ F V)
id gv,
(
forall x v,
In x l ->
snd x =
Some (
Gvar v) ->
Forall (
fun x =>
init_data_diff x id) (
gvar_init v)) ->
Genv.alloc_globals (
Genv.add_global ge (
id,
gv))
m l =
Genv.alloc_globals ge m l .
Proof.
induction l;
simpl;
intros;
eauto.
rewrite alloc_global_eq.
destr.
apply IHl.
intros;
eauto.
eauto.
Qed.
Lemma find_symbol_add_globals_other:
forall F V l (
ge:
_ F V)
s,
~
In s (
map fst l) ->
Genv.find_symbol (
Genv.add_globals ge l)
s =
Genv.find_symbol ge s.
Proof.
Lemma find_symbol_add_global_other:
forall F V l (
ge:
_ F V)
s,
s <>
fst l ->
Genv.find_symbol (
Genv.add_global ge l)
s =
Genv.find_symbol ge s.
Proof.
Lemma find_symbol_none_add_global:
forall F V (
ge:
Genv.t F V)
a i,
Genv.find_symbol (
Genv.add_global ge a)
i =
None ->
i <>
fst a /\
Genv.find_symbol ge i =
None.
Proof.
Lemma find_symbol_none_add_globals:
forall F V a (
ge:
Genv.t F V)
i,
Genv.find_symbol (
Genv.add_globals ge a)
i =
None ->
~
In i (
map fst a) /\
Genv.find_symbol ge i =
None.
Proof.
induction a;
simpl;
intros;
eauto.
apply IHa in H.
destruct H as (
H1 &
H).
apply find_symbol_none_add_global in H;
auto.
intuition.
Qed.
Lemma find_symbol_none_not_in_defs:
forall F V (
p:
program F V)
i,
Genv.find_symbol (
Genv.globalenv p)
i =
None ->
~
In i (
map fst (
prog_defs p)).
Proof.
Lemma extcall_arg_inject:
forall j g rs1 m1 arg1 loc rs2 m2,
extcall_arg rs1 m1 loc arg1 ->
(
forall r,
Val.inject j (
rs1 r) (
rs2 r)) ->
Mem.inject j g m1 m2 ->
exists arg2,
extcall_arg rs2 m2 loc arg2 /\
Val.inject j arg1 arg2.
Proof.
destruct 1;
simpl;
intros.
eexists;
split;
try econstructor;
eauto.
exploit Mem.loadv_inject;
eauto.
apply Val.offset_ptr_inject;
eauto.
intros (
v2 &
LOAD &
INJ).
eexists;
split;
try econstructor;
eauto.
Qed.
Lemma extcall_arg_pair_inject:
forall j g rs1 m1 arg1 ty rs2 m2,
extcall_arg_pair rs1 m1 ty arg1 ->
(
forall r,
Val.inject j (
rs1 r) (
rs2 r)) ->
Mem.inject j g m1 m2 ->
exists arg2,
extcall_arg_pair rs2 m2 ty arg2 /\
Val.inject j arg1 arg2.
Proof.
Lemma extcall_arguments_inject:
forall j g rs1 m1 args1 sg rs2 m2,
extcall_arguments rs1 m1 sg args1 ->
(
forall r,
Val.inject j (
rs1 r) (
rs2 r)) ->
Mem.inject j g m1 m2 ->
exists args2,
extcall_arguments rs2 m2 sg args2 /\
Val.inject_list j args1 args2.
Proof.
unfold extcall_arguments.
intros j g rs1 m1 args1 sg rs2 m2.
revert args1.
generalize (
loc_arguments sg).
induction 1;
simpl;
intros;
eauto.
exists nil;
split;
try econstructor.
eapply extcall_arg_pair_inject in H;
eauto.
decompose [
ex and]
H.
edestruct IHlist_forall2 as (
a2 &
EA &
INJ);
eauto.
eexists;
split;
econstructor;
eauto.
Qed.
Lemma set_pair_no_rsp:
forall p res rs,
no_rsp_pair p ->
set_pair p res rs RSP =
rs RSP.
Proof.
destruct p;
simpl;
intros;
rewrite !
Pregmap.gso;
intuition.
Qed.
Lemma val_inject_set_pair:
forall j p res1 res2 rs1 rs2,
(
forall r,
Val.inject j (
rs1 r) (
rs2 r)) ->
Val.inject j res1 res2 ->
forall r,
Val.inject j (
set_pair p res1 rs1 r) (
set_pair p res2 rs2 r).
Proof.
Theorem step_simulation:
forall S1 t S2,
Asm.step init_stk ge S1 t S2 ->
forall j ostack S1' (
MS:
match_states j ostack S1 S1'),
exists j'
ostack'
S2',
step ge S1'
t S2' /\
match_states j'
ostack'
S2 S2'.
Proof.
End PRESERVATION.
Lemma repr_stack_limit:
Ptrofs.unsigned (
Ptrofs.repr (
Mem.stack_limit)) =
Mem.stack_limit.
Proof.
Lemma match_initial_states s:
Asm.initial_state prog s ->
exists s'
j ostack,
match_states ((
Some (
make_singleton_frame_adt (
Genv.genv_next ge) 0 0),
nil) ::
nil) (
Genv.genv_next ge)
j ostack s s' /\
RawAsm.initial_state prog (
Pregmap.init Vundef)
s'.
Proof.
inversion 1.
subst.
rename H into INIT.
rename H0 into INITMEM.
unfold Mem.record_init_sp in H1;
destr_in H1.
rename Heqp into ALLOC.
rename H1 into RSB.
exploit Genv.initmem_inject;
eauto.
intro FLATINJ.
apply Mem.push_new_stage_inject_flat in FLATINJ.
assert (
ALLOCINJ:
exists (
f' :
meminj) (
m2' :
mem) (
b2 :
block),
Mem.alloc (
Mem.push_new_stage m0) 0 (
Mem.stack_limit +
align (
size_chunk Mptr) 8) = (
m2',
b2) /\
Mem.inject f' (
flat_frameinj (
length (
Mem.stack (
Mem.push_new_stage m0))))
m m2' /\
inject_incr (
Mem.flat_inj (
Mem.nextblock m0))
f' /\
f'
b =
Some (
b2,
Mem.stack_limit +
align (
size_chunk Mptr) 8) /\ (
forall b0 :
block,
b0 <>
b ->
f'
b0 =
Mem.flat_inj (
Mem.nextblock m2)
b0)).
{
destruct (
Mem.alloc (
Mem.push_new_stage m0) 0 (
Mem.stack_limit +
align (
size_chunk Mptr) 8))
as (
m2' &
b2)
eqn:
ALLOC'.
eapply Mem.alloc_right_inject in FLATINJ;
eauto.
exploit (
Mem.alloc_left_mapped_inject _ _ _ _ _ _ _ _ b2 (
Mem.stack_limit +
align (
size_chunk Mptr) 8)
FLATINJ ALLOC).
-
exploit Mem.alloc_result;
eauto.
intro;
subst.
red;
rewnb.
xomega.
-
generalize Mem.stack_limit_range,
align_Mptr_pos,
Mem.stack_limit_range'.
omega.
-
intros ofs k p.
rewrite_perms.
rewrite pred_dec_true;
auto.
generalize (
Mem.stack_limit_range').
intros;
omega.
-
intros ofs k p.
omega.
-
red.
intro.
generalize (
size_chunk_pos chunk);
omega.
-
unfold Mem.flat_inj.
intros b0 delta'
ofs k p.
destr.
inversion 1;
subst.
exploit Mem.alloc_result;
eauto.
intro;
subst.
xomega.
-
repeat rewrite_stack_blocks.
simpl.
intuition easy.
-
intros (
f' &
INJ &
INCR &
FB &
FOTHER).
do 3
eexists.
split;
eauto.
split;
eauto.
split;
eauto.
split;
eauto.
intros;
rewrite FOTHER;
auto.
unfold Mem.flat_inj.
exploit Mem.alloc_result;
eauto.
intro;
subst.
revert FB FOTHER.
rewnb.
repeat destr.
intros;
xomega.
apply Plt_succ_inv in p.
intuition.
subst.
contradict H.
exploit Mem.alloc_result.
apply ALLOC.
intro;
subst.
rewnb.
auto.
}
destruct ALLOCINJ as (
f' &
m2' &
b2 &
ALLOC' &
ALLOCINJ &
INCR &
F'
B &
F'
O).
assert (
b =
b2).
{
exploit Mem.alloc_result.
apply ALLOC.
exploit Mem.alloc_result.
apply ALLOC'.
intros;
subst.
rewnb.
congruence.
}
subst.
assert (
b2 =
bstack).
{
unfold bstack.
exploit Mem.alloc_result;
eauto.
intro;
subst.
rewnb.
fold ge;
reflexivity.
}
subst.
edestruct (
Mem.range_perm_drop_2)
with (
p :=
Writable)
as (
m3' &
DROP).
red;
intros;
eapply Mem.perm_alloc_2;
eauto.
assert (
DROPINJ:
Mem.inject f' (
flat_frameinj (
length (
Mem.stack (
Mem.push_new_stage m0))))
m m3').
{
eapply Mem.drop_outside_inject.
apply ALLOCINJ.
eauto.
intros b'
delta ofs k p FB1 PERM RNG.
revert PERM;
repeat rewrite_perms.
destr.
omega.
intros.
revert FB1;
unfold Mem.flat_inj.
rewrite F'
O.
unfold Mem.flat_inj.
destr.
auto.
}
assert (
RSB':
exists m4',
Mem.record_stack_blocks m3' (
make_singleton_frame_adt'
bstack frame_info_mono 0) =
Some m4' /\
Mem.inject f'
(
flat_frameinj (
length (
Mem.stack (
Mem.push_new_stage m0))))
m2 m4').
{
edestruct Mem.record_stack_blocks_inject_parallel as (
m4' &
RSB' &
RSBinj).
apply DROPINJ. 7:
eauto.
instantiate (1 :=
make_singleton_frame_adt'
bstack frame_info_mono 0).
-
red;
intros.
constructor;
auto.
simpl.
rewrite F'
B.
inversion 1.
eexists;
split;
eauto.
split;
simpl;
intros;
rewrite Z.max_r in H0;
omega.
-
repeat rewrite_stack_blocks.
easy.
-
red.
intros b [
A|[]].
subst.
unfold bstack;
simpl.
red.
rewnb.
fold ge.
xomega.
-
intros b fi o k p [
A|[]];
inv A.
repeat rewrite_perms.
destr.
-
unfold Mem.flat_inj.
intros b1 b0 delta FB.
destruct (
peq b1 bstack);
subst.
rewrite F'
B in FB;
inv FB.
tauto.
rewrite F'
O in FB;
auto.
unfold Mem.flat_inj in FB.
destr_in FB.
inv FB.
tauto.
-
reflexivity.
-
repeat rewrite_stack_blocks.
constructor.
reflexivity.
-
repeat rewrite_stack_blocks.
simpl.
omega.
-
eexists;
split;
eauto.
}
destruct RSB'
as (
m4' &
RSB' &
RSBINJ).
eexists _,
f',
_;
split.
2: (
econstructor;
eauto;
econstructor;
eauto).
econstructor;
eauto.
-
apply Mem.inject_push_new_stage_left.
revert RSBINJ.
instantiate (1 := (
None,
nil) ::
nil).
repeat rewrite_stack_blocks.
simpl.
auto.
-
repeat rewrite_stack_blocks.
simpl.
unfold bstack.
inversion 1.
intros;
reflexivity.
-
unfold rs0.
rewrite Pregmap.gss.
eauto.
-
intros.
unfold rs0.
repeat (
intros;
apply val_inject_set;
auto).
+
econstructor;
eauto.
unfold Genv.find_symbol in H2.
exploit Genv.genv_symb_range.
eauto.
unfold ge0.
intro PLT.
rewrite F'
O.
unfold Mem.flat_inj.
rewrite pred_dec_true.
eauto.
rewnb.
xomega.
exploit Mem.alloc_result;
eauto.
intro;
subst.
rewrite H1.
rewnb.
apply Plt_ne.
auto.
reflexivity.
+
unfold Vnullptr;
constructor.
+
econstructor.
rewnb.
eauto.
rewrite Ptrofs.add_zero_l.
auto.
-
red;
unfold bstack;
rewnb.
fold ge.
xomega.
-
red.
rewrite Pregmap.gss.
inversion 1;
subst.
repeat rewrite_stack_blocks.
simpl.
rewrite Ptrofs.unsigned_repr.
unfold size_frame.
simpl.
inversion 1.
subst.
simpl.
omega.
generalize Mem.stack_limit_range,
align_Mptr_pos,
Mem.stack_limit_range'.
omega.
-
red.
rewrite Pregmap.gss.
inversion 1;
subst.
rewrite Ptrofs.unsigned_repr.
apply Z.divide_add_r.
apply Mem.stack_limit_aligned.
apply align_divides;
omega.
generalize Mem.stack_limit_range,
align_Mptr_pos,
Mem.stack_limit_range'.
omega.
-
red.
intros o k p.
repeat rewrite_perms.
rewrite peq_true.
intros (
A &
B).
split.
generalize Mem.stack_limit_range'.
omega.
apply B.
auto.
auto.
-
red;
intros.
repeat rewrite_perms.
rewrite peq_true.
split;
auto.
intros;
constructor.
-
red.
repeat rewrite_stack_blocks.
inversion 1;
subst.
repeat econstructor.
-
rewrite Pregmap.gss.
eauto.
-
red.
intros b delta o k p INJ.
repeat rewrite_perms.
destr.
omega.
intro P.
rewrite F'
O in INJ by auto.
unfold Mem.flat_inj in INJ.
revert INJ.
apply Mem.perm_valid_block in P.
red in P;
revert P.
rewnb.
destr.
-
repeat rewrite_stack_blocks.
inversion 1;
subst.
repeat econstructor;
eauto.
simpl.
rewrite Z.max_r by omega.
change (
align 0 8)
with 0.
rewrite F'
B.
f_equal.
f_equal.
omega.
simpl.
rewrite Z.max_r ;
intros;
omega.
-
red.
repeat rewrite_stack_blocks.
inversion 1;
subst.
simpl.
intros.
destruct H as [[]|[[
A|[]]|[]]].
inv A.
simpl.
rewrite Z.max_r by omega.
change (
align 0 8)
with 0.
omega.
-
intros.
assert (
Plt b (
Genv.genv_next ge)).
{
unfold Genv.find_funct_ptr in H.
repeat destr_in H.
eapply Genv.genv_defs_range in Heqo;
eauto.
}
rewrite F'
O.
unfold Mem.flat_inj.
rewnb.
fold ge.
destr.
xomega.
apply Plt_ne;
auto.
-
intros.
assert (
Plt b (
Genv.genv_next ge)).
{
eapply Genv.genv_defs_range in H;
eauto.
}
rewrite F'
O.
unfold Mem.flat_inj.
rewnb.
fold ge.
destr.
xomega.
apply Plt_ne;
auto.
-
split.
simpl;
intros.
assert (
Plt b (
Genv.genv_next ge)).
{
eapply Genv.genv_symb_range in H;
eauto.
}
rewrite F'
O.
unfold Mem.flat_inj.
rewnb.
fold ge.
destr.
xomega.
apply Plt_ne;
auto.
intros b1 b2 delta FB.
destruct (
peq b1 bstack);
subst.
rewrite F'
B in FB;
inv FB;
auto.
rewrite F'
O in FB;
auto.
unfold Mem.flat_inj in FB;
repeat destr_in FB;
auto.
-
intros b1 b2 delta PLT FB.
rewrite F'
O in FB.
unfold Mem.flat_inj in FB.
destr_in FB.
intro;
subst.
rewrite F'
B in FB.
inv FB.
unfold bstack in PLT.
xomega.
-
rewnb.
fold ge.
xomega.
-
rewnb.
fold ge.
xomega.
-
repeat rewrite_stack_blocks.
simpl.
right;
left;
left.
simpl.
reflexivity.
Qed.
Lemma transf_final_states:
forall istk isp j o st1 st2 r,
match_states istk isp j o st1 st2 ->
Asm.final_state st1 r ->
final_state st2 r.
Proof.
inversion 1;
subst.
inversion 1;
subst.
econstructor.
generalize (
RINJ PC).
rewrite H3.
unfold Vnullptr.
destruct ptr64;
inversion 1;
auto.
generalize (
RINJ RAX).
rewrite H5.
unfold Vnullptr.
destruct ptr64;
inversion 1;
auto.
Qed.
Theorem transf_program_correct:
asm_prog_no_rsp ge ->
forward_simulation (
Asm.semantics
prog
((
Some (
make_singleton_frame_adt (
Genv.genv_next ge) 0 0),
nil) ::
nil))
(
RawAsm.semantics prog (
Pregmap.init Vundef)).
Proof.
End WITHMEMORYMODEL.