Require
OnMem
MemCsharpminor.
Import
Utf8
Coqlib
AST
Maps
Globalenvs
Values
Integers
Floats
Memory
Csharpminorannot
Util
AssocList
ListAdom
ToString
AdomLib
AlarmMon
AbMachineEnv
Cells
Sets
PExpr
AbMemSignatureCsharpminor
PointsTo
OnMem
MemCsharpminor.
Set Implicit Arguments.
Section num.
Context
{
num num_iter:
Type}
`{
numToString:
ToString num}
`{
numIterToString:
ToString num_iter}
(
NumDom:
ab_machine_env (
var:=
cell)
num num_iter).
Variable ge :
genv.
Variable max_concretize :
N.
Existing Instances t_leb_correct t_join_correct widen_mem_correct.
Local Instance t_gamma :
gamma_op (@
t num)
concrete_state :=
t_gamma NumDom ge.
Local Instance iter_t_gamma :
gamma_op (@
iter_t num_iter)
concrete_state :=
iter_t_gamma NumDom ge.
Local Instance mem_cshm_dom :
mem_dom _ _ _ :=
mem_cshm_dom NumDom ge max_concretize.
Lemma read_cell_upd t e σ
m x v c:
c ≠
ACtemp (
plength σ)
x →
read_cell ge ((
PTree.set x v t,
e) :: σ,
m)
c =
read_cell ge ((
t,
e) :: σ,
m)
c.
Proof.
destruct c as [
f'
x'|
f'
x'|
b];
simpl;
auto.
intros _.
rewrite !
get_stk_cons.
destruct (
Pos.eqb _ _);
reflexivity.
rewrite !
get_stk_cons.
case (
Pos.eqb_spec _ _).
intros ->
K.
simpl.
rewrite PTree.gso.
reflexivity.
intros ->;
apply K;
reflexivity.
reflexivity.
Qed.
Lemma validate_volatile_ptr_in sz ptr nes b :
∀
stk m,
sizes_gamma ge stk sz m →
validate_volatile_ptr ge sz ptr nes b =
true →
∀
blk,
BlockSet.mem blk ptr →
∃
g b,
blk =
ABglobal b ∧
Genv.find_symbol ge g =
Some b ∧
Senv.block_is_volatile ge b.
Proof.
unfold validate_volatile_ptr.
intros stk m SZ.
apply BSO.foldspec. 2:
firstorder;
fail.
intros s s'
_ ()
x H [
R1 _]
H1 H2 blk H4.
2:
easy.
destruct (
R1 _ H4)
as [ -> |
IN ].
-
destruct blk as [ ? ? |
blk ].
easy.
destruct (
Genv.invert_symbol _ _)
as [
g | ]
eqn:
Hg.
exists g,
blk.
split.
easy.
split.
now rewrite (
Genv.invert_find_symbol _ _ Hg).
destruct (
ABTreeDom.get (
ABglobal blk)
sz)
as [ | (?, (?,
vol)) ]
eqn:
Hsz.
easy.
subst.
generalize (λ
b',
SZ (
ABglobal blk)
_ _ _ b'
Hsz).
simpl.
rewrite Hg.
intros X.
specialize (
X _ eq_refl).
easy.
easy.
-
specialize (
H1 eq_refl _ IN).
eauto.
Qed.
Lemma forget_all_correct
{
A V:
Type} (
P:
A → (
cell →
V) →
Prop)
(
P_ext: ∀ ρ ρ', (∀
x, ρ(
x) = ρ'(
x)) → ∀
m, ρ ∈
P m → ρ' ∈
P m)
(
F:
A →
cell →
A)
(
PF: ∀
m ρ ρ'
x, ρ ∈
P m → (∀
y,
y ≠
x → ρ'(
y) = ρ(
y)) → ρ' ∈
P (
F m x))
l :
∀
m :
A,
∀ ρ ρ' :
cell →
V,
ρ ∈
P m →
(∀
c, ρ
c = ρ'
c ∨
In c l) →
ρ' ∈
P (
fold_left F l m).
Proof.
induction l as [|
i l IH]
using rev_ind.
-
intros m ρ ρ'
H K.
apply (
P_ext ρ).
intros c;
destruct (
K c)
as [ ? | () ];
assumption.
assumption.
-
intros m ρ ρ'
H K.
rewrite fold_left_app.
simpl.
apply PF with (λ
c,
if eq_dec c i then ρ
c else ρ'
c).
eapply IH.
eassumption.
intros c.
destruct (
eq_dec c i).
left;
reflexivity.
destruct (
K c)
as [
X |
X].
left;
exact X.
rewrite in_app in X.
destruct X as [
X | [
X | () ] ].
right;
exact X.
intuition.
intros y H0.
rewrite dec_eq_false;
auto.
Qed.
Opaque ACTreeDom.set.
Lemma ct_forget_all_get {
A}
l : ∀
m c,
ACTreeDom.get c (@
ct_forget_all A l m) =
if in_dec eq_dec c l
then All
else ACTreeDom.get c m.
Proof.
Lemma pt_forget_all_correct stk l :
∀
m :
points_to,
∀ ρ ρ' :
cell →
val,
ρ ∈
points_to_gamma ge stk m →
(∀
c, ρ
c = ρ'
c ∨
In c l) →
ρ' ∈
points_to_gamma ge stk (
ct_forget_all l m).
Proof.
Definition loose_upd_spec {
B} (
f:
cell →
B) (
x:
cell) (
v:
B) (
f':
cell →
B) :
Prop :=
f'(
x) =
v ∧ ∀
y,
y ∈
cells_disjoint(
x) →
f'(
y) =
f(
y).
Lemma nm_upd_correct nm c e n (ρ ρ':
cell →
mach_num) :
ρ ∈ γ(
nm) →
n ∈
eval_mexpr ρ
e →
ρ' ∈
loose_upd_spec ρ
c n →
ρ' ∈ γ (
nm_upd NumDom nm c e).
Proof.
Lemma nm_upd_not_bot nm c e n (ρ:
cell →
mach_num) :
ρ ∈ γ(
nm) →
n ∈
eval_mexpr ρ
e →
nm_upd NumDom nm c e ≠
Bot.
Proof.
Lemma tp_upd_correct (
val:
Type) (Γ:
gamma_op type val)
(
HJ:
join_op_correct type (
type+⊤)
val)
tp ρ
cells ty c v :
v ∈ γ(
ty) →
In c cells →
ρ ∈ γ
tp →
loose_upd_spec ρ
c v ⊆ γ (
tp_upd_cells tp cells ty).
Proof.
Lemma cell_in_bounds_range_perm κ (
ab: @
t num)
c:
am_get (
cell_in_bounds ge κ
ab c) =
Some tt →
∀
m σ
b,
m ∈
sizes_gamma ge σ (
ab_sz ab) →
block_of_ablock ge σ (
ablock_of_cell c) =
Some b →
Mem.range_perm m b (
fst (
range_of_cell c)) (
fst (
range_of_cell c) +
size_chunk (
proj1_sig κ))
Cur Writable.
Proof.
unfold cell_in_bounds.
set (
b :=
ablock_of_cell c).
destruct (
range_of_cell c)
as (
ofs, κ').
destruct (
ABTreeDom.get b (
ab_sz ab))
as [|(
hi, (
perm,
vol))]
eqn:
Hhi.
simpl.
intros ?;
eq_some_inv.
destruct (
permission_can_write perm)
eqn:
Hrw. 2:
simpl;
intro;
eq_some_inv.
destruct zle as [
L|]. 2:
simpl;
intro;
eq_some_inv.
destruct zle as [
R|]. 2:
simpl;
intro;
eq_some_inv.
intros _.
intros m σ
b'
H Hb o K.
specialize (
H _ _ _ _ _ Hhi Hb).
eapply Mem.perm_implies.
apply H.
simpl in *.
Psatz.lia.
destruct perm;
vauto;
simpl in Hrw;
eq_some_inv.
Qed.
Arguments cell_in_bounds_range_perm [κ] [
ab] [
c]
_ [
m] [σ] [
b]
_ _ _ _.
Opaque cell_in_bounds.
Lemma nassume_correct b nm F el :
∀ ρ,
ρ ∈ γ(
nm) →
∀
e,
In e el →
eval_mexpr ρ (
F e) (
of_bool b) →
ρ ∈ γ (
nassume NumDom b nm F el).
Proof.
Lemma env_ok (ε:
lvarset) (
e:
env) :
(∀
x,
PSet.mem x ε =
dom x e) →
∀
i,
is_local ε
i =
true ↔
e !
i ≠
None.
Proof.
unfold is_local,
dom.
intros H i.
rewrite H.
destruct (
e !
i);
intuition.
eq_some_inv.
Qed.
Remark bind_parameters_zip formals : ∀
args te,
bind_parameters formals args te =
fold_left2 (λ
acc id v,
do te <-
acc;
ret (
PTree.set id v te))
(λ
_ _ ,
None) (λ
_ _,
None)
formals args (
Some te).
Proof.
induction formals as [|id formals IH].
reflexivity.
destruct args as [|v args]. reflexivity.
simpl. intros te. rewrite IH. reflexivity.
Qed.
Lemma set_local_sizes_get μ
vars sz b :
list_norepet (
map fst vars) →
ABTreeDom.get b (
set_local_sizes μ
vars sz) =
match b with
|
ABlocal μ'
x =>
if peq μ' μ
then match assoc x vars with
|
Some hi =>
Just (
hi, (
Freeable,
false))
|
None =>
ABTreeDom.get b sz
end
else ABTreeDom.get b sz
|
_ =>
ABTreeDom.get b sz
end.
Proof.
Lemma clear_local_sizes_get μ ε
b sz :
ABTreeDom.get b (
clear_local_sizes μ ε
sz) =
match b with
|
ABlocal μ'
x =>
if peq μ μ' &&
PSet.mem x ε
then All else ABTreeDom.get b sz
|
_ =>
ABTreeDom.get b sz
end.
Proof.
unfold clear_local_sizes.
apply PSetOp.foldspec.
intros s s'
a b0 x H [
REM REM']
H1.
unfold ABTreeDom.get in *.
rewrite ABTree.grspec.
destruct (
ABTree.elt_eq b (
ABlocal μ
x))
as [
EQ|
ME].
subst.
destruct peq. 2:
congruence.
rewrite H.
reflexivity.
rewrite H1.
destruct b as [μ'
x'|
b];
auto.
destruct peq;
simpl;
auto.
subst.
specialize (
REM x').
specialize (
REM'
x').
destruct (
PSet.mem x'
s).
specialize (
REM eq_refl).
destruct REM as [
REM|
REM].
elim ME.
congruence.
rewrite REM.
reflexivity.
destruct (
PSet.mem x'
s'). 2:
auto.
destruct (
REM'
eq_refl)
as [
_ Y].
discriminate.
intros s H.
destruct b as [μ'
x'|
b];
auto.
destruct peq;
simpl;
auto.
subst.
specialize (
H x').
destruct (
PSet.mem);
auto.
intuition.
Qed.
Lemma read_perm_non_volatile {
V} (
gv:
globvar V) :
perm_order (
Genv.perm_globvar gv)
Readable →
gvar_volatile gv =
false.
Proof.
Arguments ab_sz _ _/.
Arguments ab_num _ _/.
Arguments ab_tp _ _/.
Lemma ab_alloc_global_ok:
∀
prog m,
ge =
Genv.globalenv prog ->
Genv.init_mem prog =
Some m ->
∀
b gv ab ab'
id log,
Genv.find_var_info ge b =
Some gv ->
Genv.invert_symbol ge b =
Some id ->
ab_alloc_global NumDom ge (
Genv.perm_globvar gv) (
gvar_volatile gv)
b (
gvar_init gv) (
NotBot ab) = (
ab', (
nil,
log)) ->
m ∈
sizes_gamma ge nil (
ab_sz ab) ->
ab_stk ab =
Just nil ->
mem_as_fun ge (
nil,
m) ∈
tnum_gamma _ ge nil (
ab_nm ab) ->
match ab'
with
|
Bot =>
False
|
NotBot ab' =>
m ∈
sizes_gamma ge nil (
ab_sz ab') /\
ab_stk ab' =
Just nil /\
mem_as_fun ge (
nil,
m) ∈
tnum_gamma _ ge nil (
ab_nm ab')
end.
Proof.
intros prog m H H0 b gv ab ab'
id log H1 H2 H3 H4 H5 H6.
eapply Genv.init_mem_characterization in H0. 2:
rewrite <-
H;
apply H1.
assert (
gv.(
gvar_volatile) =
Senv.block_is_volatile ge b)
as Hvol.
{
simpl.
unfold Genv.block_is_volatile.
rewrite H1.
reflexivity. }
clear H1.
destruct H0 as (
PERM &
PERM' &
INIT).
specialize (λ
H,
INIT (
read_perm_non_volatile _ H)).
rewrite <-
H in INIT.
clear H prog.
revert log H3.
unfold ab_alloc_global.
apply am_bind_case.
intros;
eq_some_inv;
subst.
eapply H;
eauto.
intros;
eq_some_inv.
intros [
sz ab'']
log Hab''
log'
eq.
simpl in eq.
eq_some_inv.
subst.
revert ab PERM PERM'
INIT Hvol H4 H5 H6 log Hab''.
change (
Genv.init_data_list_size (
gvar_init gv))
with (0+
Genv.init_data_list_size (
gvar_init gv)).
generalize 0
at 2 4 5 12
as offs.
generalize (
Genv.perm_globvar gv).
intros perm.
generalize (
gvar_volatile gv).
intros vol.
generalize (
gvar_init gv).
intros i.
clear gv.
induction i as [ |
a l IHl ].
-
unfold am_fold.
simpl.
destruct ab as [?[?[? ?]]].
intros.
inv Hab''.
simpl.
split. 2:
auto.
unfold sizes_gamma in *.
intros.
unfold ABTreeDom.get in H.
rewrite ABTree.gsspec in H.
destruct ABTree.elt_eq.
+
inv H.
rewrite Z.add_0_r in PERM.
simpl in H0.
rewrite H2 in H0.
inv H0.
split.
apply PERM.
apply bool_leb_refl.
+
fold (
ABTreeDom.get b0 s)
in H.
simpl in *.
eauto.
-
change (
a::
l)
with ((
a::
nil)++
l)%
list.
intros *.
rewrite am_fold_app.
apply am_bind_case.
intros x y l0 l'
H;
intros;
eq_some_inv;
subst;
eapply H;
eauto.
intros;
eq_some_inv.
destruct ab as (
abstk &
absz & (
abty &
abnm)).
intros [
offs'
ab']
log Ha PERM PERM'
INIT Hvol SZ STK (
TY & ρ' &
COMPAT &
NM)
log'
Hl.
unfold am_fold in Ha.
simpl in Ha.
match type of Ha with
|
appcontext[
if ?
b then _ else _] =>
destruct b; [|
discriminate]
end.
cut (
match ab'
with
|
Bot =>
False
|
NotBot ab' =>
sizes_gamma ge nil (
ab_sz ab')
m
∧
ab_stk ab' =
Just nil
∧
tnum_gamma _ ge nil (
ab_nm ab') (
mem_as_fun ge (
nil,
m))
end).
{
intro.
destruct ab'.
contradiction.
destruct H as (? & ? & ?).
destruct a;
simpl in Ha;
repeat match type of Ha with
|
appcontext[
Genv.find_symbol ?
ge ?
i ] =>
destruct (
Genv.find_symbol ge i); [|
discriminate]
|
appcontext[
permission_can_read ?
p ] =>
destruct (
permission_can_read p)
end;
try (
inv Ha;
apply IHl in Hl;
auto;
((
intros;
rewrite <-
Z.add_assoc; (
apply PERM ||
eapply PERM';
eauto)) ||
now intros K;
destruct (
INIT K))). }
clear Hl IHl.
destruct a; [..|
destruct (
Genv.find_symbol ge i)
eqn:
EQSYMB; [|
discriminate]];
inv Ha;
try match goal with
| |-
context [
AbMachineEnv.assign ?
c ?
e ?
ab] =>
refine (
let ASS :=
AbMachineEnv.assign_correct c (
e:=
e)
_ NM _ in _);
[
repeat econstructor;
auto using Zle_refl,
Fleb_refl,
floatofsingle_nan|
destruct AbMachineEnv.assign as [|
abnm']; [
contradiction|
simpl]]
end;
try match goal with
| |-
context [
permission_can_read ?
p] =>
destruct (
permission_can_read p)
as [
P|
P];
try (
specialize (
INIT P);
destruct INIT);
try now repeat (
split;
eauto)
end;
simpl.
+
split.
auto.
split.
auto.
split.
*
intro.
unfold ACTreeDom.get.
rewrite ACTree.gsspec.
destruct ACTree.elt_eq.
subst.
simpl.
rewrite H,
H2.
simpl.
unfold type_of_int.
apply int_eq_intro.
intros <-.
reflexivity.
intros _.
exact I.
apply TY.
*
eexists.
split. 2:
apply ASS.
intro.
simpl.
unfold upd.
destruct (
eq_dec c).
subst c.
simpl.
rewrite H,
H2.
repeat econstructor.
apply COMPAT.
+
split.
auto.
split.
auto.
split.
*
intro.
unfold ACTreeDom.get.
rewrite ACTree.gsspec.
destruct ACTree.elt_eq.
subst.
simpl.
rewrite H,
H2.
simpl.
unfold type_of_int.
apply int_eq_intro.
intros <-.
reflexivity.
intros _.
exact I.
apply TY.
*
eexists.
split. 2:
apply ASS.
intro.
simpl.
unfold upd.
destruct (
eq_dec c).
subst c.
simpl.
rewrite H,
H2.
repeat econstructor.
apply COMPAT.
+
split.
auto.
split.
auto.
split.
*
intro.
unfold ACTreeDom.get.
rewrite ACTree.gsspec.
destruct ACTree.elt_eq.
subst.
simpl.
rewrite H,
H2.
simpl.
unfold type_of_int.
apply int_eq_intro.
intros <-.
reflexivity.
intros _.
exact I.
apply TY.
*
eexists.
split. 2:
apply ASS.
intro.
simpl.
unfold upd.
destruct (
eq_dec c).
subst c.
simpl.
rewrite H,
H2.
repeat econstructor.
apply COMPAT.
+
split.
auto.
split.
auto.
split.
*
intro.
unfold ACTreeDom.get.
rewrite ACTree.gsspec.
destruct ACTree.elt_eq.
subst.
simpl.
rewrite H,
H2.
constructor.
apply TY.
*
eexists.
split. 2:
apply ASS.
intro.
simpl.
unfold upd.
destruct (
eq_dec c).
subst c.
simpl.
rewrite H,
H2.
repeat econstructor.
apply COMPAT.
+
split.
auto.
split.
auto.
split.
*
intro.
unfold ACTreeDom.get.
rewrite ACTree.gsspec.
destruct ACTree.elt_eq.
subst.
simpl.
rewrite H,
H2.
constructor.
apply TY.
*
eexists.
split. 2:
apply ASS.
intro.
simpl.
unfold upd.
destruct (
eq_dec c).
subst c.
simpl.
rewrite H,
H2.
repeat econstructor.
apply COMPAT.
+
split.
auto.
split.
auto.
split.
*
intro.
unfold ACTreeDom.get.
rewrite ACTree.gsspec.
destruct ACTree.elt_eq.
subst.
simpl.
rewrite H,
H2.
constructor.
apply TY.
*
eexists.
split. 2:
apply ASS.
intro.
simpl.
unfold upd.
destruct (
eq_dec c).
subst c.
simpl.
rewrite H,
H2.
repeat econstructor.
apply COMPAT.
+
unfold zero_all_cells.
revert abstk absz abty abnm ρ'
SZ STK NM TY COMPAT.
induction (
Z.to_N z)
using N.peano_ind.
*
repeat (
split;
eauto).
*
setoid_rewrite N.peano_rect_succ.
intros abstk absz abty abnm ρ'
X H3 H4 H5 H7.
eapply memory_chunk_fold_rec. 2:
eapply IHn;
now eauto.
{
clear abstk absz abty abnm ρ'
X H3 H4 H5 H7.
intros [|(
abstk &
absz & (
abty &
abnm))]
c.
contradiction.
intros (
SZ &
STK &
TY & ρ' &
COMPAT &
NM).
destruct zle,
Zdivide_dec;
try now repeat (
split;
eauto).
simpl.
match goal with
| |-
context [
AbMachineEnv.assign ?
ce ?
e ?
ab] =>
refine (
let ASS :=
AbMachineEnv.assign_correct ce (
e:=
e)
(
n:=
match c with exist (
Many32|
Many64)
H =>
match H with end
|
_ =>
_ end)
_ NM _
in _)
end.
-
destruct c as [[] []];
repeat constructor;
auto using Zle_refl,
Fleb_refl.
-
destruct AbMachineEnv.assign as [|
abnm']; [
contradiction|
simpl].
refine (
let H':=
H (
proj1_sig c) (
offs +
Z.of_N n)
_ _ _ in _).
eauto.
zify;
omega.
omega.
auto.
simpl.
split.
auto.
split.
auto.
split.
+
intro.
unfold ACTreeDom.get.
rewrite ACTree.gsspec.
destruct ACTree.elt_eq.
subst.
simpl.
rewrite H',
H2.
destruct c as [[] []];
constructor.
apply TY.
+
eexists.
split. 2:
apply ASS.
intro.
simpl.
unfold upd.
destruct (
eq_dec _).
subst c0.
simpl.
rewrite H',
H2.
destruct c as [[] []];
repeat econstructor.
apply COMPAT. }
+
split.
auto.
split.
auto.
rewrite EQSYMB in H.
destruct H as (
b' &
eq &
H).
inv eq.
split.
*
intro.
unfold ACTreeDom.get.
rewrite ACTree.gsspec.
destruct ACTree.elt_eq.
subst.
simpl.
rewrite H,
H2.
eexists.
split.
apply BSO.mem_singleton.
eauto.
simpl.
erewrite Genv.find_invert_symbol;
eauto.
apply TY.
*
eexists.
split. 2:
apply ASS.
intro.
simpl.
unfold upd.
destruct (
eq_dec c).
subst c.
simpl.
rewrite H,
H2.
repeat econstructor.
apply COMPAT.
Qed.
Lemma ab_alloc_globals_ok:
∀
prog m,
ge =
Genv.globalenv prog ->
Genv.init_mem prog =
Some m ->
list_norepet (
map fst prog.(
prog_defs)) ->
∀
b ab log,
ab_alloc_globals NumDom ge prog.(
prog_defs) = ((
b,
ab), (
nil,
log)) ->
b =
plength prog.(
prog_defs) /\
match ab with
|
Bot =>
False
|
NotBot ab =>
m ∈
sizes_gamma ge nil (
ab_sz ab) /\
ab_stk ab =
Just nil /\
mem_as_fun ge (
nil,
m) ∈
tnum_gamma _ ge nil (
ab_nm ab)
end.
Proof.
Lemma check_volatile_sound {
tgt κ
ab} :
∀ μ
log,
check_volatile NumDom ge max_concretize tgt κ
ab = (μ, (
nil,
log)) →
match ab_stk ab with Just (
_ :: σ ) => μ =
plength σ |
_ =>
False end ∧
match tgt with
|
inl (
g,
ofs) =>
∃
b,
Genv.find_symbol ge g =
Some b ∧
∃
hi perm,
ABTreeDom.get (
ABglobal b) (
ab_sz ab) =
Just (
hi, (
perm,
true))
|
inr addr =>
∃
tn ty ne,
am_get (
ab_eval_expr NumDom ge max_concretize ab addr) =
Some (
NotBot (
tn,
Just ty,
ne)) ∧
∃
ptr,
ty =
TyPtr (
Just ptr) ∧
validate_volatile_ptr ge (
ab_sz ab)
ptr ne true
end.
Proof.
intros μ.
unfold check_volatile.
apply am_bind_case.
intros;
eq_some_inv;
subst;
eauto.
intros;
eq_some_inv.
intros ()
log H.
destruct (
ab_stk _)
as [ | [ |
_ σ ] ].
easy.
easy.
split.
inv H0.
auto.
destruct tgt as [ (
g,
ofs) |
addr ].
-
destruct (
Genv.find_symbol _ _)
as [
b | ];
eq_some_inv.
exists b;
split.
easy.
destruct (
ABTreeDom.get _ _)
as [ | (?, (?, ())) ];
eq_some_inv.
vauto.
-
revert log H.
apply am_bind_case.
intros;
eq_some_inv;
subst;
eauto.
intros;
eq_some_inv.
intros [ | ((
tn &
ty) &
ne) ]
log EV.
easy.
destruct ty as [ | [ | | | | | [ |
ptr ] | [ |
ptr ] | ] ];
try easy;
intros log'
H;
eexists tn,
_,
ne;
(
split; [
now rewrite EV |
eexists;
split; [
vauto | ] ]).
destruct validate_volatile_ptr.
reflexivity.
eq_some_inv.
Qed.
Lemma only_global_pointer_iff aptr :
only_global_pointer ge aptr →
∃
ptr,
aptr =
Just ptr ∧
∀
p,
BlockSet.mem p ptr → ∃
b,
p =
ABglobal b ∧ ∃
g,
Genv.invert_symbol ge b =
Some g ∧
Senv.public_symbol ge g.
Proof.
Definition alloc_variables'
e m v :=
List.fold_left (λ
e_m id_sz,
let '(
e,
m) :=
e_m in
let '(
id,
sz) :=
id_sz in
let '(
m₁,
b₁) :=
Mem.alloc m 0
sz in
(
PTree.set id (
b₁,
sz)
e,
m₁))
v (
e,
m).
Lemma alloc_variables_alt v:
∀
e m e'
m',
alloc_variables e m v e'
m' ↔
alloc_variables'
e m v = (
e',
m').
Proof.
induction v as [|(
id,
sz)
v IH].
-
intros e m e'
m'.
split;
intros H.
inv H.
reflexivity.
compute in H.
eq_some_inv.
subst.
vauto.
-
intros e m e'
m'.
unfold alloc_variables'.
simpl.
destruct (
Mem.alloc m 0
sz)
as (
m₁,
b₁)
eqn:
H.
change (
alloc_variables e m ((
id,
sz) ::
v)
e'
m' ↔
alloc_variables' (
PTree.set id (
b₁,
sz)
e)
m₁
v = (
e',
m')).
etransitivity. 2:
apply IH.
split;
intros H'.
inv H'.
congruence.
vauto.
Qed.
Definition alloc_var :=
alloc_variables'
empty_env.
Lemma alloc_var_alt m v e'
m' :
alloc_variables empty_env m v e'
m' ↔
alloc_var m v = (
e',
m').
Proof.
Lemma alloc_var_snoc m v id sz :
alloc_var m (
v ++ (
id,
sz) ::
nil)%
list =
let '(
e,
m') :=
alloc_var m v in
let '(
m₁,
b₁) :=
Mem.alloc m' 0
sz in
(
PTree.set id (
b₁,
sz)
e,
m₁).
Proof.
Lemma alloc_var_guts m v:
∀
e'
m',
alloc_var m v = (
e',
m') →
∀
b,
Mem.valid_block m b →
Mem.valid_block m'
b ∧
(
Mem.mem_contents m') !!
b = (
Mem.mem_contents m) !!
b ∧
(
Mem.mem_access m') !!
b = (
Mem.mem_access m) !!
b.
Proof.
induction v as [|(
id,
sz)
v IH]
using rev_ind.
intros e'
m'
H b H0.
compute in H.
eq_some_inv.
subst.
auto.
intros e'
m'
H b H0.
rewrite alloc_var_snoc in H.
destruct (
alloc_var m v)
as (
e₀,
m₀).
destruct (
Mem.alloc m₀ 0
sz)
as (
m₁,
b₁)
eqn:
H₁.
eq_some_inv.
subst.
specialize (
IH _ _ eq_refl _ H0).
destruct IH as (
V &
IHc &
IHa).
split.
apply (
Mem.valid_block_alloc _ _ _ _ _ H₁).
exact V.
Transparent Mem.alloc.
unfold Mem.alloc in H₁.
Opaque Mem.alloc.
eq_some_inv.
subst.
simpl.
split; (
etransitivity; [
apply PMap.gso,
Plt_ne,
V |
eassumption ]).
Qed.
Corollary alloc_var_load m v:
∀
e'
m',
alloc_var m v = (
e',
m') →
∀
b,
Mem.valid_block m b →
∀ κ
o,
Mem.load κ
m'
b o =
Mem.load κ
m b o.
Proof.
Lemma alloc_variables_dom e m v e'
m' :
alloc_variables e m v e'
m' →
∀
x,
dom x e' =
dom x e ||
in_dec peq x (
List.map fst v).
Proof.
clear.
induction 1.
intros;
simpl;
rewrite orb_false_r;
reflexivity.
intros x.
simpl.
rewrite (
IHalloc_variables x).
clear.
rewrite dom_set.
destruct peq.
destruct peq.
rewrite orb_true_r.
reflexivity.
intuition.
simpl.
destruct (
dom x e).
reflexivity.
simpl.
destruct peq.
intuition.
destruct (
in_dec);
reflexivity.
Qed.
Lemma in_elements_set {
A}
e x y (
v:
A):
In x (
PTree.elements (
PTree.set y v e)) →
x = (
y,
v) ∨
In x (
PTree.elements e) ∧
fst x ≠
y.
Proof.
Lemma alloc_variables_perm_mono m e v e'
m':
alloc_variables e m v e'
m' →
∀
b o p,
Mem.perm m b o Cur p →
Mem.perm m'
b o Cur p.
Proof.
induction 1;
auto.
intros b o p H1.
eapply IHalloc_variables.
eapply Mem.perm_alloc_1;
eauto.
Qed.
Lemma alloc_variables_perm'
e m v e'
m':
alloc_variables e m v e'
m' →
∀
b hi,
In (
b, 0,
hi) (
blocks_of_env e') →
In (
b, 0,
hi) (
blocks_of_env e) ∨
Mem.range_perm m'
b 0
hi Cur Freeable.
Proof.
induction 1;
intros b hi IN.
left;
exact IN.
destruct (
IHalloc_variables _ _ IN)
as [
IN'|
R];
auto.
clear IHalloc_variables.
unfold blocks_of_env in IN'.
rewrite in_map_iff in IN'.
destruct IN'
as (
q &
Hq &
IN').
apply in_elements_set in IN'.
destruct IN'
as [ -> | (
IN' &
Hq') ].
2:
left;
apply in_map_iff;
vauto.
simpl in Hq.
eq_some_inv.
subst.
right.
intros o Ho.
eapply Mem.perm_alloc_2 in H;
eauto.
eapply alloc_variables_perm_mono;
eauto.
Qed.
Corollary alloc_variables_perm m v e m':
alloc_variables empty_env m v e m' →
∀
b hi,
In (
b, 0,
hi) (
blocks_of_env e) →
Mem.range_perm m'
b 0
hi Cur Freeable.
Proof.
intros H b hi H0.
destruct (alloc_variables_perm' H b hi H0) as [K|K]. elim K. exact K.
Qed.
Lemma alloc_variables_env'
e m v e'
m':
alloc_variables e m v e'
m' →
list_norepet (
List.map fst v) →
∀
x y,
PTree.get x e' =
Some y →
PTree.get x e =
Some y ∨
assoc x v =
Some (
snd y).
Proof.
induction 1.
auto.
intros NR x y H1.
inv NR.
destruct (
IHalloc_variables H5 _ _ H1)
as [
K|
K].
rewrite PTree.gsspec in K.
destruct peq.
eq_some_inv.
subst.
right.
simpl.
rewrite dec_eq_true.
reflexivity.
left.
exact K.
simpl.
rewrite dec_eq_false.
auto.
intro;
apply H4.
apply assoc_in in K.
rewrite in_map_iff.
subst.
eexists;
split;
eauto;
reflexivity.
Qed.
Corollary alloc_variables_env m v e m':
alloc_variables empty_env m v e m' →
list_norepet (
List.map fst v) →
∀
x y,
PTree.get x e =
Some y →
assoc x v =
Some (
snd y).
Proof.
intros H H0 x y H1.
destruct (
alloc_variables_env'
H H0 _ H1)
as [
X|
X];
eauto.
rewrite PTree.gempty in X.
eq_some_inv.
Qed.
Lemma alloc_variables_load'
e m v :
∀
e'
m',
alloc_variables e m v e'
m' →
∀
x y,
e' !
x =
Some y →
e !
x =
Some y ∨
Mem.valid_block m' (
fst y) ∧ ∀
o,
ZMap.get o (
Mem.mem_contents m') !! (
fst y) =
Undef.
Proof.
setoid_rewrite alloc_variables_alt.
induction v as [|(
id,
sz)
v IH]
using rev_ind.
intros e'
m'
H x y H0.
compute in H.
eq_some_inv.
left.
congruence.
intros e'
m'
H x y H0.
unfold alloc_variables'
in H.
rewrite fold_left_app in H.
assert ((
let '(
e,
m) :=
alloc_variables'
e m v in let '(
m₁,
b₁) :=
Mem.alloc m 0
sz in (
PTree.set id (
b₁,
sz)
e,
m₁)) = (
e',
m'))
as H'
by
exact H.
clear H.
destruct (
alloc_variables'
e m v)
as (
ee,
mm).
specialize (
IH _ _ eq_refl).
destruct (
Mem.alloc mm 0
sz)
as (
m₁,
b₁)
eqn:
H₁.
eq_some_inv.
subst.
rewrite PTree.gsspec in H0.
destruct peq.
eq_some_inv.
subst.
right.
split.
apply (
Mem.valid_new_block _ _ _ _ _ H₁).
intros o.
Transparent Mem.alloc.
unfold Mem.alloc in *.
Opaque Mem.alloc.
eq_some_inv.
subst.
simpl.
rewrite PMap.gss.
apply ZMap.gi.
specialize (
IH _ _ H0).
destruct IH as [
IH | [
V IH]].
left;
exact IH.
right.
split.
exact (
Mem.valid_block_alloc _ _ _ _ _ H₁
_ V).
intros o.
specialize (
IH o).
Transparent Mem.alloc.
unfold Mem.alloc in *.
Opaque Mem.alloc.
eq_some_inv.
subst.
simpl.
rewrite PMap.gso.
exact IH.
apply Plt_ne,
V.
Qed.
Corollary alloc_variables_load m v e m':
alloc_variables empty_env m v e m' →
∀
x y,
e !
x =
Some y →
Mem.valid_block m' (
fst y) ∧ ∀
o,
ZMap.get o (
Mem.mem_contents m') !! (
fst y) =
Undef.
Proof.
intros H x y H0.
destruct (
alloc_variables_load'
H _ H0);
auto.
rewrite PTree.gempty in *.
eq_some_inv.
Qed.
Lemma alloc_var_inj m v :
∀
e'
m',
alloc_var m v = (
e',
m') →
(
Mem.valid_block m ⊆
Mem.valid_block m') ∧
(∀
x y,
e' !
x =
Some y →
Mem.valid_block m' (
fst y) ∧ ¬
Mem.valid_block m (
fst y)) ∧
injective_map (λ
x,
fmap fst (
e' !
x)).
Proof.
induction v as [|(
id,
sz)
v IH]
using rev_ind.
intros e'
m'
H.
compute in H.
eq_some_inv.
subst.
split.
easy.
split;
repeat intro;
rewrite PTree.gempty in *;
simpl in *;
eq_some_inv.
intros e'
m'
H.
rewrite alloc_var_snoc in H.
destruct (
alloc_var m v)
as (
e₀,
m₀).
specialize (
IH _ _ eq_refl).
destruct (
Mem.alloc m₀ 0
sz)
as (
m₁,
b₁)
eqn:
H₁.
eq_some_inv.
subst.
destruct IH as (
M &
V &
IH).
split.
intros b B.
eapply Mem.valid_block_alloc;
eauto.
split.
intros x y H.
rewrite PTree.gsspec in H.
destruct peq.
eq_some_inv.
subst.
split.
exact (
Mem.valid_new_block _ _ _ _ _ H₁).
intros X.
apply (
Mem.fresh_block_alloc _ _ _ _ _ H₁),
M,
X.
destruct (
V _ _ H);
intuition.
apply (
Mem.valid_block_alloc _ _ _ _ _ H₁).
eauto.
intros x x'
a Ha Ha'.
rewrite PTree.gsspec in *.
destruct peq.
simpl in *.
eq_some_inv.
subst id a.
destruct peq.
easy.
destruct (
e₀ !
x')
as [(?,?)|]
eqn:
Hx';
simpl in *;
eq_some_inv;
subst.
exfalso.
generalize (
proj1 (
V _ _ Hx')).
exact (
Mem.fresh_block_alloc _ _ _ _ _ H₁).
destruct peq.
simpl in *.
eq_some_inv.
subst.
destruct (
e₀ !
x)
as [(?,?)|]
eqn:
Hx;
simpl in *;
eq_some_inv;
subst.
exfalso.
generalize (
proj1 (
V _ _ Hx)).
exact (
Mem.fresh_block_alloc _ _ _ _ _ H₁).
exact (
IH _ _ _ Ha Ha').
Qed.
Lemma alloc_variables_build vars m m' :
∀
e',
alloc_variables empty_env m vars e'
m' →
∀
x :
PSet.elt,
PSet.mem x (
PSetOp.build (
rev_map fst vars)) =
dom x e'.
Proof.
Remark create_undef_temps_undef l x :
extend (λ
x, (
create_undef_temps l) !
x)
x =
Vundef.
Proof.
Lemma push_frame_invariant vars :
∀ σ
m tmp e m',
alloc_variables empty_env m vars e m' →
invariant ge (σ,
m) →
invariant ge ((
tmp,
e) :: σ,
m').
Proof.
intros σ
m tmp e m'
Hal Inv.
split.
+
intros t0 e0 [
H|
H]
b hi H0.
eq_some_inv.
subst t0 e0.
eapply (
alloc_variables_perm);
eauto.
intros o Ho.
eapply (
alloc_variables_perm_mono);
eauto.
eapply Inv.(
localFreeable);
eauto.
+
intros t0 e0 [
H|
H]
x b y b'
z H0 H1.
2:
exact (
Inv.(
localNotGlobal)
_ _ H _ _ H0 H1).
eq_some_inv.
subst t0 e0.
pose proof (
Inv.(
globalValid)
_ H0)
as X.
pose proof (
alloc_var_inj _ _ (
proj1 (
alloc_var_alt _ _ _ _)
Hal))
as (
_ &
Y &
_).
specialize (
Y _ _ H1).
destruct Y as [
_ Y].
simpl in *.
intros ->.
exact (
Y X).
+
intros (
f,
x) (
f',
x')
a.
simpl.
destruct (
alloc_var_inj _ _ (
proj1 (
alloc_var_alt _ _ _ _)
Hal))
as (
_ &
Q &
H).
rewrite !
get_stk_cons.
case (
Pos.eqb_spec).
intros ->.
simpl.
case (
Pos.eqb_spec).
intros ->.
simpl.
intros H0 H1.
f_equal.
exact (
H _ _ _ H0 H1).
intros NE H0 H1.
apply do_opt_some_inv in H0.
destruct H0 as ((
a' &
al) &
H0 & ?).
simpl in *.
eq_some_inv.
subst a'.
specialize (
Q _ _ H0).
simpl in Q.
apply do_opt_some_inv in H1.
destruct H1 as (
tee &
Htee &
H1).
apply do_opt_some_inv in H1.
destruct H1 as ((
a' &
al') &
H1 & ?).
simpl in *.
eq_some_inv.
subst a'.
apply get_stk_in in Htee.
destruct tee as (
te' &
e').
simpl in *.
assert (
In (
a, 0,
al') (
blocks_of_env e'))
as Ha.
unfold blocks_of_env.
rewrite in_map_iff.
eexists.
split. 2:
apply PTree.elements_correct,
H1.
reflexivity.
elim (
proj2 Q).
eapply Inv.(
localValid);
eauto.
intros NE.
case (
Pos.eqb_spec).
intros ->.
simpl.
intros H0 H1.
apply do_opt_some_inv in H0.
destruct H0 as ((
te',
e') &
Htee &
H0).
apply do_opt_some_inv in H0.
destruct H0 as ((
a',
al) &
Ha & ?).
simpl in *.
eq_some_inv.
subst a'.
apply do_opt_some_inv in H1.
destruct H1 as ((
a',
al') &
Ha' & ?).
simpl in *.
eq_some_inv.
subst a'.
specialize (
Q _ _ Ha').
simpl in Q.
elim (
proj2 Q).
clear Q.
apply get_stk_in in Htee.
eapply (
Inv.(
localValid));
eauto.
intros _.
exact (
Inv.(@
localInj _ _) (
f,
x) (
f',
x')
a).
+
simpl.
intros x b H.
destruct (
alloc_var_inj _ _ (
proj1 (
alloc_var_alt _ _ _ _)
Hal))
as (
Q &
_).
apply Q.
eapply Inv.(
globalValid);
eauto.
+
simpl.
intros t'
e' [
H|
H]
x b z H'.
eq_some_inv.
subst.
apply (
proj1 (
alloc_variables_load Hal _ H')).
destruct (
alloc_var_inj _ _ (
proj1 (
alloc_var_alt _ _ _ _)
Hal))
as (
Q &
_).
apply Q.
eapply Inv.(
localValid);
eauto.
+
intros ab b H o.
simpl.
pose proof (
proj1 (
alloc_var_alt _ _ _ _)
Hal)
as Hal'.
destruct ab as [
f x |
b' ].
revert H.
simpl.
rewrite get_stk_cons.
case Pos.eqb_spec.
intros ->.
simpl.
destruct (
e !
x)
as [(
b',
s)|]
eqn:
Hb';
simpl;
intro;
eq_some_inv.
subst b'.
now rewrite (
proj2 (
alloc_variables_load Hal x Hb')).
intros _ H.
generalize (
noIntFragment Inv (
ABlocal f x)
H o).
simpl.
assert (
Mem.valid_block m b)
as Hv.
destruct (
get_stk _ _)
as [(
t',
e')|]
eqn:
HIN;
simpl in H;
eq_some_inv.
apply get_stk_in in HIN.
destruct (
e' !
x)
as [(
b',
z')|]
eqn:
HX;
eq_some_inv;
subst.
apply (
Inv.(
localValid)
_ _ HIN _ HX).
rewrite (
proj1 (
proj2 (
alloc_var_guts _ Hal'
Hv))).
exact id.
generalize (
noIntFragment Inv (
ABglobal b')
H o).
simpl.
assert (
Mem.valid_block m b)
as Hv.
simpl in H.
destruct (
Genv.invert_symbol _ _)
as [
g|]
eqn:
Hg;
eq_some_inv;
subst b'.
eapply Inv.(
globalValid),
Genv.invert_find_symbol,
Hg.
rewrite (
proj1 (
proj2 (
alloc_var_guts _ Hal'
Hv))).
exact id.
Qed.
Lemma push_frame_sizes σ
sz vars m t'
e'
m' :
invariant ge ((
t',
e') :: σ,
m') →
list_norepet (
map fst vars) →
alloc_variables empty_env m vars e'
m' →
m ∈
sizes_gamma ge σ
sz →
m' ∈
sizes_gamma ge ((
t',
e') :: σ) (
set_local_sizes (
plength σ)
vars sz).
Proof.
Lemma push_frame_pt σ
tmp e'
ty :
type_gamma (
ptset_gamma ge σ)
ty ⊆
type_gamma (
ptset_gamma ge ((
tmp,
e') :: σ))
ty.
Proof.
intros ();
simpl;
try easy.
intros b i.
destruct ty as [ | | | | | [ |
ptr ] | [ |
ptr ] | ];
try exact id;
(
intros (
b' &
Hb' &
Hb);
exists b';
split; [
exact Hb' | ];
(
destruct b'
as [
f'
x|
b'];
simpl in *;
[
apply do_opt_some_inv in Hb;
destruct Hb as ((
t'',
e'') &
H &
Hb);
apply do_opt_some_inv in Hb;
destruct Hb as ((
b',
sz') &
Hb & ?);
eq_some_inv;
subst b';
rewrite (
get_stk_tail _ _ _ H);
simpl;
rewrite Hb;
reflexivity
|
now hsplit;
eq_some_inv;
subst;
rewrite Hb
])
).
Qed.
Section ARGS_MATCH.
Local Set Elimination Schemes.
Variables (
f:
ident) (
en :
env) (
tmp:
temp_env) (σ:
list (
temp_env *
env)) (
m:
mem) (ρ
n:
cell →
mach_num).
Inductive args_match :
list expr →
list val →
list (
type+⊤ *
list (
mexpr cell)) →
Prop :=
|
AMnil :
args_match nil nil nil
|
AMcons eargs vargs aargs e v ty ln me n :
v ≠
Vundef →
v ∈
eval_expr ge en tmp m (
expr_erase e) →
v ∈
toplift_gamma (
type_gamma (
ptset_gamma ge ((
tmp,
en) :: σ)))
ty →
In me ln →
n ∈
N.ncompat v →
n ∈
eval_mexpr ρ
n me →
(∀
x y,
ACtemp x y ∈
me_free_var me → (
x <
Pos.succ (
plength σ))%
positive) →
args_match eargs vargs aargs →
args_match (
e ::
eargs) (
v ::
vargs) ((
ty,
ln) ::
aargs)
.
Lemma am_a_cons_inv eargs vargs a aargs :
args_match eargs vargs (
a ::
aargs) →
∃
e eargs'
v vargs'
ty ln me n,
eargs =
e ::
eargs' ∧
vargs =
v ::
vargs' ∧
a = (
ty,
ln) ∧
v ≠
Vundef ∧
v ∈
eval_expr ge en tmp m (
expr_erase e) ∧
v ∈
toplift_gamma (
type_gamma (
ptset_gamma ge ((
tmp,
en) :: σ)))
ty ∧
In me ln ∧
n ∈ (
N.ncompat v ∩
eval_mexpr ρ
n me) ∧
(∀
x y,
ACtemp x y ∈
me_free_var me → (
x <
Pos.succ (
plength σ))%
positive) ∧
args_match eargs'
vargs'
aargs.
Proof.
inversion 1. repeat (econstructor (eauto)).
Qed.
End ARGS_MATCH.
Lemma load_undef {
m b} :
(∀
o,
ZMap.get o (
Mem.mem_contents m) !!
b =
Undef) →
∀ κ
o,
extend (
Mem.load κ
m b)
o =
Vundef.
Proof.
intros H κ
o.
simpl.
generalize (
Mem.load_result κ
m b o).
case Mem.load. 2:
reflexivity.
intros v Hv;
specialize (
Hv v eq_refl);
subst v.
destruct κ;
simpl;
rewrite !
H;
reflexivity.
Qed.
Lemma ab_bind_parameters_sound e t σ
m vars e'
m' :
invariant ge ((
t,
e) :: σ,
m) →
alloc_variables empty_env m vars e'
m' →
∀
params eargs aargs vargs ρ
n,
args_match e t σ
m ρ
n eargs vargs aargs →
∀
tmp tmp',
bind_parameters params vargs tmp =
Some tmp' →
∀
ab ab',
am_get (
ab_bind_parameters NumDom (
Pos.succ (
plength σ))
params aargs (
ret (
NotBot ab))) =
Some ab' →
mem_as_fun ge ((
tmp,
e') :: (
t,
e) :: σ,
m) ∈
points_to_gamma ge ((
tmp,
e') :: (
t,
e) :: σ) (
ab_tp ab) →
ρ
n ∈ (
compat (
mem_as_fun ge ((
tmp,
e') :: (
t,
e) :: σ,
m)) ∩ γ(
ab_num ab)) →
∃
q,
ab' =
NotBot q ∧
ab_stk q =
ab_stk ab ∧
ab_sz q =
ab_sz ab ∧
mem_as_fun ge ((
tmp',
e') :: (
t,
e) :: σ,
m') ∈
points_to_gamma ge ((
tmp',
e') :: (
t,
e) :: σ) (
ab_tp q) ∧
∃ ρ
n', ρ
n' ∈ (
compat (
mem_as_fun ge ((
tmp',
e') :: (
t,
e) :: σ,
m')) ∩ γ (
ab_num q)).
Proof.
intros INV Hm'.
induction params as [|
id params IH];
intros eargs aargs vargs ρ
n AM tmp tmp'
BIND ab ab'
AB_BIND TP (
CPT &
NM);
destruct ab as (
stk &
sz &
tp &
nm).
+
destruct aargs;
simpl in AB_BIND,
BIND;
unfold ret in AB_BIND;
eq_some_inv.
subst ab'.
destruct vargs;
eq_some_inv.
subst tmp'.
exists (
stk, (
sz, (
tp,
nm))).
split.
reflexivity.
split.
reflexivity.
split.
reflexivity.
split; [|
exists ρ
n;
split];
auto.
-
intros c.
generalize (
TP c).
simpl.
destruct (
ACTreeDom.get c tp)
as [|
ty].
exact id.
destruct c as [
f'
x ofs|
f'
x|
b ofs];
simpl.
rewrite !
get_stk_cons.
case (
Pos.eqb_spec).
simpl.
intros ->.
destruct (
e' !
x)
as [(
b,
h)|]
eqn:
Hx.
simpl.
pose proof (
alloc_var_inj _ _ (
proj1 (
alloc_var_alt _ _ _ _)
Hm'))
as (
_ &
Y &
_).
specialize (
Y _ _ Hx).
destruct Y as [
_ Y].
simpl in Y.
rewrite (
not_valid_block_load_None Y).
intros H.
apply type_gamma_inv'
in H.
contradiction.
exact id.
intros NE.
case (
Pos.eqb_spec).
simpl.
intros ->.
destruct (
e !
x)
as [(
b,
h)|]
eqn:
Hx.
simpl.
assert (
Mem.valid_block m b)
as Hb.
eapply INV.(
localValid).
left.
reflexivity.
exact Hx.
rewrite (
alloc_var_load _ (
proj1 (
alloc_var_alt _ _ _ _)
Hm')
Hb).
exact id.
exact id.
intros NE'.
destruct (
get_stk f' σ)
as [(
t'',
e'')|]
eqn:
Hf'.
simpl.
destruct (
e'' !
x)
as [(
b,
h)|]
eqn:
Hx.
simpl.
assert (
Mem.valid_block m b)
as Hb.
eapply INV.(
localValid).
right.
apply (
get_stk_in Hf').
exact Hx.
rewrite (
alloc_var_load _ (
proj1 (
alloc_var_alt _ _ _ _)
Hm')
Hb).
exact id.
exact id.
exact id.
exact id.
destruct (
Genv.invert_symbol ge b)
eqn:
B;
auto.
rewrite (
alloc_var_load _ (
proj1 (
alloc_var_alt _ _ _ _)
Hm') (
INV.(
globalValid)
_ (
Genv.invert_find_symbol _ _ B))).
exact id.
-
intros c.
generalize (
CPT c).
simpl.
destruct c as [
f'
x ofs|
f'
x|
b ofs];
simpl.
rewrite !
get_stk_cons.
case (
Pos.eqb_spec).
simpl.
intros ->.
destruct (
e' !
x)
as [(
b,
s)|]
eqn:
Hx.
simpl.
intros _.
pose proof (
load_undef (
proj2 (
alloc_variables_load Hm'
_ Hx)) (
proj1_sig κ)
ofs)
as X.
simpl in X.
rewrite X.
vauto.
exact id.
intros NE.
case (
Pos.eqb_spec).
simpl.
intros ->.
destruct (
e !
x)
as [(
b,
s)|]
eqn:
Hx.
simpl.
assert (
Mem.valid_block m b)
as Hb.
eapply INV.(
localValid).
left.
reflexivity.
exact Hx.
rewrite (
alloc_var_load _ (
proj1 (
alloc_var_alt _ _ _ _)
Hm')
Hb).
exact id.
exact id.
intros NE'.
destruct (
get_stk f' σ)
as [(
t'',
e'')|]
eqn:
Hf'.
simpl.
destruct (
e'' !
x)
as [(
b,
h)|]
eqn:
Hx.
simpl.
assert (
Mem.valid_block m b)
as Hb.
eapply INV.(
localValid).
right.
apply (
get_stk_in Hf').
exact Hx.
rewrite (
alloc_var_load _ (
proj1 (
alloc_var_alt _ _ _ _)
Hm')
Hb).
exact id.
exact id.
exact id.
exact id.
destruct (
Genv.invert_symbol ge b)
eqn:
B;
auto.
rewrite (
alloc_var_load _ (
proj1 (
alloc_var_alt _ _ _ _)
Hm') (
INV.(
globalValid)
_ (
Genv.invert_find_symbol _ _ B))).
exact id.
+
destruct aargs as [|
a aargs'].
simpl in AB_BIND;
unfold ret in AB_BIND;
eq_some_inv.
destruct (
am_a_cons_inv AM)
as
(
ex &
eargs' &
v &
vargs' &
ty &
ln &
me &
n & -> & -> & -> &
Def &
EV &
Vtp &
Hme & (
Ncpt &
EVn) &
Hfv &
AM').
assert (
args_match e t σ
m (
upd ρ
n (
ACtemp (
Pos.succ (
plength σ))
id)
n)
eargs'
vargs'
aargs')
as AM''.
{
clear -
AM'
Hfv.
induction AM'.
constructor.
econstructor;
eauto.
eapply eval_mexpr_fv. 2:
eassumption.
intros x H7.
unfold upd.
destruct (
eq_dec x);
auto.
subst.
specialize (
H5 _ _ H7).
Psatz.lia.
}
specialize (
IH _ _ _ _ AM''
_ _ BIND).
simpl in AB_BIND.
assert (
upd ρ
n (
ACtemp (
Pos.succ (
plength σ))
id)
n ∈ γ
(
union_list_map (λ
ne0,
AbMachineEnv.assign (
ACtemp (
Pos.succ (
plength σ))
id)
ne0 nm) (
NotBot nm)
ln)).
{
rewrite union_list_map_correct.
eapply union_list_correct.
refine _.
apply in_map,
Hme.
apply AbMachineEnv.assign_correct;
eauto. }
destruct (
union_list_map _ _ _)
as [|
nm']
eqn:
Hnm'.
contradiction.
specialize (
IH _ _ AB_BIND).
destruct IH as ((
stk' &
sz' &
tp' &
nm'') & -> &
Hstk' &
Hsz' &
Htp' &
Hq).
simpl.
*
intros c.
unfold ct_upd.
rewrite ACTreeDom.gsspec.
rewrite ct_forget_all_get.
destruct (
ACTree.elt_eq c).
subst c.
simpl.
rewrite get_stk_cons,
plength_cons.
rewrite Pos.eqb_refl.
simpl.
rewrite PTree.gss.
destruct ty.
exact I.
simpl.
apply push_frame_pt;
eauto.
destruct in_dec.
exact I.
simpl.
rewrite read_cell_upd.
generalize (
TP c).
simpl.
destruct (
ACTreeDom.get).
exact (λ
_,
I).
apply type_gamma_covariant,
ptset_gamma_tmp.
reflexivity.
rewrite plength_cons.
assumption.
*
split.
eapply (
N.compat_upd _ (λ
x,
x));
eauto.
intros c.
destruct (
eq_dec _ _).
subst.
simpl.
rewrite get_stk_cons,
plength_cons,
Pos.eqb_refl.
simpl.
rewrite PTree.gss.
exact eq_refl.
simpl.
rewrite read_cell_upd.
auto.
now rewrite plength_cons.
auto.
*
simpl in *.
subst.
eexists (
stk, (
sz, (
tp',
nm''))).
vauto.
Qed.
A (concrete) block is valid given a stack iff in this block is allocated
* either a global symbol s
* or a local variable x of a function f
Definition valid_block (
stk:
list (
temp_env *
env))
b :
Prop :=
(∃
s,
Genv.invert_symbol ge b =
Some s)
∨ (∃
t e x sz,
In (
t,
e)
stk ∧
e !
x =
Some (
b,
sz)).
Lemma valid_block_tmp stk stk' :
stacks_tmp stk stk' →
valid_block stk' ⊆
valid_block stk.
Proof.
intros H b [
Hb |
Hb];[
left;
exact Hb|
right].
hsplit.
apply (
stacks_tmp_in H)
in Hb.
hsplit.
vauto.
Qed.
Lemma pop_local_pt_get μ
pt c :
ACTree.get c (
pop_local_pt μ
pt) =
do ty <-
ACTree.get c pt;
if if is_local_cell μ
c
then false
else match ty with
| (
TyPtr (
Just bs) |
TyZPtr (
Just bs)) =>
negb (
BSO.existsb (
is_local_block μ)
bs)
|
TyPtr All |
TyZPtr All
|
TyFloat |
TySingle |
TyLong |
TyInt |
TyZero |
TyIntPtr =>
true
end
then Some ty
else None.
Proof.
Lemma pop_frame_pt τ₀ ε₀ σ
m m' (
tp:
points_to)
c:
(∀
b,
b ∈
valid_block σ →
(∀ κ
o,
Mem.load κ
m b o =
Mem.load κ
m'
b o)
) →
mem_as_fun ge ((τ₀, ε₀) :: σ,
m)
c ∈
toplift_gamma (
type_gamma (
ptset_gamma ge ((τ₀, ε₀) :: σ))) (
ACTreeDom.get c tp) →
mem_as_fun ge (σ,
m')
c ∈
toplift_gamma (
type_gamma (
ptset_gamma ge σ))
(
ACTreeDom.get c (
pop_local_pt (
plength σ)
tp)).
Proof.
intros Hb.
unfold ACTreeDom.get.
rewrite pop_local_pt_get.
simpl.
destruct (
ACTree.get c tp)
as [
ty|]. 2:
exact id.
destruct (
is_local_cell _ c)
eqn:
GL.
exact (λ
_,
I).
simpl.
match goal with |-
appcontext[
if ?
b then _ else _ ] =>
remember b as case eqn:
Hcase end.
revert Hcase.
case case;
clear case.
2:
exact (λ
_ _,
I).
intros Hcase.
symmetry in Hcase.
destruct c as [
f x ofs|
f x|
b ofs];
simpl in *.
-
destruct (
eq_dec _ _);
simpl in GL;
eq_some_inv.
clear GL.
rewrite get_stk_cons.
rewrite (
proj2 (
Pos.eqb_neq _ _));
auto.
destruct (
get_stk f σ)
as [(
t,
e)|]
eqn:
Hv. 2:
exact id.
simpl.
destruct (
e !
x)
as [(
b,
s)|]
eqn:
Hv'. 2:
exact id.
simpl.
rewrite Hb.
destruct (
Mem.load (
proj1_sig κ)
m'
b ofs)
as [()|];
simpl;
try exact id.
destruct ty as [ | | | | | [ |
ptr ] | [ |
ptr ] | ];
try exact id;
intros (
b' &
Hb' &
Hb'');
exists b'; (
split; [
exact Hb' | ]);
(
destruct b'
as [
g y|
b'''];
simpl in *;
eq_some_inv;
[ |
exact Hb'' ]);
revert Hb'';
rewrite get_stk_cons;
(
rewrite (
proj2 (
Pos.eqb_neq _ _)); [
exact id | ]);
apply negb_true_iff in Hcase;
rewrite BSO.existsb_forall in Hcase;
specialize (
Hcase _ Hb');
simpl in Hcase;
clear -
Hcase;
intros ->;
rewrite eq_dec_true in Hcase;
simpl in *;
eq_some_inv.
right.
repeat eexists.
exact (
get_stk_in Hv).
exact Hv'.
-
destruct (
eq_dec _).
simpl in GL;
eq_some_inv.
rewrite get_stk_cons.
rewrite (
proj2 (
Pos.eqb_neq _ _));
auto.
destruct (
get_stk f σ)
as [(
t,
e)|]
eqn:
Hv. 2:
exact id.
simpl.
destruct (
t !
x)
as [
v|]
eqn:
Hv'. 2:
exact id.
destruct v;
try exact id.
destruct ty as [ | | | | | [ |
ptr ] | [ |
ptr ] | ];
try exact id;
intros (
b' &
Hb' &
Hb'');
exists b'; (
split; [
exact Hb' | ]);
(
destruct b'
as [
g y|
b'''];
simpl in *;
eq_some_inv;
[ |
exact Hb'' ]);
revert Hb'';
rewrite get_stk_cons;
(
rewrite (
proj2 (
Pos.eqb_neq _ _)); [
exact id | ]);
apply negb_true_iff in Hcase;
rewrite BSO.existsb_forall in Hcase;
specialize (
Hcase _ Hb');
simpl in Hcase;
clear -
Hcase;
intros ->;
rewrite eq_dec_true in Hcase;
simpl in *;
eq_some_inv.
-
destruct (
Genv.invert_symbol ge b)
as [
s|]
eqn:
Hs. 2:
exact id.
rewrite Hb.
simpl.
destruct (
Mem.load (
proj1_sig κ)
m'
b ofs)
as [()|];
simpl;
try exact id.
destruct ty as [ | | | | | [ |
ptr ] | [ |
ptr ] | ];
try exact id;
intros (
b' &
Hb' &
Hb'');
exists b'; (
split; [
exact Hb' | ]);
(
destruct b'
as [
g y|
b'''];
simpl in *;
eq_some_inv;
[ |
exact Hb'' ]);
revert Hb'';
rewrite get_stk_cons;
(
rewrite (
proj2 (
Pos.eqb_neq _ _)); [
exact id | ]);
apply negb_true_iff in Hcase;
rewrite BSO.existsb_forall in Hcase;
specialize (
Hcase _ Hb');
simpl in Hcase;
clear -
Hcase;
intros ->;
rewrite eq_dec_true in Hcase;
simpl in *;
eq_some_inv.
left.
vauto.
Qed.
Lemma pop_frame_compat τ₀ ε₀ σ
m m' :
(∀
b,
b ∈
valid_block σ →
(∀ κ
o,
Mem.load κ
m b o =
Mem.load κ
m'
b o)
) →
compat (
mem_as_fun ge ((τ₀, ε₀) :: σ,
m)) ⊆
compat (
mem_as_fun ge (σ,
m')).
Proof.
intros Hb ρ
H c.
-
generalize (
H c).
destruct c as [
f x|
f x|
b];
simpl.
+
destruct (
get_stk f σ)
as [(
t,
e)|]
eqn:
Hv. 2:
exact (λ
_,
I).
rewrite (
get_stk_tail _ _ _ Hv).
simpl.
destruct (
e !
x)
as [(
b,
s)|]
eqn:
Hv'. 2:
exact id.
simpl.
rewrite Hb.
exact id.
right.
repeat eexists;
eauto.
exact (
get_stk_in Hv).
+
destruct (
get_stk f σ)
as [(
t,
e)|]
eqn:
Hv. 2:
exact (λ
_,
I).
simpl.
rewrite (
get_stk_tail _ _ _ Hv).
exact id.
+
destruct (
Genv.invert_symbol ge b)
eqn:
Hv. 2:
exact id.
rewrite Hb.
exact id.
left.
vauto.
Qed.
Lemma pop_frame_invariant τ₀ ε₀ σ
m m':
invariant ge ((τ₀, ε₀) :: σ,
m) →
(∀
b,
b ∈
valid_block σ →
(∀
lo hi p,
Mem.range_perm m b lo hi Cur p →
Mem.range_perm m'
b lo hi Cur p) ∧
(
b ∈
Mem.valid_block m →
b ∈
Mem.valid_block m')
) →
Mem.mem_contents m =
Mem.mem_contents m' →
invariant ge (σ,
m').
Proof.
intros INV HB Hc.
split.
-
intros t0 e H b hi H0.
simpl.
apply HB.
simpl in H.
right.
unfold blocks_of_env in H0.
rewrite in_map_iff in H0.
destruct H0 as ((
x &
b' &
s') &
Hb' &
Hx).
simpl in Hb'.
eq_some_inv.
subst.
apply PTree.elements_complete in Hx.
repeat econstructor;
eauto.
eapply INV.
right.
exact H.
easy.
-
intros t0 e H.
eapply INV.
right.
exact H.
-
intros x x'
a H H'.
generalize (
INV.(@
localInj _ _)
x x'
a).
destruct x as (
f,
x),
x'
as (
f',
x').
simpl in *.
destruct (
get_stk f σ)
as [(
t,
e)|]
eqn:
Hte;
eq_some_inv.
rewrite (
get_stk_tail _ _ _ Hte).
destruct (
get_stk f' σ)
as [(
t',
e')|]
eqn:
Hte';
eq_some_inv.
rewrite (
get_stk_tail _ _ _ Hte').
simpl in *.
auto.
-
intros x b H.
generalize (
INV.(
globalValid)
_ H).
simpl.
refine (
proj2 (
HB _ _)).
left.
apply Genv.find_invert_symbol in H.
vauto.
-
intros t0 e H x b z H0.
apply HB.
vauto2.
eapply INV.(
localValid);
eauto.
right.
eassumption.
-
simpl.
intros ab b H o.
assert (
block_of_ablock ge ((τ₀, ε₀) :: σ)
ab =
Some b)
as H'.
{
destruct ab as [
f x |
b' ]. 2:
exact H.
simpl.
rewrite get_stk_cons.
case Pos.eqb_spec. 2:
intros _;
exact H.
intros ->.
exfalso.
revert H.
simpl.
generalize (
get_stk_lt (
plength σ) σ).
case get_stk.
intros p X _;
specialize (
X _ eq_refl).
apply Plt_ne in X.
exact (
X eq_refl).
intros;
eq_some_inv. }
generalize (
INV.(
noIntFragment)
ab H'
o).
simpl.
rewrite Hc.
exact id.
Qed.
Lemma pop_frame_sizes τ₀ (ε₀:
env) σ
m m' (
sz:
sizes) ε':
invariant ge ((τ₀, ε₀) :: σ,
m) →
(∀
b,
b ∈
valid_block σ →
(∀
lo hi p,
Mem.range_perm m b lo hi Cur p →
Mem.range_perm m'
b lo hi Cur p)
) →
m ∈
sizes_gamma ge ((τ₀, ε₀) :: σ)
sz →
m' ∈
sizes_gamma ge σ (
clear_local_sizes (
plength σ) ε'
sz).
Proof.
intros INV HB SZ.
intros b hi perm vol b'.
rewrite clear_local_sizes_get.
intros Hhi Hb.
split.
-
eapply HB;[|
eapply (
SZ b hi perm vol b')];
destruct b as [
f x|
b];
simpl in Hb;
unfold is_local in Hb;
eq_some_inv;
auto.
destruct (
get_stk f σ)
as [(
t,
e)|]
eqn:
Hv;
eq_some_inv.
destruct (
e !
x)
as [(
b,
s)|]
eqn:
Hv';
eq_some_inv.
right.
subst.
repeat econstructor.
exact (
get_stk_in Hv).
exact Hv'.
left.
destruct (
Genv.invert_symbol ge b)
eqn:
Hs;
eq_some_inv;
subst.
vauto.
revert Hhi.
destruct (
peq _ f &&
PSet.mem x ε').
discriminate.
auto.
simpl.
destruct (
get_stk f σ)
as [(
t,
e)|]
eqn:
Hv;
eq_some_inv.
now rewrite (
get_stk_tail _ _ _ Hv).
-
specialize (
SZ b).
destruct b as [ μ'
x |
g ].
destruct (
peq _ _).
+
clear SZ.
simpl in Hb.
generalize (
get_stk_lt μ' σ).
destruct (
get_stk _ _).
intros X.
specialize (
X _ eq_refl).
subst.
Psatz.lia.
eq_some_inv.
+
simpl in Hhi.
apply (
SZ _ _ _ b'
Hhi).
simpl.
rewrite get_stk_cons, (
proj2 (
Pos.eqb_neq _ _));
auto.
+
apply (
SZ _ _ _ b'
Hhi Hb).
Qed.
Lemma free_list_ex tmp env stk m :
invariant ge ((
tmp,
env) ::
stk,
m) →
∃
m',
Mem.free_list m (
blocks_of_env env) =
Some m' ∧
∀
b,
valid_block stk b →
(∀ κ
ofs,
Mem.load κ
m b ofs =
Mem.load κ
m'
b ofs) ∧
(∀
lo hi p,
Mem.range_perm m b lo hi Cur p →
Mem.range_perm m'
b lo hi Cur p) ∧
(
b ∈
Mem.valid_block m →
b ∈
Mem.valid_block m').
Proof.
intros INV.
simpl in *.
assert (∀
x x'
b,
fmap fst env !
x =
Some b →
fmap fst env !
x' =
Some b →
x =
x')
as INJ.
{
intros x x'
b H H0.
pose proof (
INV.(@
localInj _ _) (
plength stk,
x) (
plength stk,
x')
b)
as INJ'.
simpl in INJ'.
rewrite (
get_stk_length)
in INJ'.
simpl in INJ'.
specialize (
INJ'
H H0).
eq_some_inv.
assumption.
}
assert (∀
x f'
x'
b b',
fmap fst env !
x =
Some b →
(
do t_e <-
get_stk f'
stk;
fmap fst (
snd t_e) !
x') =
Some b' →
b ≠
b')
as INJ₀.
{
intros x f'
x'
b b'
H H0 <-.
pose proof (
INV.(@
localInj _ _) (
plength stk,
x) (
f',
x')
b)
as INJ'.
simpl in INJ'.
rewrite get_stk_length in INJ'.
destruct (
get_stk f'
stk)
as [(
t,
e)|]
eqn:
Hte;
eq_some_inv.
rewrite (
get_stk_tail _ _ _ Hte)
in INJ'.
simpl in INJ'.
specialize (
INJ'
H H0).
simpl in *.
eq_some_inv.
subst.
apply get_stk_lt in Hte.
Psatz.lia.
}
assert (
injective_map (λ
x_v :
ident *
positive,
do t_e <-
get_stk (
fst x_v)
stk;
fmap fst (
snd t_e) ! (
snd x_v)))
as INJ₁.
{
intros (
f,
x) (
f',
x').
simpl.
intros a H H0.
pose proof (
INV.(@
localInj _ _) (
f,
x) (
f',
x')
a)
as INJ'.
simpl in *.
destruct (
get_stk f stk)
as [(
t,
e)|]
eqn:
Hte;
eq_some_inv.
rewrite (
get_stk_tail _ _ _ Hte)
in INJ'.
destruct (
get_stk f'
stk)
as [(
t',
e')|]
eqn:
Hte';
eq_some_inv.
rewrite (
get_stk_tail _ _ _ Hte')
in INJ'.
simpl in INJ'.
auto.
}
generalize (
INV.(
localFreeable)
_ _ (
or_introl eq_refl)).
generalize (
INV.(
localNotGlobal)
_ _ (
or_introl eq_refl)).
setoid_rewrite (
ptree_get_assoc env).
generalize (λ
t e H,
INV.(
localFreeable)
t e (
or_intror H)).
generalize (λ
t e H,
INV.(
localNotGlobal)
t e (
or_intror H)).
setoid_rewrite (
ptree_get_assoc env)
in INJ.
setoid_rewrite (
ptree_get_assoc env)
in INJ₀.
generalize (
PTree.elements_keys_norepet env).
unfold blocks_of_env in *.
generalize dependent (
PTree.elements env).
simpl.
clear INV env.
intros l.
revert m.
induction l as [|(
x, (
b,
hi))
l IH].
intros m _ _ _ _.
simpl.
vauto.
intros m INJ INJ₀
NR'
LG LF LG'
LF'.
simpl in *.
inv NR'.
destruct (
Mem.free m b 0
hi)
as [
m₁|]
eqn:
M₁.
destruct (
IH m₁)
as (
m' &
M' &
IH');
clear IH.
+
intros x0 x'
b0 H H0.
specialize (
INJ x0 x'
b0).
assert (
x ≠
x0).
{
intros ->.
generalize (
assoc_in x0 l).
destruct (
assoc x0 l).
intros X.
specialize (
X _ eq_refl).
apply H1.
rewrite in_map_iff.
eexists (
x0,
_).
vauto.
simpl in *.
eq_some_inv.
}
assert (
x ≠
x').
{
intros ->.
generalize (
assoc_in x'
l).
destruct (
assoc x'
l).
intros X.
specialize (
X _ eq_refl).
apply H1.
rewrite in_map_iff.
eexists (
x',
_).
vauto.
simpl in *.
eq_some_inv.
}
rewrite !
dec_eq_false in INJ;
auto.
+
intros x0 f'
x'
b0 b'
H H0.
specialize (
INJ₀
x0 f'
x'
b0 b').
rewrite dec_eq_false in INJ₀.
eauto.
intros ->.
generalize (
assoc_in x0 l).
destruct (
assoc x0 l).
intros X.
specialize (
X _ eq_refl).
apply H1.
rewrite in_map_iff.
eexists (
x0,
_).
vauto.
simpl in *.
eq_some_inv.
+
eauto.
+
eauto.
+
intros t0 e H b0 hi0 H0 ofs X.
specialize (
LF _ _ H _ _ H0 ofs X).
eapply Mem.perm_free_1;
eauto.
left.
rewrite in_map_iff in H0.
destruct H0 as ((
x' &
b' &
sz) & ? &
H').
simpl in *.
eq_some_inv.
subst.
cut (
b ≠
b0).
auto.
apply in_get_stk in H.
destruct H as (
n &
Hn).
apply (
INJ₀
x n x').
rewrite dec_eq_true.
reflexivity.
apply (
In_norepet_assoc _ _ _ (
PTree.elements_keys_norepet _))
in H'.
rewrite Hn.
simpl.
rewrite ptree_get_assoc.
simpl.
unfold PTree.elt in *.
now rewrite H'.
+
intros x0 b0 y b'
z H H0.
eapply (
LG'
_ _ y);
try eassumption.
rewrite dec_eq_false.
eassumption.
intros ->.
apply H1.
apply assoc_in in H0.
rewrite in_map_iff.
eexists (
y,
_).
vauto.
+
intros b0 hi0 H ofs Hofs.
eapply Mem.perm_free_1;
eauto.
left.
rewrite in_map_iff in H.
destruct H as ((
x' &
b' &
sz) &
H &
H').
simpl in *.
eq_some_inv.
intro;
subst.
destruct (
eq_dec x x').
subst.
apply H1.
rewrite in_map_iff.
eexists (
x',
_).
vauto.
specialize (
INJ x x'
b).
apply (
In_norepet_assoc _ _ _ H2)
in H'.
rewrite dec_eq_true,
dec_eq_false in INJ;
auto.
unfold PTree.elt in *.
rewrite H'
in INJ.
specialize (
INJ eq_refl eq_refl).
auto.
eapply LF'.
vauto.
eauto.
+
exists m'.
split.
easy.
intros b0 [(
s &
H0)|(
t &
e &
y &
sz &
LOC &
H0)].
-
assert (
b0 ≠
b).
{
eapply LG';
eauto.
apply Genv.invert_find_symbol;
eauto.
rewrite dec_eq_true.
reflexivity. }
split;[|
split].
*
intros κ
ofs.
etransitivity. 2:
eapply IH';
vauto.
clear IH'.
symmetry.
eapply Mem.load_free;
eauto.
*
intros lo0 hi0 p H'.
eapply IH'.
vauto.
intros ofs Hofs;
eapply Mem.perm_free_1;
eauto.
*
intros H5.
eapply IH'.
vauto.
eapply Mem.valid_block_free_1;
eauto.
-
assert (
b0 ≠
b).
{
apply (
in_get_stk)
in LOC.
destruct LOC as (
f &
Hf).
generalize (
INJ₀
x f y b b0).
rewrite dec_eq_true.
intros X.
specialize (
X eq_refl).
rewrite Hf in X.
simpl in *.
rewrite H0 in X.
specialize (
X eq_refl).
auto. }
split;[|
split].
*
etransitivity. 2:
eapply IH';
eauto.
clear IH'.
symmetry.
eapply Mem.load_free;
eauto.
vauto2.
*
intros lo0 hi0 p H5.
eapply IH'.
vauto2.
intros ofs Hofs;
eapply Mem.perm_free_1;
eauto.
*
intros H5.
eapply IH'.
vauto2.
eapply Mem.valid_block_free_1;
eauto.
+
Transparent Mem.free.
unfold Mem.free in M₁.
Opaque Mem.free.
destruct Mem.range_perm_dec;
eq_some_inv.
intuition.
Qed.
Lemma nm_forget_all_weaken cells nm :
γ(
nm) ⊆ γ(
nm_forget_all NumDom cells nm).
Proof.
Lemma pop_local_num_correct μ ε τ
sz nm:
γ
nm ⊆ γ(
pop_local_num NumDom μ ε τ
sz (
NotBot nm)).
Proof.
Lemma ab_alloc_global_ex:
∀
ab gv id m ab'
log,
ab_alloc_global NumDom ge (
Genv.perm_globvar gv) (
gvar_volatile gv) (
Mem.nextblock m)
gv.(
gvar_init)
ab = (
ab', (
nil,
log)) ->
∃
m',
Genv.alloc_global ge m (
id,
Gvar gv) =
Some m'.
Proof.
Lemma ab_alloc_globals_ex:
∀
gl b ab log,
ab_alloc_globals NumDom ge gl = ((
b,
ab), (
nil,
log)) ->
∃
m,
Genv.alloc_globals ge Mem.empty gl =
Some m /\
Mem.nextblock m =
b.
Proof.
induction gl using rev_ind.
-
simpl.
intros.
inv H.
eauto.
-
intros ab.
unfold ab_alloc_globals.
rewrite am_fold_app.
apply am_bind_case.
intros;
eq_some_inv;
subst;
eauto.
intros;
eq_some_inv.
intros [
b ab']
log Hbab'.
destruct (
IHgl _ _ _ Hbab')
as (
m &
Hm &
Ham).
subst b.
erewrite <-
Genv.alloc_globals_app;
eauto.
simpl.
unfold am_fold.
simpl.
pose proof Genv.alloc_global_nextblock ge x m.
destruct x as [
id [
gf|
gv]].
simpl in *.
+
intros.
destruct (
Mem.alloc m 0 1)
as [
m'
b0]
eqn:
EQm'.
edestruct alloc_can_drop as [
m''
Hm''].
eauto.
rewrite Hm''.
eexists.
split.
eauto.
rewrite H.
inv H0.
auto.
auto.
+
apply am_bind_case.
intros;
eq_some_inv;
subst;
eauto.
intros;
eq_some_inv.
intros ab''
log'
Hab''
b'
log''
eq.
eq_some_inv.
subst.
edestruct ab_alloc_global_ex as [
m'
Hm'];
eauto.
rewrite Hm'.
eauto.
Qed.
Lemma init_mem_sound :
∀ (
defs :
list (
ident *
globdef fundef unit)) (
a :
option concrete_state),
Init_Mem ge defs a → γ (
AbMemSignatureCsharpminor.init_mem _ defs)
a.
Proof.
intros defs a (
prog &
Hge &
Hdefs &
H).
simpl.
subst defs.
unfold init_mem.
eapply am_assert_spec.
eauto.
constructor.
intro.
apply am_bind_case.
eauto.
constructor.
intros [
b ab]
log AAG.
simpl.
edestruct ab_alloc_globals_ex as (
m &
EQm &
NEXT).
eauto.
erewrite H by eauto.
rewrite Hge in EQm.
apply norepet_map_iff in H0.
eapply ab_alloc_globals_ok in AAG;
eauto.
destruct AAG.
destruct ab as [|
ab].
contradiction.
destruct ab as (
stk, (
sz, (
tp,
nm))).
destruct H2 as (? & ? & ? & ?).
simpl in *.
subst stk.
split;[| | |
split];
auto.
+
vauto.
+
intros _.
split;
try easy.
intros x b0 Hb0.
subst ge.
eapply Genv.find_symbol_not_fresh;
eauto.
intros ab b0 H3.
exact (
init_mem_no_int_fragment prog EQm b0).
Qed.
Ltac ung :=
repeat
match goal with
|
G : γ
_ _ |-
_ =>
unfold γ
in G
|
G :
t_gamma ?
a ?
b |-
_ =>
let STK :=
fresh "
STK"
in
let INV :=
fresh "
INV"
in
let SZ :=
fresh "
SZ"
in
let TPNM :=
fresh "
TPNM"
in
destruct G as [
STK INV SZ TPNM]
|
G : ?
NOTALL ≠
All →
_ |-
_ =>
let HH :=
fresh "
HH"
in
assert (
HH:
NOTALL ≠
All)
by discriminate;
specialize (
G HH);
clear HH
|
G :
stack_elt_gamma _ (
_,
_) |-
_ =>
destruct G
|
G :
stack_elt_gamma _ ?
a |-
_ =>
destruct a as (? & ?);
destruct G
|
G :
list_gamma _ _ (
_ ::
_) |-
_ =>
apply gamma_cons_inv in G;
destruct G as (? & ? & ? & ? &
G)
|
G :
list_gamma _ (
_ ::
_)
_ |-
_ =>
apply gamma_cons_inv_r in G;
destruct G as (? & ? & ? & ? &
G)
|
G :
list_gamma _ nil _ |-
_ =>
apply gamma_nil_r in G
|
G :
list_gamma _ _ nil |-
_ =>
apply gamma_nil_l in G
|
G :
MemCsharpminor.tnum_gamma _ _ _ _ _ |-
_ =>
let TP :=
fresh "
TP"
in
let ρ
n :=
fresh "ρ
n"
in
let CPT :=
fresh "
CPT"
in
let NM :=
fresh "
NM"
in
destruct G as (
TP & ρ
n &
CPT &
NM)
end.
Lemma forget_temp_sound x t e stk m σ
ab :
((
t,
e) ::
stk,
m) ∈ γ (
Just σ,
ab) →
∀
v, ((
PTree.set x v t,
e) ::
stk,
m) ∈ γ (
forget_cell NumDom (
Just σ,
ab) (
ACtemp (
plength stk)
x)).
Proof.
Lemma list_gamma_len {
t B} {
G:
gamma_op t B} {
x y} :
list_gamma G x y →
plength x =
plength y.
Proof.
Lemma noerror_correct e ab :
match am_get (
noerror NumDom ge max_concretize e ab)
with
|
Some tt => ∀
tmp env stk m, ((
tmp,
env) ::
stk,
m) ∈ γ(
ab) →
∃
v,
eval_expr ge env tmp m (
expr_erase e)
v ∧
v ≠
Vundef
|
None =>
True
end.
Proof.
Existing Instance UnitGamma.
Lemma noerror_sound: ∀
e ab,
Noerror ge e (γ
ab) ⊆ γ (
noerror NumDom ge max_concretize e ab).
Proof.
intros q ab.
generalize (
noerror_correct q ab).
destruct (
noerror _ _ _ q ab)
as ((), ([|],?)).
2:
exact (λ
_ _ _,
I).
intros X a [
t e s m H Nb].
specialize (
X t e s m H).
destruct X as (
v &
V &
Def).
specialize (
Nb _ V Def).
rewrite Nb;
reflexivity.
Qed.
Existing Instance boolean_partitionning.
Lemma assume_sound :
∀ (
e :
expr) (
ab :
t) (
a :
option (
bool *
concrete_state)),
Assume ge e (γ
ab)
a → γ (
assume _ ge max_concretize e ab)
a.
Proof.
intros e ([|[|(ε,τ) σ]] &
sz & (
tp &
nm))
cs ASSUME;
try exact I.
destruct ASSUME as [
t'
e'
s m H K].
ung.
simpl in *.
ung.
eq_some_inv.
subst x x0.
unfold assume.
simpl.
apply am_bind_case.
easy.
intros;
exact I.
intros ((
tp',
nm'),
nc)
log'
NC.
assert (
TN : (
mem_as_fun ge ((
t',
e') ::
s,
m)) ∈
tnum_gamma _ ge ((
t',
e') ::
s) (
tp,
nm))
by exact (
conj TP (
ex_intro _ _ (
conj CPT NM))).
generalize (
nconvert_sound _ max_concretize _ eq_refl (
env_ok _ _ H0)
INV SZ (
tp,
nm)
TN (
bool_expr e)).
rewrite (
list_gamma_len STK)
in NC.
simpl.
rewrite NC.
intros (
MONO &
NB).
destruct (
NoError.noerror_eval_expr_def NB)
as (
v &
DEF &
EV).
assert (
Hb:∃
b,
v =
Val.of_bool b ∧ ∃
v',
eval_expr ge e'
t'
m (
expr_erase e)
v' ∧
Val.bool_of_val v'
b).
{
clear -
EV DEF.
assert (∀
v b,
Val.cmp_bool Cne v (
Vint Int.zero) =
Some b →
Val.bool_of_val v b).
{
clear.
intros [ |
i |
i |
f |
f |
b i ];
simpl;
intros;
eq_some_inv.
subst.
constructor. }
destruct e as [ ? | ? | ? | ? |
op ? ? | ? ? ];
try destruct op;
simpl in EV;
NoError.eval_expr_inv;
simpl in *;
eq_some_inv;
subst;
unfold Val.cmp,
Val.cmpu,
Val.cmpf,
Val.cmpfs in *;
try
match goal with
|-
appcontext[
Val.of_optbool ?
o ] =>
let b :=
fresh in
destruct o as [
b | ]
eqn:
K;
[ |
elim (
DEF eq_refl) ];
exists b;
split;
[
reflexivity | ];
eexists;
split; [
repeat (
econstructor;
eauto) |
eauto ];
eauto
end.
unfold Val.cmp;
rewrite K;
simpl;
bif;
constructor.
unfold Val.cmpu;
rewrite K;
simpl;
bif;
constructor.
unfold Val.cmpf;
rewrite K;
simpl;
bif;
constructor.
unfold Val.cmpfs;
rewrite K;
simpl;
bif;
constructor.
unfold Val.cmpl in EV.
destruct (
Val.cmpl_bool _ _ _)
eqn:
K;
simpl in EV;
eq_some_inv;
subst.
eexists.
split.
reflexivity.
eexists.
split.
repeat (
econstructor;
simpl;
eauto).
unfold Val.cmpl;
rewrite K;
reflexivity.
destruct b;
constructor.
unfold Val.cmplu in EV.
destruct (
Val.cmplu_bool _ _ _)
eqn:
K;
simpl in EV;
eq_some_inv;
subst.
eexists.
split.
reflexivity.
eexists.
split.
repeat (
econstructor;
simpl;
eauto).
unfold Val.cmplu;
rewrite K;
reflexivity.
destruct b;
constructor.
}
destruct Hb as (
b & -> &
v' &
EV' &
Hb).
specialize (
K _ b Hb EV').
rewrite K.
set (
f b :=
do z <-
nassume NumDom b nm'
id nc;
NotBot (
AbMem (
Just ((ε, τ) :: σ))
sz tp'
z)).
fold (
f true).
fold (
f false).
apply boolean_partition.
unfold f.
clear f.
destruct (
tnum_m_stronger MONO (
conj (
Pun.mem_as_fun_pun_u8 _ _ INV.(
noIntFragment))
TN))
as (
TP' & (ρ
n' &
Nc' &
NM')).
generalize (
nconvert_ex NumDom max_concretize ε
sz eq_refl (
env_ok _ _ H0)
INV (
tp,
nm)
TN (
bool_expr e)).
rewrite NC.
simpl.
intros (
MONO' &
lpe &
Hlpe &
X).
specialize (
X _ EV DEF TP'
_ Nc'
NM').
destruct X as (
pe &
lme' &
me &
n &
INp &
Hpe &
Hlme' &
Hpn &
INn &
Hn &
Hnty &
ME).
refine ((λ
X Y,
botbind_spec _ _ _ Y _ X)
_ _).
eapply nassume_correct.
exact NM'.
eauto.
destruct b;
inv Hn;
exact ME.
intros a'
A'.
constructor.
red.
simpl.
econstructor;
auto.
auto.
auto.
split.
auto.
eauto.
Qed.
Ltac ssubst :=
repeat
match goal with
|
H : ?
a = ?
b |-
_ =>
first [
subst a |
subst b]
end.
Lemma ab_eval_expr_correct (
ab: @
t num)
stk m (
G: (
stk,
m) ∈ γ
ab)
e :
match am_get (
ab_eval_expr _ ge max_concretize ab e)
with
|
Some res =>
match res with
|
NotBot (
tn,
ty,
ln) =>
tnum_mono NumDom ge stk (
ab_nm ab)
tn ∧
∃
env tmp stk',
stk = (
tmp,
env) ::
stk' ∧
∀ ρ',
ρ' ∈
compat (
mem_as_fun ge (
stk,
m)) →
ρ' ∈ γ(
snd tn) →
∃
v,
eval_expr ge env tmp m (
expr_erase e)
v ∧
v ≠
Vundef ∧
v ∈ (
toplift_gamma (
type_gamma (
ptset_gamma ge stk))
ty) ∧
∃
me n,
In me ln ∧
N.ncompat v n ∧
(∀
x y :
ident,
me_free_var me (
ACtemp x y) → (
x <
Pos.succ (
plength stk'))%
positive) ∧
eval_mexpr ρ'
me n
|
Bot =>
False
end
|
None =>
True
end.
Proof.
unfold ab_eval_expr.
destruct ab as ([|[|(ε, τ) σ]] &
sz &
tp &
nm);
try exact I.
simpl.
apply am_bind_case.
easy.
vauto.
intros ((
tp',
nm'),
lpe)
log LPE.
apply am_bind_case.
easy.
vauto.
intros lme log'
LME.
ung.
assert (
TN :
mem_as_fun ge (
stk,
m) ∈
tnum_gamma _ ge stk (
tp,
nm))
by exact (
conj TP (
ex_intro _ ρ
n (
conj CPT NM))).
simpl in *.
ung.
destruct x.
subst.
simpl in *.
pose proof (
env_ok _ _ H0)
as Tmp.
generalize (
convert_to_me NumDom max_concretize _ (
list_gamma_len STK)
Tmp INV SZ (
tp,
nm)
TN e).
simpl.
rewrite LPE.
simpl.
rewrite LME.
intros (
MONO &
v &
V &
DEF &
H).
destruct (
MONO _ (
Pun.mem_as_fun_pun_u8 _ _ INV.(
noIntFragment)) (
conj TP (
ex_intro _ _ (
conj CPT NM))))
as (
TP' &
NM').
destruct lpe as [|
pe₀
lpe].
-
hsplit.
edestruct H;
eauto.
apply NM';
auto.
hsplit.
auto.
-
rewrite union_list_map_correct.
match goal with |-
appcontext[
union_list _ (
map ?
f _) ] =>
set (
func :=
f )
end.
Opaque union_list.
simpl.
split.
exact MONO.
eexists _,
_,
_.
split.
reflexivity.
clear NM'.
intros ρ'
CPT'
NM'.
specialize (
H TP' ρ'
CPT'
NM').
destruct H as (
pe &
lme' &
me &
n &
Hpe &
Hv &
Hme &
Hlme &
Hlme' &
Nvn &
Htn &
Hn).
exists v.
split.
exact V.
split.
exact DEF.
pose proof (
in_map func _ _ Hpe)
as IN.
split.
apply (@
union_list_correct (
_+⊤)
val All (
toplift_gamma ((
type_gamma (
ptset_gamma ge ((
t,
e0) ::
x0)))))
_ _ _ _ v IN).
eapply (
pt_eval_pexpr_correct (
list_gamma_len STK)
_ Hv).
clear -
DEF.
destruct v;
apply (
DEF eq_refl) ||
exact I.
exists me,
n.
split.
eauto.
split.
assumption.
split. 2:
now intuition.
intros x y FV.
destruct (
N.nconvert_fv _ _ _ _ _ _ _ _ NumDom sz _ _ _ _ Hme _ Hlme'
_ FV)
as (? &
FV' & <- ).
assert (
HT:=
convert_free_def NumDom max_concretize (
plength σ) ε
sz Tmp INV e (
tp,
nm)
TN).
rewrite LPE in HT.
specialize (
HT _ Hpe _ FV').
revert HT.
simpl.
generalize (
TP (
ACtemp x y)).
simpl.
destruct (
get_stk _ _)
as [ (?, ?) | ]
eqn:
Hk.
intros _ _.
generalize (
get_stk_lt _ _ Hk).
rewrite plength_cons.
Psatz.lia.
intros _ X.
elim (
X eq_refl).
Grab Existential Variables.
eauto.
Transparent join.
Qed.
Lemma ab_eval_exprlist_correct ε τ σ
m :
∀
eargs (
ab: @
t num) (
Hstk:
ab_stk ab ≠
All) (
G: ((τ, ε) :: σ,
m) ∈ γ
ab),
match am_get (
ab_eval_exprlist NumDom ge max_concretize ab eargs)
with
|
None =>
True
|
Some Bot =>
False
|
Some (
NotBot (
ab',
aargs)) =>
ab_stk ab =
ab_stk ab' ∧
ab_sz ab =
ab_sz ab' ∧
tnum_mono NumDom ge ((τ,ε) :: σ) (
ab_nm ab) (
ab_nm ab')
∧
∀ ρ
n,
ρ
n ∈
compat (
mem_as_fun ge ((τ, ε) :: σ,
m)) →
ρ
n ∈ γ (
ab_num ab) →
∃
vargs,
eval_exprlist ge ε τ
m (
List.map expr_erase eargs)
vargs ∧
args_match ε τ σ
m ρ
n eargs vargs aargs
end.
Proof.
induction eargs as [ |
e eargs IH ];
intros ab Hstk G.
-
split.
auto.
split.
auto.
split.
auto.
apply tnum_mono_refl.
intuition vauto2.
-
simpl.
apply am_bind_case.
easy.
intros;
exact I.
pose proof (
ab_eval_expr_correct G e)
as X.
intros [ | (((
tp,
nm),
ty),
margs) ]
log K;
rewrite K in X.
exact X.
destruct X as (
MONO & (
i &
j &
k & ? &
X)).
eq_some_inv.
subst i j k.
apply am_bind_case.
easy.
intros;
exact I.
assert (
t_gamma (
with_tnum (λ
_ :
tnum, (
tp,
nm))
ab) ((τ, ε) :: σ,
m))
as G'.
{
destruct ab as (
stk &
sz &
tp₀ &
nm₀).
simpl in *.
ung.
simpl in *.
unfold with_tnum.
split;
vauto;
eauto.
destruct (
MONO _ (
Pun.mem_as_fun_pun_u8 _ _ (
noIntFragment (
INV Hstk)))).
split.
auto.
eauto.
split.
auto.
eauto.
}
specialize (
IH (
with_tnum (λ
_ :
tnum, (
tp,
nm))
ab)
Hstk G').
intros [ | (
ab',
aargs') ]
log'
K';
rewrite K'
in IH.
exact IH.
destruct IH as (? & ? &
MONO' &
IH).
split.
auto.
split.
auto.
split.
eauto using tnum_mono_trans.
destruct ab'
as (
stk' &
sz' &
tp' &
nm').
simpl in *.
intros ρ
n CPT NM.
destruct ab as (
stk &
sz &
tp₀ &
nm₀).
simpl in *.
ung.
simpl in *.
specialize (
INV Hstk).
destruct (
MONO _ (
Pun.mem_as_fun_pun_u8 _ _ (
noIntFragment INV)))
as
(
TPm &
NMm).
vauto.
specialize (
X ρ
n CPT (
NMm _ CPT NM)).
destruct X as (
v &
EV &
Def &
TY &
me &
n &
Hme &
Hvn &
FV &
MEV).
specialize (
IH ρ
n CPT).
destruct IH as (
vargs &
Hvargs &
IH').
apply NMm;
eauto.
exists (
v ::
vargs).
split.
vauto.
econstructor;
eauto.
Qed.
Global Opaque ab_eval_exprlist.
Existing Instance stack_elt_gamma.
Lemma assign_in_correct (μ:
fname) (
x:
ident) (
a:
expr) (
ab:
t)
stk m :
(
stk,
m) ∈ γ(
ab) →
match am_get (
assign_in NumDom ge max_concretize μ
x a ab)
with
|
Some ab' =>
match ab'
with
|
Bot =>
False
|
NotBot ab' =>
ab_stk ab =
ab_stk ab' ∧
ab_sz ab =
ab_sz ab' ∧
∃
env tmp stk',
stk = (
tmp,
env) ::
stk' ∧
match get_stk_dep μ
stk with
|
inleft H =>
let '
exist ((
pre, (
tmp',
env')),
post)
_ :=
H in
∃
v,
eval_expr ge env tmp m (
expr_erase a)
v ∧
v ≠
Vundef ∧
(
pre ++ (
PTree.set x v tmp',
env') ::
post,
m)%
list ∈ γ(
ab')
|
inright _ =>
True
end
end
|
None =>
True
end.
Proof.
unfold assign_in,
assign_cells.
intros G.
destruct ab as ([|?], ?).
exact I.
apply am_bind_case.
easy.
intros;
exact I.
intros res log Hres.
simpl.
generalize (
ab_eval_expr_correct G a).
rewrite Hres.
destruct res as [ | (((
tp,
nm),
ty),
lme) ].
intros ().
intros (
MONO & ε₀ & τ₀ & σ & -> &
H).
ung.
simpl in *.
destruct (
tnum_m_stronger MONO (
conj (
Pun.mem_as_fun_pun_u8 _ _ INV.(
noIntFragment))
TPNM))
as (
TP' & ρ
n &
CPT' &
NM').
specialize (
H ρ
n CPT'
NM').
destruct H as (
v &
V &
Def &
Hty &
me &
n &
INme &
Cptn &
_ &
EVn).
simpl.
rewrite union_list_map_correct.
unfold nm_upd_cells.
simpl.
assert (
X:=
union_list_correct (
NotBot nm) (
G:=
gamma_bot mach_gamma)
(
map (
nm_upd NumDom nm (
ACtemp μ
x))
lme)).
setoid_rewrite in_map_iff in X.
specialize (λ
m,
X _ m (
ex_intro _ me (
conj eq_refl INme))).
assert (
HX:γ (
nm_upd NumDom nm (
ACtemp μ
x)
me) (
upd ρ
n (
ACtemp μ
x)
n)).
{
eapply forget_all_correct.
apply gamma_num_ext.
{
clear.
intros [|
m].
intros ? ? ? ().
simpl.
intros ρ ρ'
x H H0.
eapply forget_correct';
eauto. }
eapply AbMachineEnv.assign_correct;
try eassumption.
intuition. }
specialize (
X _ HX).
clear HX.
destruct (
union_list (
NotBot nm) (
map _ lme))
as [|
nm'].
simpl.
exact X.
simpl.
split.
reflexivity.
split.
reflexivity.
eexists _,
_,
_.
split.
reflexivity.
destruct (
get_stk_dep)
as [
IN | ].
destruct IN as (((
pre & (
tmp',
env')) &
post),
IN).
simpl in IN.
destruct IN as (
STK' &
IN &
Hstk).
apply Pos.eqb_eq in Hstk.
rewrite <- (
rev_involutive (
_ ++
_ ::
nil))
in IN.
apply rev_inj in IN.
rewrite rev_app_distr,
rev_involutive in IN.
simpl in IN.
exists v.
split.
easy.
split.
easy.
assert (∀
q,
q ≠
ACtemp μ
x →
mem_as_fun ge ((τ₀, ε₀) :: σ,
m)
q =
mem_as_fun ge (
pre ++ (
PTree.set x v tmp',
env') ::
post,
m)
q)%
list as Hupd.
{
intros q H.
rewrite IN.
unfold temp_env in *.
destruct q as [
f y|
f y|
b];
simpl.
rewrite !
get_stk_app, !
plength_cons.
case (
Pos.ltb_spec);
auto.
intros LT.
rewrite !
get_stk_cons.
case (
Pos.eqb_spec);
easy.
rewrite !
get_stk_app, !
plength_cons.
case (
Pos.ltb_spec);
auto.
intros LT.
rewrite !
get_stk_cons.
case (
Pos.eqb_spec);
auto.
clear LT.
intros ->.
simpl.
rewrite PTree.gso.
easy.
intros ->.
subst.
now apply H.
reflexivity. }
assert (
mem_as_fun ge (
pre ++ (
PTree.set x v tmp',
env') ::
post ,
m) (
ACtemp μ
x) =
v)%
list as Hupd'.
{
unfold temp_env in *.
simpl.
rewrite get_stk_app.
simpl.
case (
Pos.ltb_spec).
intros LT.
rewrite get_stk_cons.
rewrite Hstk, (
Pos.eqb_refl).
simpl.
rewrite PTree.gss.
reflexivity.
rewrite plength_cons,
Pplus_one_succ_l.
Psatz.lia.
}
split;[| | |
split].
destruct pre as [|(?, ?)
pre].
+
ung.
simpl in *;
eq_some_inv;
ssubst;
vauto.
+
ung.
simpl in *.
eq_some_inv.
ssubst.
constructor.
easy.
apply Forall2_app_inv_r in STK.
hsplit.
apply list_append_map_inv in H1.
hsplit.
ssubst.
fold (
map γ (
l0 ++
l3)).
rewrite map_app.
apply Forall2_app.
auto.
inversion H;
clear H.
ssubst.
symmetry in H1;
apply map_cons_inv in H1.
hsplit.
ssubst.
vauto.
+
intros _.
eapply invariant_tmp. 2:
eassumption.
unfold stacks_tmp.
rewrite IN, !
map_app.
reflexivity.
+
simpl.
eapply (
sizes_gamma_tmp). 2:
eassumption.
unfold stacks_tmp.
rewrite IN, !
map_app.
reflexivity.
+
simpl.
intros c.
eapply ACTreeDom.gamma_set.
eapply pt_forget_all_correct.
eapply points_to_gamma_tmp. 2:
eassumption.
unfold stacks_tmp.
rewrite IN, !
map_app.
reflexivity.
intros.
left.
reflexivity.
simpl.
ssubst.
rewrite get_stk_length'.
simpl.
rewrite PTree.gss.
destruct ty as [|
ty].
exact I.
revert Hty.
apply type_gamma_covariant,
ptset_gamma_tmp.
unfold stacks_tmp.
rewrite IN, !
map_app.
reflexivity.
exact Hupd.
+
exists (
upd ρ
n (
ACtemp μ
x)
n).
split.
eapply (
N.compat_upd _ id);
eauto.
intros q.
destruct (
eq_dec q)
as [ -> |
ME].
auto.
symmetry;
apply Hupd;
exact ME.
apply X.
+
easy.
Qed.
Lemma assign_sound :
∀ (
x :
ident) (
e :
expr) (
ab :
t) (
a :
option concrete_state),
Assign ge x e (γ
ab)
a → γ (
assign NumDom ge max_concretize x e ab)
a.
Proof.
intros x e ab a H.
unfold assign.
destruct ab as ([|[|(ε,τ) σ]] &
sz &
tp &
nm);
try (
exact I).
simpl.
generalize (@
assign_in_correct (
plength σ)
x e (
Just ((ε,τ) :: σ), (
sz, (
tp,
nm)))).
fold stack.
fold (@
tnum num).
destruct (
assign_in _)
as (
ab', ([|], ?)). 2:
intros;
exact I.
simpl.
destruct H as [
tmp en stk m H Ha ].
intros H'.
specialize (
H'
_ _ H).
destruct ab'
as [|
ab'].
destruct H'.
hsplit.
subst.
eq_some_inv.
subst.
ung.
simpl in *.
ung.
eq_some_inv.
subst.
destruct (
get_stk_dep)
as [ ( ((
pre, (
tmp',
env')),
post) &
EQ ) | (
_ &
K) ].
2:
rewrite (
list_gamma_len STK),
get_stk_length in K;
eq_some_inv.
simpl in *.
destruct EQ as (
EQ &
IN &
Hlen).
rewrite <- (
rev_involutive (
_ ++
_ ::
nil))
in IN.
apply rev_inj in IN.
rewrite rev_app_distr,
rev_involutive in IN.
simpl in IN.
apply Pos.eqb_eq in Hlen.
rewrite (
list_gamma_len STK),
get_stk_length in EQ.
eq_some_inv.
subst.
hsplit.
erewrite Ha;
eauto.
hnf.
destruct pre.
simpl in *.
eq_some_inv.
subst.
easy.
exfalso.
clear -
IN Hlen STK.
simpl in *.
eq_some_inv.
subst.
rewrite (
list_gamma_len STK),
plength_app,
plength_cons in Hlen.
simpl in *.
rewrite Ppred_minus,
Pplus_one_succ_r in Hlen.
zify.
rewrite Pos2Z.inj_sub in Hlen;
Psatz.lia.
Qed.
Lemma assign_any_sound :
∀ (
x :
ident) (
ty:
typ) (
ab :
t) (
a :
option concrete_state),
AssignAny x ty (γ
ab)
a → γ (
assign_any NumDom x ty ab)
a.
Proof.
intros x ty ab cs [
t e s m G (
v &
Hty' & ->) ].
destruct ab as ([|[|(ε,τ)
stk]] &
sz &
tp &
nm);
try exact I.
unfold assign_any.
ung.
simpl in *.
ung.
eq_some_inv.
subst x0 x1.
assert (
mem_as_fun ge ((
PTree.set x v t,
e) ::
s,
m) ∈
upd_spec (
mem_as_fun ge ((
t,
e) ::
s,
m)) (
ACtemp (
plength stk)
x)
v)
as Hupd.
{
intros c.
case @
eq_dec.
intros ->.
simpl.
rewrite (
list_gamma_len STK),
get_stk_length.
simpl.
now rewrite PTree.gss.
destruct c;
simpl;
auto;
rewrite !
get_stk_cons;
case (
Pos.eqb_spec _ _);
auto;
intros ->
NE;
simpl.
rewrite PTree.gso;
auto.
rewrite (
list_gamma_len STK)
in NE;
congruence.
}
assert (
stacks_tmp ((
t,
e) ::
s) ((
PTree.set x v t,
e) ::
s))
by reflexivity.
assert (
ty <>
VP ->
ty <>
VIP ->
points_to_gamma ge ((
PTree.set x v t,
e) ::
s) (
ACTreeDom.set tp (
ACtemp (
plength stk)
x) (
Just match ty with VI =>
TyInt |
VF =>
TyFloat |
VS =>
TySingle |
_ =>
TyLong end))
(
mem_as_fun ge ((
PTree.set x v t,
e) ::
s,
m)))
as PT'.
{
intros.
eapply points_to_gamma_tmp;
eauto.
intros c.
generalize (
TP c).
rewrite (
Hupd c),
ACTreeDom.gsspec.
unfold eq_dec,
ACellDec.
destruct (
ACTree.elt_eq c). 2:
exact id.
intros _.
destruct ty;
try congruence;
apply gamma_typ_inv in Hty';
hsplit;
subst v;
exact I.
}
assert (
v ∈ γ
ty)
as Hty by exact Hty'.
destruct ty;
try exact I;
apply gamma_typ_inv in Hty;
hsplit;
match goal with
| |-
appcontext[
AbMachineEnv.forget ?
c ?
nm ] =>
generalize (
AbMachineEnv.forget_correct c ρ
n (
N.compat_fun v)
_ NM);
destruct (
AbMachineEnv.forget c nm)
as [|
nm'];
[
exact id|
simpl;
intros Hnm;
split;
simpl;
vauto]
end;
repeat
match goal with
| |-
sizes_gamma _ _ _ _ =>
eapply sizes_gamma_tmp;
eauto
| |-
appcontext[
invariant] =>
intros _;
eapply invariant_tmp;
eauto
| |-
appcontext[@γ
tnum] =>
simpl
| |-
_ ∧
_ =>
split
| |-
appcontext[
points_to_gamma] =>
apply PT';
discriminate
| |-
appcontext[
ACTreeDom.gamma_tree gamma_typ] =>
eapply ACTreeDom.gamma_set;
eauto;
[
rewrite Hupd,
dec_eq_true;
subst v;
vauto
|
intros;
rewrite Hupd,
dec_eq_false;
easy]
| |- ∃
_,
_ ∧
mach_gamma _ _ =>
eexists;
split;[|
eassumption];
(
eapply (
N.compat_upd _ id);
eauto using N.ncompat_compat_fun)
end.
Qed.
Lemma vload_sound : ∀
rettemp gofs κ
args ab,
VLoad ge rettemp gofs κ
args (γ
ab) ⊆ γ (
vload NumDom ge max_concretize rettemp gofs κ
args ab).
Proof.
Lemma store_sound α :
∀ (κ :
memory_chunk) (
dst src :
expr) (
ab :
t)
(
a :
option concrete_state),
Store ge κ
dst src (γ
ab)
a
→ γ (
store NumDom ge max_concretize α κ
dst src ab)
a.
Proof.
intros κ
dst src ab a [
t e s m G H ].
unfold store.
match goal with
|- γ (
match ?κ0
with _ =>
_ end)
_ =>
remember κ0
as κ'
end.
destruct κ'
as [κ''|]. 2:
constructor.
assert (κ =
proj1_sig κ'').
{
destruct κ;
inv Heqκ';
reflexivity. }
subst κ.
clear Heqκ'.
destruct ab as ([|[|(ε,τ) σ]] &
sz &
tp &
nm);
try (
exact I).
simpl.
apply am_assert_spec.
easy.
intros;
exact I.
intros Hcast.
ung.
simpl in *.
ung.
eq_some_inv.
subst x0 x.
pose proof (
deref_expr_correct NumDom max_concretize _ eq_refl (
env_ok _ _ H1)
INV SZ (
Some α) (
tp,
nm) (
conj TP (
ex_intro _ _ (
conj CPT NM))) κ''
dst)
as DEREF.
apply am_bind_case.
easy.
easy.
intros ((
tp',
nm'),
cells)
log Hcells.
rewrite (
list_gamma_len STK)
in Hcells.
simpl in *.
rewrite Hcells in DEREF.
destruct DEREF as (
TN' &
NB &
DEREF).
apply NoError.noerror_eval_expr in NB.
destruct NB as (
v &
Hv).
specialize (
DEREF _ Hv).
destruct DEREF as (
ab &
b &
i & -> &
Habi &
Hab &
Hal).
specialize (λ
v m'
S,
H v _ m'
S Hv).
destruct cells as [|
c₀
cells].
elim Habi;
fail.
match goal with
| |-
appcontext[
am_rev_map ?
f ?
l ] =>
pose proof (
am_rev_map_correct f l)
as CIB
end.
apply am_bind_case.
easy.
easy.
intros TT log'
Hcib.
rewrite Hcib in CIB.
destruct CIB as [
_ CIB'].
assert (∀
c,
In c (
c₀ ::
cells) → ∀
b,
block_of_ablock ge ((
t,
e) ::
s) (
ablock_of_cell c) =
Some b →
Mem.range_perm m b (
fst (
range_of_cell c)) (
fst (
range_of_cell c) +
size_chunk (
proj1_sig κ''))
Cur Writable)
as CIB.
{
intros c IN b'
Hb'.
specialize (
CIB'
_ IN).
destruct CIB'
as (() &
CIB' &
_).
apply (
cell_in_bounds_range_perm CIB'
SZ Hb').
}
clear CIB'.
unfold assign_cells.
match goal with
| |-
appcontext[
ab_eval_expr ?
D ?
G ?
M ?
ab ?
e ] =>
pose proof (λ
s m G, @
ab_eval_expr_correct ab s m G e)
as Hsrc
end.
specialize (
Hsrc ((
t,
e) ::
s)
m).
simpl in *.
apply am_bind_case.
easy.
intros;
exact I.
intros q log''
Hq.
rewrite Hq in Hsrc.
destruct (
tnum_m_stronger TN' (
conj (
Pun.mem_as_fun_pun_u8 _ _ INV.(
noIntFragment)) (
conj TP (
ex_intro _ _ (
conj CPT NM)))))
as (
TP' & (ρ
n' &
Nc' &
NM')).
destruct q as [|(((
tp'',
nm'') &
ty) &
ln)].
destruct Hsrc.
split;
eauto;
vauto.
edestruct Hsrc as (
MONO &
Hsrc').
split;
eauto;
vauto.
clear Hsrc.
destruct Hsrc'
as (
j &
k &
l & ? &
Hsrc);
eq_some_inv;
subst j k l.
apply am_assert_spec.
easy.
intros;
exact I.
intros Htypes.
destruct (
tnum_m_stronger MONO (
conj (
Pun.mem_as_fun_pun_u8 _ _ INV.(
noIntFragment)) (
conj TP' (
ex_intro _ _ (
conj Nc'
NM')))))
as (
TP'' & ρ' &
CPT' &
NM'').
specialize (
Hsrc _ CPT'
NM'').
destruct Hsrc as (
v &
Hsrc &
Def &
Hvty &
me &
n &
INme &
Hvn &
_ &
Hn).
specialize (λ
m',
H v m'
Hsrc).
destruct (
Mem.valid_access_store m (
proj1_sig κ'')
b (
Int.unsigned i)
v)
as (
m' &
Hm').
{
split.
simpl.
specialize (
CIB _ Habi b).
rewrite ablock_of_cell_from in CIB.
specialize (
CIB Hab).
destruct ab;
try exact CIB.
simpl in Hab.
eq_some_inv.
exact Hal.
}
specialize (
H m'
Hm').
subst a.
rewrite union_list_map_correct.
set (
l :=
map (
nm_upd_cells NumDom nm'' (
c₀ ::
cells))
ln).
assert (
Val.load_result (
proj1_sig κ'')
v =
v)
as Hlr.
{
clear -
Htypes Hvty Hcast Hsrc.
destruct ty as [|
ty ].
simpl in *;
eq_some_inv.
apply type_gamma_inv in Hvty.
destruct ty;
hsplit;
destruct κ''
as [[] []];
eq_some_inv;
intuition;
hsplit;
subst;
try reflexivity;
simpl;
f_equal;
destruct src;
simpl in *;
eq_some_inv;
destruct u;
eq_some_inv;
NoError.eval_expr_inv;
simpl in Hsrc;
eq_some_inv;
repeat
match goal with
|
H :
appcontext[
Val.sign_ext _ ?
a] |-
_ =>
destruct a;
inversion H;
clear H;
apply Int.sign_ext_widen;
intuition
|
H :
appcontext[
Val.zero_ext _ ?
a] |-
_ =>
destruct a;
inversion H;
clear H;
apply Int.zero_ext_widen;
intuition
end.
}
assert (
loose_upd_spec
(
mem_as_fun ge ((
t,
e) ::
s,
m))
(
cell_from ab (
Int.unsigned i, κ''))
v
(
mem_as_fun ge ((
t,
e) ::
s,
m')))
as Hupd.
{
split.
+
destruct ab as [
f x|
b'];
simpl in *.
revert Hab.
rewrite get_stk_cons.
case (
Pos.eqb_spec).
simpl.
destruct (
_ !
x)
as [(
b' & ?) | ];
intros;
eq_some_inv.
simpl.
subst b'.
rewrite (
Mem.load_store_same _ _ _ _ _ _ Hm');
auto.
destruct (
get_stk f _)
as [(? &
e')|];
intros;
eq_some_inv.
simpl.
destruct (
e' !
x)
as [(
b' & ?) | ];
eq_some_inv;
subst b'.
simpl.
rewrite (
Mem.load_store_same _ _ _ _ _ _ Hm');
auto.
destruct (
Genv.invert_symbol ge b');
eq_some_inv;
subst b'.
rewrite (
Mem.load_store_same _ _ _ _ _ _ Hm');
auto.
+
pose proof (
Mem.store_valid_access_3 _ _ _ _ _ _ Hm')
as [
_ AL].
intros [
f x i' κ'|
f x|
b'
i' κ']
DIS;
simpl.
*
rewrite get_stk_cons.
case (
Pos.eqb_spec).
intros ->.
simpl.
destruct (
_ !
x)
as [(
b' &
s') | ]
eqn:
Hb';
auto;
eq_some_inv.
simpl.
destruct (
Zdivide_dec (
align_chunk (
proj1_sig κ'))
i')
as [
AL'|
NA].
apply align_chunk_pos.
2:
rewrite !(
misaligned_load NA);
reflexivity.
rewrite (
Mem.load_store_other _ _ _ _ _ _ Hm').
reflexivity.
{
destruct ab as [
f'
x'|
b''];
simpl in Hab;
eq_some_inv.
destruct (
eq_dec b'
b);
auto.
right.
ssubst.
assert ((
plength s,
x) = (
f',
x')).
{
pose proof (
INV.(@
localInj _ _) (
plength s,
x) (
f',
x')
b)
as LOCALS.
simpl in LOCALS.
rewrite get_stk_length in LOCALS.
simpl in LOCALS.
rewrite Hb'
in LOCALS.
specialize (
LOCALS eq_refl).
revert LOCALS.
revert Hab.
rewrite get_stk_cons.
case (
Pos.eqb_spec).
simpl.
intros ->.
destruct (
_ !
x')
as [(
b',
s'')|];
intros;
eq_some_inv.
subst b'.
specialize (
LOCALS eq_refl).
congruence.
destruct (
get_stk f'
_)
as [(?,
e')|];
eq_some_inv.
simpl.
destruct (
e' !
_)
as [(
b',
s'')|];
intros;
eq_some_inv.
subst b'.
specialize (
LOCALS eq_refl).
congruence.
intros;
eq_some_inv.
}
eq_some_inv.
ssubst.
destruct DIS as [
DIS|
DIS].
simpl in DIS.
unfold is_true in DIS;
hsplit;
eq_some_inv.
simpl in DIS.
clear -
DIS.
intuition.
apply do_opt_some_inv in Hab.
destruct Hab as (
sym &
Hsym &
Hab).
eq_some_inv.
subst b''.
pose proof (
INV.(
localNotGlobal)
_ _ (
or_introl eq_refl))
as K.
left.
apply not_eq_sym.
eapply K.
apply Genv.invert_find_symbol,
Hsym.
exact Hb'.
}
destruct (
get_stk f _)
as [(
t' &
e')|]
eqn:
He';
auto;
eq_some_inv.
simpl.
destruct (
e' !
_)
as [(
b' &
s') | ]
eqn:
Hb';
auto;
eq_some_inv.
simpl.
destruct (
Zdivide_dec (
align_chunk (
proj1_sig κ'))
i')
as [
AL'|
NA].
apply align_chunk_pos.
2:
rewrite !(
misaligned_load NA);
reflexivity.
rewrite (
Mem.load_store_other _ _ _ _ _ _ Hm').
reflexivity.
{
destruct ab as [
f'
x'|
b''];
simpl in Hab;
eq_some_inv.
destruct (
eq_dec b'
b);
auto.
right.
assert ((
f,
x) = (
f',
x')).
{
subst b'.
revert Hab.
generalize (
INV.(@
localInj _ _) (
f,
x) (
f',
x')
b).
simpl.
rewrite (
get_stk_tail _ _ _ He').
simpl.
rewrite Hb'.
simpl.
destruct (
get_stk f'
_)
as [(?,
e'')|];
intros;
eq_some_inv.
simpl in *.
destruct (
e'' !
x')
as [(
b',
s'')|];
eq_some_inv.
subst b'.
auto.
}
eq_some_inv.
subst f'
x'.
destruct DIS as [
DIS|
DIS].
simpl in DIS;
unfold is_true in DIS;
hsplit;
eq_some_inv.
simpl in DIS.
clear -
DIS.
intuition.
apply do_opt_some_inv in Hab.
destruct Hab as (
sym &
Hsym &
Hab).
eq_some_inv.
subst b''.
left.
apply not_eq_sym.
eapply INV.(
localNotGlobal).
right.
eapply get_stk_in,
He'.
apply Genv.invert_find_symbol,
Hsym.
exact Hb'.
}
*
reflexivity.
*
destruct (
Genv.invert_symbol ge b')
as [
sym'|]
eqn:
Hsym';
auto;
eq_some_inv.
destruct (
Zdivide_dec (
align_chunk (
proj1_sig κ'))
i')
as [
AL'|
NA].
apply align_chunk_pos.
2:
rewrite !(
misaligned_load NA);
reflexivity.
rewrite (
Mem.load_store_other _ _ _ _ _ _ Hm').
reflexivity.
{
destruct ab as [
f'
x'|
b''];
simpl in Hab;
eq_some_inv.
left.
intros ->.
revert Hab.
rewrite get_stk_cons.
case (
Pos.eqb_spec).
simpl.
intros ->.
pose proof (
INV.(
localNotGlobal)
_ _ (
or_introl eq_refl))
as GE.
destruct (
_ !
x')
as [(?,?)|]
eqn:
Hex';
intro;
eq_some_inv.
eapply GE.
eapply Genv.invert_find_symbol.
eassumption.
exact Hex'.
auto.
destruct (
get_stk f'
_)
as [(
t',
e')|]
eqn:
Hf'
s.
simpl.
destruct (
e' !
x')
as [(?,?)|]
eqn:
He'
x';
intros;
eq_some_inv.
eapply INV.(
localNotGlobal).
right.
eapply get_stk_in.
exact Hf'
s.
eapply Genv.invert_find_symbol.
eassumption.
exact He'
x'.
auto.
intros;
eq_some_inv.
apply do_opt_some_inv in Hab.
destruct Hab as (
sym &
Hsym &
Hab).
eq_some_inv.
subst b''.
destruct (
eq_dec b'
b);
auto.
right.
subst b'.
clear -
AL AL'
DIS.
destruct DIS as [
DIS|
DIS];
simpl in DIS.
unfold is_true in DIS;
hsplit;
eq_some_inv.
intuition.
}
}
set (ρ
n'' := λ
c,
if cells_disjoint_dec (
cell_from ab (
Int.unsigned i, κ''))
c
then ρ'(
c)
else if eq_dec (
cell_from ab (
Int.unsigned i, κ''))
c
then n
else N.compat_fun (
mem_as_fun ge ((
t,
e) ::
s,
m')
c)).
assert (
Hρ
n''ρ
n:
loose_upd_spec ρ' (
cell_from ab (
Int.unsigned i, κ''))
n ρ
n'').
{
clear.
unfold ρ
n''.
split.
destruct cells_disjoint_dec as [
K|
K].
elim (
cells_disjoint_not_eq K eq_refl).
rewrite dec_eq_true.
reflexivity.
intros y H.
destruct cells_disjoint_dec.
reflexivity.
eapply cells_disjoint_overlap;
eauto. }
assert (
Hρ
n'' : γ (
union_list (
NotBot nm'')
l) ρ
n'').
{
eapply union_list_correct.
refine _.
subst l.
rewrite in_map_iff.
exists me.
split.
reflexivity.
exact INme.
unfold nm_upd_cells.
rewrite union_list_map_correct.
eapply union_list_correct;
eauto.
refine _.
rewrite in_map_iff.
vauto.
eapply nm_upd_correct;
try eassumption. }
destruct (
union_list (
NotBot _)
l)
as [|
nmo].
contradiction.
split;[| | |
split].
-
simpl.
vauto.
-
intros _.
split.
+
intros f t'
e'
H'.
intros hi H o'
Ho'.
eapply Mem.perm_store_1.
eassumption.
eapply INV;
eassumption.
+
eapply INV;
eauto.
+
eapply INV.(
localInj).
+
simpl.
intros ?
b0 H.
eapply (
Mem.store_valid_block_1) .
eassumption.
eapply INV;
eauto.
+
intros t'
e'
H' ?
b'
z H.
eapply Mem.store_valid_block_1;
try eassumption.
eapply INV.(
localValid);
eauto.
+
simpl.
intros ab0 b0 H o.
Transparent Mem.store.
unfold Mem.store in Hm'.
Opaque Mem.store.
destruct Mem.valid_access_dec;
eq_some_inv.
rewrite <-
Hm'.
generalize (
INV.(
noIntFragment)
_ H o).
simpl.
rewrite PMap.gsspec.
case peq.
intros <-.
assert ((
o <
Int.unsigned i \/
o >=
Int.unsigned i +
Z.of_nat (
Datatypes.length (
encode_val (
proj1_sig κ'')
v))) \/ (
Int.unsigned i <=
o <
Int.unsigned i +
Z.of_nat (
Datatypes.length (
encode_val (
proj1_sig κ'')
v))))
as Hr by Psatz.lia.
destruct Hr as [
Hout |
Hin ].
*
rewrite Mem.setN_outside.
exact id.
exact Hout.
*
intros _.
generalize (
Mem.setN_in _ _ _ (
Mem.mem_contents m) !!
b0 Hin).
destruct (
ZMap.get _ _)
as [ | ? | () ? ? ];
try (
intros;
exact I).
clear.
destruct κ''
as [() ()];
destruct v;
simpl;
try (
intuition congruence);
try (
unfold inj_bytes;
rewrite in_map_iff;
intros ( ? & ? & ? );
discriminate).
*
intros _.
exact id.
-
simpl.
intros b'
hi perm vol b''
Hhi Hb''.
split.
intros o'
Ho'.
eapply Mem.perm_store_1.
eassumption.
eapply SZ;
eassumption.
eapply SZ;
eassumption.
-
refine (
tp_upd_correct _ (
c₀ ::
cells)
ty _ Habi TP''
Hupd).
destruct ty as [ |
ty ].
exact I.
apply type_gamma_inv in Hvty.
clear -
Hvty Htypes.
destruct ty;
destruct κ''
as [[][]];
simpl in Htypes;
eq_some_inv;
hsplit;
intuition;
hsplit;
subst;
vauto;
assumption.
-
exists ρ
n''.
split.
+
unfold ρ
n''.
intros c.
specialize (
CPT'
c).
simpl in *.
destruct (
cells_disjoint_dec).
generalize (
proj2 Hupd c).
simpl.
intros Y.
rewrite Y.
auto.
auto.
destruct (
eq_dec (
cell_from _ _)
c).
subst c.
generalize (
proj1 Hupd).
simpl.
intros ->.
assumption.
apply N.ncompat_compat_fun.
+
auto.
Qed.
Lemma vstore_sound : ∀
rettemp gofs κ
args ab,
VStore ge rettemp gofs κ
args (γ
ab) ⊆ γ (
vstore NumDom ge max_concretize rettemp gofs κ
args ab).
Proof.
intros rettemp gofs κ
args ab.
pose proof (@
ab_eval_expr_correct ab)
as AEEC.
unfold vstore.
match goal with
| |-
appcontext[
match ?
x with _ =>
_ end ] =>
destruct x as [(
tgt,
arg) | ]
eqn:
Htgt
end.
2:
easy.
apply am_bind_case.
easy.
easy.
intros μ'
log Hvol.
apply check_volatile_sound in Hvol.
intros a [
t e s m G H ].
ung.
simpl in *.
destruct ab as ([ | [ | (ε,τ)
stk] ] &
sz & (
tp &
nm)).
easy.
easy.
simpl in *.
destruct TPNM as (
TP & ρ &
CPT &
NM).
ung.
subst.
eq_some_inv.
subst.
destruct Hvol as [ ->
Hvol ].
apply am_bind_case.
easy.
easy.
intros abval log'
Harg.
generalize (λ
G,
AEEC ((
t,
e) ::
s)
m G arg).
rewrite Harg.
intros Hev.
destruct abval as [ | (((
tp',
nm') &
oty) &
lne) ].
destruct Hev.
vauto2.
destruct Hev as (
MONO &
Hev).
vauto2.
destruct Hev as (
i &
j &
k & ? &
Hev).
eq_some_inv.
subst i j k.
destruct (
tnum_m_stronger MONO (
conj (
Pun.mem_as_fun_pun_u8 _ _ INV.(
noIntFragment)) (
conj TP (
ex_intro _ _ (
conj CPT NM)))))
as (
TP' & ρ' &
CPT' &
NM').
specialize (
Hev ρ'
CPT'
NM').
destruct Hev as (
v &
Hv &
Hvdef &
Hty &
ne' &
n &
Hne' &
Hvn &
Hn' &
Hn ).
apply am_assert_spec.
easy.
easy.
destruct oty as [ |
ty ].
easy.
intros Htyκ.
assert (∃
v':
Events.eventval,
Events.eventval_match ge v' (
AST.type_of_chunk κ) (
Val.load_result κ
v))
as v'.
{
apply type_gamma_inv in Hty.
destruct ty, κ;
eq_some_inv;
hsplit;
subst;
vauto;
try (
destruct Hty;
hsplit;
subst;
vauto);
apply only_global_pointer_iff in Htyκ;
destruct Htyκ
as (
ptr' & -> &
Hptr );
match goal with
|
Hpt : γ (
Just _)
_ |-
_ =>
destruct Hpt as (
ab &
Hab &
Habb);
specialize (
Hptr ab Hab);
idtac end;
destruct Hptr as (
b' & -> &
g' &
Hg' &
Hgp);
simpl in *;
rewrite Hg'
in Habb;
eq_some_inv;
subst;
eexists (
Events.EVptr_global g'
_);
econstructor;
eauto;
apply Genv.invert_find_symbol,
Hg'.
}
destruct v'
as (
v' &
Hv').
destruct gofs as [ (
g,
ofs) | ].
-
destruct args as [ |
arg' [ | ? ? ] ];
eq_some_inv.
subst.
destruct Hvol as (
b &
Hg &
hi &
perm &
Hvol ).
generalize (
SZ (
ABglobal b)
hi perm true b Hvol).
simpl.
rewrite (
Genv.find_invert_symbol _ _ Hg).
intros Hsz;
destruct (
Hsz eq_refl)
as (
Hrange &
Hvol').
clear Hsz.
specialize (λ
tr,
H tr _ _ _ _ v (
conj eq_refl (
conj eq_refl eq_refl))
Hg Hv).
rewrite Hvol'
in H.
refine (
let H' :=
H (
Events.Event_vstore κ
g ofs v' ::
nil)
_ in _).
vauto.
clear H;
subst a.
destruct rettemp as [
r | ].
+
rewrite (
list_gamma_len STK).
apply forget_temp_sound.
split;
vauto;
eauto.
+
split;
eauto;
vauto.
-
unfold with_tnum.
simpl.
destruct args as [ |
addr [ |
arg' [ | ? ? ] ] ];
eq_some_inv;
subst.
destruct Hvol as ((
tp'',
nm'') &
ptr' &
ne &
EV &
Hvol).
specialize (λ
G,
AEEC ((
t,
e) ::
s)
m G addr).
rewrite EV in AEEC.
edestruct AEEC as (
MONO' &
AEEC').
split;
eauto;
vauto.
clear AEEC.
destruct AEEC'
as (? & ? & ? & ? &
AEEC).
eq_some_inv.
subst x x1 x2.
destruct (
tnum_m_stronger MONO' (
conj (
Pun.mem_as_fun_pun_u8 _ _ INV.(
noIntFragment)) (
conj TP (
ex_intro _ _ (
conj CPT NM)))))
as (
TP'' & ρ'' &
CPT'' &
NM'').
specialize (
AEEC ρ''
CPT''
NM'').
destruct AEEC as (
v'' &
Hv'' &
Hvdef' &
Hty' &
ne'' &
n' &
Hne'' &
Hvn' &
Hn'' &
Hn''' ).
simpl in *.
destruct Hvol as (
ptr & -> &
Hvol).
apply type_gamma_inv in Hty'.
destruct Hty'
as (
b &
i & -> &
Hpt').
destruct Hpt'
as (
blk &
Hblk &
Hb').
generalize (
validate_volatile_ptr_in SZ Hvol _ Hblk).
intros (
g &
b' & -> &
Hg &
Hvol').
simpl in Hb'.
rewrite (
Genv.find_invert_symbol _ _ Hg)
in Hb'.
eq_some_inv.
subst.
refine (
let H' :=
H (
Events.Event_vstore κ
g i v' ::
nil)
_ _ _ _ v (
conj eq_refl Hv'')
Hg Hv _ in _).
vauto.
clear H.
simpl in Hvol'.
rewrite Hvol'
in H'.
subst a.
destruct rettemp as [
r | ].
+
rewrite (
list_gamma_len STK).
apply forget_temp_sound.
split;
vauto;
eauto.
+
split;
eauto;
vauto.
Qed.
Lemma push_frame_sound :
∀ (
f :
function) (
args :
list expr)
(
ab :
t) (
a :
option concrete_state),
PushFrame ge f args (γ
ab)
a → γ (
push_frame NumDom ge max_concretize f args ab)
a.
Proof.
intros fn args.
intros (
stk &
sz & (
tp &
nm))
cs (σ &
m &
H &
NR &
PF).
ung.
simpl in *.
unfold push_frame.
simpl.
destruct stk as [|σ'].
simpl.
apply am_bind_case.
easy.
easy.
intros [|(?,?)] ? ?.
easy.
destruct (
ab_bind_parameters _)
as (?, (?,?));
exact I.
assert ( ∃
m1 e1,
alloc_variables empty_env m fn.(
fn_vars)
e1 m1)
as (
m1 &
e1 &
H1).
{
generalize fn.(
fn_vars).
intros l.
generalize empty_env,
m.
induction l as [|(
v,
sz')
l IH].
vauto2.
intros e m'.
destruct (
Mem.alloc m' 0
sz')
as [
m''
b]
eqn:
AL.
destruct (
IH (
PTree.set v (
b,
sz')
e)
m'')
as (
m1 &
e1 &
H1).
vauto2.
}
specialize (λ
vargs Hvargs,
PF vargs Hvargs m1 e1 H1).
simpl.
apply am_bind_case.
easy.
easy.
destruct σ
as [|(
t,
e) σ].
-
specialize (
PF _ eq_refl).
simpl in STK.
ung.
subst σ'.
generalize dependent (
fn_params fn).
intros [|]
PF.
{
specialize (
PF _ eq_refl).
subst cs.
unfold ab_bind_parameters.
destruct args. 2:
easy.
simpl.
intros x log X;
vm_compute in X.
eq_some_inv.
subst x.
split; [| | |
split].
+
hnf.
simpl.
constructor. 2:
vauto.
exact (
alloc_variables_build H1).
+
simpl.
intros _.
eapply push_frame_invariant;
eauto.
+
simpl.
refine (
push_frame_sizes _ NR _ _);
eauto using push_frame_invariant.
+
intros c.
generalize (
TP c).
simpl.
destruct (
ACTreeDom.get c tp)
as [|
bs].
exact id.
destruct c as [
f x ofs|
f x|
b ofs];
simpl.
rewrite get_stk_cons.
case (
Pos.eqb_spec).
simpl.
intros ->.
destruct (
e1 !
x)
as [(
b,
h)|]
eqn:
Hx;
auto.
simpl.
pose proof (
load_undef (
proj2 (
alloc_variables_load H1 _ Hx)) (
proj1_sig κ)
ofs)
as X.
simpl in X.
rewrite X.
exact id.
rewrite get_stk_nil.
intros _.
exact id.
rewrite get_stk_cons.
case (
Pos.eqb_spec).
simpl.
intros ->.
generalize (
create_undef_temps_get (
fn_temps fn)
x).
destruct ((
create_undef_temps (
fn_temps fn)) !
x);
intuition.
subst;
auto.
rewrite get_stk_nil.
easy.
destruct (
Genv.invert_symbol ge b)
eqn:
B;
auto.
simpl.
rewrite (
alloc_var_load _ (
proj1 (
alloc_var_alt _ _ _ _)
H1) (
INV.(
globalValid)
_ (
Genv.invert_find_symbol _ _ B))).
destruct (
Mem.load (
proj1_sig κ)
m b ofs)
as [()|];
try exact id.
intros Hty.
apply type_gamma_inv'
in Hty.
destruct Hty as [ ([ |
ptr ] &
Hty & [ -> | -> ])| -> ];
try exact I;
destruct Hty as (
q &
Q &
Q');
(
exists q;
split; [
exact Q | ];
destruct q;
simpl in *;
eq_some_inv;
exact Q'
).
+
exists ρ
n.
split;
auto.
intros c.
generalize (
CPT c).
simpl.
destruct c as [
f x ofs|
f x|
b ofs];
simpl;
try rewrite get_stk_nil;
try rewrite get_stk_cons;
intros X.
case (
Pos.eqb_spec);
intros _.
simpl.
destruct (
e1 !
x)
as [(
b,
s)|]
eqn:
Hx.
simpl.
generalize (
load_undef (
proj2 (
alloc_variables_load H1 _ Hx)) (
proj1_sig κ)
ofs).
simpl.
intros Y.
rewrite Y.
exact X.
exact X.
rewrite get_stk_nil.
exact X.
case (
Pos.eqb_spec);
intros _.
simpl.
generalize (
create_undef_temps_get (
fn_temps fn)
x).
destruct ((
create_undef_temps (
fn_temps fn)) !
x);
intuition.
subst;
auto.
rewrite get_stk_nil.
exact X.
destruct (
Genv.invert_symbol ge b)
eqn:
B;
auto.
rewrite (
alloc_var_load _ (
proj1 (
alloc_var_alt _ _ _ _)
H1) (
INV.(
globalValid)
_ (
Genv.invert_find_symbol _ _ B))).
exact X.
}
destruct args;
intros x log X;
vm_compute in X;
eq_some_inv;
subst x.
exact I.
-
intros x log X.
assert (
ab_stk (
Just σ', (
sz, (
tp,
nm))) ≠
All)
as Hstk by (
simpl;
congruence).
generalize (@
ab_eval_exprlist_correct e t σ
m args _ Hstk).
unfold tnum in *.
rewrite X.
clear X.
simpl.
intros H.
destruct x as [ | (
ab'' &
ab_args) ].
destruct H.
split;
eauto;
vauto.
destruct H as (
EQstk &
EQsz &
MONO &
Hargs).
split;
eauto;
vauto.
destruct (
Hargs _ CPT NM)
as (
vargs &
EVL &
AM).
clear Hargs.
specialize (
PF _ EVL).
unfold with_stk.
simpl.
match goal with |-
appcontext[
ab_bind_parameters ?
D ?μ ?
f ?
a (
NotBot ?
t, (
nil,
_))] =>
set (
ab' :=
t)
end.
specialize (
INV Hstk).
assert (((∀
t0, ∃
t1,
bind_parameters fn.(
fn_params)
vargs t0 =
Some t1) ∧ ∃
ab'',
am_get (
ab_bind_parameters NumDom (
plength σ')
fn.(
fn_params)
ab_args (
ret (
NotBot ab'))) =
Some ab'')
∨
am_get (
ab_bind_parameters NumDom (
plength σ')
fn.(
fn_params)
ab_args (
ret (
NotBot ab'))) =
None)
as T1.
{
clear PF.
setoid_rewrite bind_parameters_zip.
generalize (
NotBot ab').
clear ab'.
revert args ab_args vargs AM EVL.
generalize fn.(
fn_params).
intros formals.
induction formals as [|
id formals IH];
intros args ab_args vargs AM EVL b;
inv AM;
simpl;
vauto.
specialize (
IH _ _ _ H7).
inv EVL.
specialize (
IH H13).
match goal with |-
appcontext[
ab_bind_parameters _ _ _ _ ?
x ] =>
set (
y :=
x)
end.
specialize (
IH (
fst y)).
destruct IH as [
IH' |
IH' ]; [
left |
right ];
eauto.
hsplit.
split.
intros t0.
specialize (
IH' (
PTree.set id v t0)).
eauto.
eauto.
}
simpl in T1.
destruct T1 as [(
T1 &
Hab'')|
T1].
2:
destruct (
ab_bind_parameters _)
as (?, ([|], ?));
simpl in T1;
eq_some_inv;
exact I.
specialize (
T1 (
create_undef_temps fn.(
fn_temps))).
hsplit.
specialize (
PF t1 T1).
rewrite PF;
clear cs PF.
destruct (
ab_bind_parameters _ _ _ _ _)
as (
q,([|],?))
eqn:
Q;
simpl in Hab'';
eq_some_inv;
subst q.
red.
red.
simpl.
match goal with |- ?
x ∈
gamma_bot _ _ =>
set (
cs :=
x)
end.
assert (γ(
ab_stk ab') (
fst cs))
as G1.
{
subst cs ab'.
simpl in *.
ung.
subst.
simpl.
constructor.
exact (
alloc_variables_build H1).
vauto. }
assert (
invariant ge cs)
as INV'.
{
subst cs.
refine (
push_frame_invariant _ _ INV);
eauto.
}
specialize (
MONO _ (
Pun.mem_as_fun_pun_u8 _ _ INV.(
noIntFragment)) (
conj TP (
ex_intro _ _ (
conj CPT NM)))).
edestruct (λ
K q, @
ab_bind_parameters_sound e t σ
m fn.(
fn_vars)
e1 m1 INV K fn.(
fn_params)
args ab_args vargs ρ
n q _ _ T1 ab')
as ((
stk' &
sz' &
tp' &
nm') & -> &
Hstk' &
Hsz &
Htp & ρ
n' &
Hnm);
simpl;
eauto.
{
rewrite (
list_gamma_len STK),
plength_cons in Q.
rewrite Q;
reflexivity.
}
{
subst ab'
cs.
simpl.
intros c.
pose proof (
proj1 MONO c)
as X.
simpl.
destruct (
ACTreeDom.get c _)
as [|
ty].
exact X.
apply push_frame_pt;
auto.
revert X.
simpl.
destruct c as [
f'
x'|
f'
x'|
b];
simpl.
destruct (
get_stk f' (
_ :: σ))
as [ (?, ?) | ]
eqn:
X.
simpl.
rewrite (
get_stk_tail _ _ _ X).
exact id.
simpl.
now intros K;
apply type_gamma_inv'
in K.
destruct (
get_stk f' (
_ :: σ))
as [ (?, ?) | ]
eqn:
X.
simpl.
rewrite (
get_stk_tail _ _ _ X).
exact id.
simpl.
now intros K;
apply type_gamma_inv'
in K.
exact id.
}
{
subst ab'
cs.
simpl.
split;
auto.
intros c;
specialize (
CPT c).
destruct c as [
f'
x'|
f'
x'|
b];
simpl in *.
rewrite get_stk_cons.
case (
Pos.eqb_spec).
simpl.
intros ->.
destruct (
e1 !
x')
as [(
b,
h)|]
eqn:
Hx.
simpl.
pose proof (
alloc_var_inj _ _ (
proj1 (
alloc_var_alt _ _ _ _)
H1))
as (
_ &
Y &
_).
specialize (
Y _ _ Hx).
destruct Y as [
_ Y].
simpl in Y.
rewrite (
not_valid_block_load_None Y).
vauto.
vauto.
intros _.
exact CPT.
rewrite get_stk_cons.
case (
Pos.eqb_spec).
simpl.
intros ->.
generalize (
create_undef_temps_get fn.(
fn_temps)
x').
destruct ((
create_undef_temps _) !
x').
intros;
hsplit;
subst;
vauto.
intros _;
vauto.
intros _.
exact CPT.
exact CPT.
apply (
proj2 MONO ρ
n CPT);
auto.
}
split;[| | |
split].
+
rewrite Hstk'.
subst ab'.
econstructor;
eauto.
hnf.
eapply alloc_variables_build;
eauto.
+
intros _.
exact INV'.
+
generalize (
push_frame_sizes INV'
NR H1 SZ).
rewrite Hsz.
simpl.
simpl in STK.
rewrite (
list_gamma_len STK).
rewrite <-
EQsz.
exact id.
+
exact Htp.
+
exists ρ
n'.
eauto.
Qed.
Lemma pop_frame_sound :
∀ (
ret :
option expr) (
rettemp :
option ident) (
ab :
t)
(
a :
option concrete_state),
PopFrame ge ret rettemp (γ
ab)
a
→ γ (
AbMemSignatureCsharpminor.pop_frame _ ret rettemp ab)
a.
Proof.
Hint Resolve env_ok.
intros ret rettemp (σ &
sz &
tp &
nm)
a H.
destruct H as [
tmp env stk m H PF ].
destruct σ
as [|[|(ε₀,τ₀) σ]].
exact I.
exact I.
ung.
simpl in STK.
ung.
eq_some_inv.
subst x x0.
destruct σ
as [|(ε₁,τ₁) σ].
-
destruct ret as [
ret|]. 2:
exact I.
ung.
subst.
simpl.
unfold pop_frame;
simpl.
generalize (λ
G, @
ab_eval_expr_correct (
Just ((ε₀,τ₀) ::
nil), (
sz, (
tp,
nm))) ((
tmp,
env) ::
nil)
m G ret).
match goal with
| |-
appcontext [
am_get ?
X] =>
match goal with
| |-
appcontext [
do ret' <- ?
Y;
_] =>
change X with Y;
destruct Y as ([|(((
tp',
nm') &
ty) &
ln)], ([|],?))
end
end.
intros X;
eelim X;
split;
eauto;
vauto.
intros _;
exact I.
2:
intros _;
destruct ty as [ | () ];
exact I.
simpl.
intros X.
destruct ty as [|
ty].
exact I.
apply am_bind_case.
easy.
intros;
exact I.
intros ()
log Hty.
edestruct X as (
MONO &
Y).
split;
eauto;
vauto.
clear X.
destruct Y as (
i &
j &
k & ? &
X).
eq_some_inv.
subst i j k.
destruct (
tnum_m_stronger MONO (
conj (
Pun.mem_as_fun_pun_u8 _ _ INV.(
noIntFragment)) (
conj TP (
ex_intro _ _ (
conj CPT NM)))))
as (
TP' & ρ' &
CPT' &
NM').
specialize (
X ρ'
CPT'
NM').
destruct X as (
v &
V &
Def &
TY &
_).
assert (
TY' :=
type_gamma_inv _ _ _ TY).
clear TY.
simpl in TY'.
assert (∃
i,
v =
Vint i).
{
destruct ty;
eq_some_inv;
hsplit;
vauto. }
hsplit.
subst v.
specialize (λ
m'
M',
PF m'
M'
_ V _ eq_refl).
destruct (
free_list_ex INV)
as (
m' &
Hm' &
Hm'').
specialize (
PF _ Hm').
subst a.
split;[| | |
split].
+
vauto.
+
intros _.
eapply pop_frame_invariant.
eauto.
intros b H;
split.
intros lo hi p H1.
apply Hm'';
assumption.
apply Hm'',
H.
apply (
free_list_contents Hm').
+
eapply pop_frame_sizes;
eauto.
simpl.
eapply Hm''.
+
intros c.
refine (
pop_frame_pt tmp env m m'
tp c _ (
TP c)).
eapply Hm''.
+
exists ρ
n.
split;
auto.
refine (
pop_frame_compat m'
_ CPT).
eapply Hm''.
-
simpl.
unfold pop_frame.
simpl.
destruct (
free_list_ex INV)
as (
m' &
Hm' &
Hm'').
specialize (
PF _ Hm').
destruct ret as [
ret|].
destruct rettemp as [
rettemp|].
+
apply am_bind_case.
easy.
intros;
exact I.
intros ab'
log Hab'.
generalize (@
assign_in_correct (
plength σ)
rettemp ret (
Just ( (ε₀,τ₀) :: (ε₁,τ₁) :: σ), (
sz, (
tp,
nm)))).
fold stack;
fold (@
tnum num).
rewrite Hab'.
simpl.
intros X.
specialize (
X ((
tmp,
env) ::
stk)
m).
refine (
let K :=
X _ in _).
econstructor;
vauto.
eauto.
eauto.
destruct ab'
as [|(σ' &
sz' &
tp' &
nm')].
destruct K.
clear X.
hsplit.
simpl in *.
subst sz' σ'.
eq_some_inv.
subst env0 tmp0 stk'.
ung.
subst.
destruct get_stk_dep as [
IN|(
NI &
_)].
2:
clear -
STK NI;
rewrite (
list_gamma_len STK), !
plength_cons in NI;
simpl in *;
apply Pos.leb_le in NI;
Psatz.lia.
destruct IN as (((
pre & (
tmp',
env')) &
post) &
EQ &
IN &
Hlen).
simpl in *.
rewrite <- (
rev_involutive (
_ ++
_ ::
_))
in IN.
apply rev_inj in IN.
rewrite !
rev_app_distr in IN.
simpl in IN.
rewrite rev_involutive in IN.
rewrite (
list_gamma_len STK)
in EQ.
generalize (
get_stk_length' ((
tmp,
env) ::
nil)
x x0).
simpl.
intros X.
rewrite X in EQ.
clear X.
eq_some_inv.
subst.
apply (
Pos.eqb_eq)
in Hlen.
rewrite (
list_gamma_len STK)
in Hlen.
destruct pre as [ | ? [ | ? ? ] ];
simpl in *;
eq_some_inv;
subst;
simpl in *.
rewrite plength_cons in *.
Psatz.lia.
2:
clear -
Hlen;
rewrite plength_app,
Ppred_minus,
plength_cons,
Pplus_one_succ_r in Hlen;
zify;
rewrite !
Pos2Z.inj_sub in Hlen;
Psatz.lia.
hsplit.
subst.
clear STK SZ TP CPT NM ρ
n.
ung.
simpl in *.
ung.
eq_some_inv.
subst x x0.
eq_some_inv.
subst x1 x2.
erewrite PF;
eauto.
clear PF.
assert (∀
b :
block,
valid_block ((
PTree.set rettemp v tmp',
env') ::
post)
b →
∀ (κ :
memory_chunk) (
o :
Z),
Mem.load κ
m b o =
Mem.load κ
m'
b o)
as Hb'.
{
intros b ?.
refine (
proj1 (
Hm''
b _)).
eapply valid_block_tmp;
eauto.
reflexivity. }
assert (∀
b :
block,
valid_block ((
PTree.set rettemp v tmp',
env') ::
post)
b →
(∀ (
lo hi :
Z)
p,
Mem.range_perm m b lo hi Cur p →
Mem.range_perm m'
b lo hi Cur p) ∧
(
b ∈
Mem.valid_block m →
b ∈
Mem.valid_block m'))
as Hb''.
{
intros b ?.
eapply Hm'';
eauto.
eapply valid_block_tmp;
eauto.
reflexivity. }
generalize (
pop_local_num_correct (
Pos.succ (
plength σ)) ε₀ τ₀
sz nm'
_ NM).
destruct (
pop_local_num _ _ _ _).
intros ().
intros NM'.
constructor;
vauto;[| |
split].
*
intros _.
eapply pop_frame_invariant;
eauto.
apply (
free_list_contents Hm').
*
simpl.
generalize (
pop_frame_sizes ε₀
INV0 (λ
x y,
proj1 (
Hb''
x y))
SZ).
rewrite (
list_gamma_len STK),
plength_cons.
exact id.
*
intros c.
generalize (
pop_frame_pt tmp env _ _ tp'
c Hb' (
TP c)).
rewrite (
list_gamma_len STK),
plength_cons.
exact id.
*
exists ρ
n.
split. 2:
exact NM'.
generalize CPT.
apply pop_frame_compat.
exact Hb'.
+
match goal with |-
context[
noerror ?
D ?
G ?
N ?
e ?
ab ] =>
generalize (
noerror_correct e ab)
end.
destruct (
noerror _)
as ((), ([|],?)).
2:
exact (λ
_,
I).
simpl in *.
intros H.
edestruct H as (
v &
V &
Def).
econstructor;
simpl;
eauto.
vauto.
intuition eauto.
vauto.
clear H.
specialize (
PF _ V).
ung.
subst.
destruct x.
subst.
rewrite plength_cons.
generalize (
pop_local_num_correct (
Pos.succ (
plength σ)) ε₀ τ₀
sz nm _ NM).
rewrite (
list_gamma_len STK).
destruct (
pop_local_num _ _ _ _).
intros ().
intros NM'.
simpl.
constructor;
vauto;[| |
split].
*
intros _.
eapply pop_frame_invariant;
eauto.
eapply Hm''.
apply (
free_list_contents Hm').
*
simpl.
erewrite <-
plength_cons.
eapply pop_frame_sizes;
eauto.
simpl.
eapply Hm''.
*
intros c.
generalize (
TP c).
simpl.
erewrite <-
plength_cons.
apply pop_frame_pt.
eapply Hm''.
*
exists ρ
n.
split. 2:
exact NM'.
generalize CPT.
apply pop_frame_compat.
eapply Hm''.
+
destruct rettemp.
exact I.
specialize (
PF _ eq_refl).
ung.
subst.
destruct x.
subst.
simpl in *.
rewrite plength_cons.
generalize (
pop_local_num_correct (
Pos.succ (
plength σ)) ε₀ τ₀
sz nm _ NM).
destruct (
pop_local_num _ _ _ _).
intros ().
intros NM'.
constructor;
vauto;[| |
split].
*
intros _.
eapply pop_frame_invariant;
eauto.
eapply Hm''.
apply (
free_list_contents Hm').
*
simpl.
generalize (
pop_frame_sizes ε₀
INV (λ
x y,
proj1 (
proj2 (
Hm''
x y)) )
SZ).
rewrite (
list_gamma_len STK),
plength_cons.
exact id.
*
intros c.
generalize (
pop_frame_pt tmp env _ _ tp c (λ
x y,
proj1 (
Hm''
x y) ) (
TP c)).
rewrite (
list_gamma_len STK),
plength_cons.
exact id.
*
exists ρ
n.
split. 2:
exact NM'.
generalize CPT.
apply pop_frame_compat.
eapply Hm''.
Qed.
Existing Instance ListIncl.
Lemma deref_fun_sound :
∀ (
e :
expr) (
ab :
t) (
a :
option (
ident *
fundef)),
DerefFun ge e (γ
ab)
a → γ (
deref_fun NumDom ge max_concretize e ab)
a.
Proof.
Instance widen_mem_correct:
widen_op_correct (
iter_t +⊥) (
t +⊥)
concrete_state.
Proof.
split.
-
intros x a Ha.
eapply botbind_spec,
Ha.
intros a' [
STK INV SZ TN ].
constructor;
auto.
destruct a'
as (? & ? & ? & ?).
destruct TN as (
TP &
NM).
split;
auto.
destruct NM as (ρ' &
A &
B).
eexists.
split.
eauto.
apply init_iter_correct.
auto.
-
unfold widen_mem.
intros x y cs Hcs.
destruct x as [|(
stk &
sz &
tp &
nm)].
contradiction.
destruct Hcs as [
STK INV SZ (
TP & ρ &
CPT &
NM) ].
simpl.
match goal with
| |-
context [?
A ▽ ?
B] =>
pose proof (
widen_incr A B _ NM)
as Q;
destruct (
A ▽
B)
end.
unfold ACTree.elt in *.
destruct y as [|(
STK' &
SZ' &
TP' &
NUM')].
+
split.
constructor;
auto.
split.
auto.
eexists.
split.
eauto.
apply Q.
eapply botbind_spec. 2:
apply Q.
constructor;
auto.
split.
auto.
eexists.
split.
eauto.
auto.
+
match goal with
| |-
context [(
match stk with All =>
All |
Just STK0 => @?
A STK0 end)] =>
remember (
match stk with All =>
All |
Just STK0 =>
A STK0 end)
as STK''
end.
cbv beta in HeqSTK''.
unfold top_op in STK''.
assert (γ
STK'' (
fst cs)).
{
destruct stk.
subst.
constructor.
destruct STK'.
subst.
constructor.
subst.
apply list_widen_incr,
STK.
intros x y f Hf.
apply (
join_correct (
join_op_correct :=
join_stack_elt_correct)).
left.
exact Hf. }
assert (
STK'' ≠
All →
invariant ge cs).
{
intros.
apply INV.
destruct stk.
congruence.
discriminate. }
assert (
sizes_gamma ge (
fst cs) (
sizes_widen sz SZ') (
snd cs)).
{
unfold sizes_widen.
apply sizes_join_correct.
auto. }
assert (
points_to_gamma ge (
fst cs) (
points_to_widen tp TP') (
mem_as_fun ge cs)).
{
apply ACTreeDom.join_tree_correct.
refine _.
auto. }
split.
*
constructor.
auto.
auto.
auto.
split.
auto.
eexists.
split.
eauto.
apply Q.
*
eapply botbind_spec.
constructor.
auto.
auto.
auto.
split.
auto.
eexists.
split.
eauto.
eauto.
apply Q.
Qed.
Lemma mem_cshm_dom_correct:
mem_dom_spec _ ge mem_cshm_dom t_gamma (
gamma_bot iter_t_gamma).
Proof.
End num.