From compcert Require Import common.Separation.
From compcert Require Import common.Values.
From compcert Require Import common.Memdata.
From compcert Require Import common.Memory.
From compcert Require Import common.Globalenvs.
From compcert Require common.Errors.
From compcert Require Import cfrontend.Ctypes.
From compcert Require Import cfrontend.Clight.
From compcert Require Import lib.Maps.
From compcert Require Import lib.Coqlib.
From compcert Require Import lib.Integers.
From Velus Require Import Common.
From Velus Require Import Common.CompCertLib.
From Velus Require Import Ident.
From Velus Require Import Environment.
From Velus Require Import VelusMemory.
From Coq Require Import List.
Import List.ListNotations.
From Coq Require Import ZArith.BinInt.
From Coq Require Import Program.Tactics.
From Velus Require Import ObcToClight.MoreSeparation.
From Velus Require Import ObcToClight.Generation.
From Velus Require Import ObcToClight.GenerationProperties.
From Velus Require Import ObcToClight.Interface.
Import Obc.Syn.
Import Obc.Sem.
Import Obc.Typ.
Open Scope list.
Open Scope sep_scope.
Open Scope Z.
Definition match_value (
ov:
option val) (
v:
val) :
Prop :=
match ov with
|
None =>
True
|
Some v' =>
v =
v'
end.
Definition match_var (
ve:
venv) (
le:
temp_env) (
x:
ident) :
Prop :=
match le !
x with
|
Some v =>
match_value (
Env.find x ve)
v
|
None =>
False
end.
Section Staterep.
Variable ge :
composite_env.
Definition staterep_mems (
cls:
class) (
me:
menv) (
b:
block) (
ofs:
Z) '((
x,
ty):
ident *
type) :=
match field_offset ge x (
make_members cls)
with
|
Errors.OK d =>
contains_w (
type_chunk ty)
b (
ofs +
d) (
match_value (
find_val x me))
|
Errors.Error _ =>
sepfalse
end.
Fixpoint staterep
(
p:
program) (
clsnm:
ident) (
me:
menv) (
b:
block) (
ofs:
Z):
massert :=
match p with
|
nil =>
sepfalse
|
cls ::
p' =>
if ident_eqb clsnm cls.(
c_name)
then
sepall (
staterep_mems cls me b ofs)
cls.(
c_mems)
**
sepall (
fun '((
i,
c):
ident *
ident) =>
match field_offset ge i (
make_members cls)
with
|
Errors.OK d =>
staterep p'
c (
instance_match i me)
b (
ofs +
d)
|
Errors.Error _ =>
sepfalse
end)
cls.(
c_objs)
else staterep p'
clsnm me b ofs
end.
Definition staterep_objs (
p:
program) (
cls:
class) (
me:
menv) (
b:
block) (
ofs:
Z) '((
i,
c):
ident *
ident) :
massert :=
match field_offset ge i (
make_members cls)
with
|
Errors.OK d =>
staterep p c (
instance_match i me)
b (
ofs +
d)
|
Errors.Error _ =>
sepfalse
end.
Lemma staterep_objs_not_in:
forall objs p cls me i me_i b ofs,
~
InMembers i objs ->
sepall (
staterep_objs p cls me b ofs)
objs <-*->
sepall (
staterep_objs p cls (
add_inst i me_i me)
b ofs)
objs.
Proof.
Lemma staterep_cons:
forall cls prog clsnm me b ofs,
clsnm =
cls.(
c_name) ->
staterep (
cls ::
prog)
clsnm me b ofs <-*->
sepall (
staterep_mems cls me b ofs)
cls.(
c_mems)
**
sepall (
staterep_objs prog cls me b ofs)
cls.(
c_objs).
Proof.
intros *
Hnm.
apply ident_eqb_eq in Hnm.
simpl;
rewrite Hnm;
reflexivity.
Qed.
Lemma staterep_skip_cons:
forall cls prog clsnm me b ofs,
clsnm <>
cls.(
c_name) ->
staterep (
cls ::
prog)
clsnm me b ofs <-*->
staterep prog clsnm me b ofs.
Proof.
intros *
Hnm.
apply ident_eqb_neq in Hnm.
simpl;
rewrite Hnm;
reflexivity.
Qed.
Lemma staterep_skip_app:
forall clsnm prog oprog me b ofs,
find_class clsnm oprog =
None ->
staterep (
oprog ++
prog)
clsnm me b ofs <-*->
staterep prog clsnm me b ofs.
Proof.
Remark staterep_skip:
forall c clsnm prog prog'
me b ofs,
find_class clsnm prog =
Some (
c,
prog') ->
staterep prog clsnm me b ofs <-*->
staterep (
c ::
prog')
clsnm me b ofs.
Proof.
Lemma decidable_footprint_staterep:
forall p clsnm me b ofs,
decidable_footprint (
staterep p clsnm me b ofs).
Proof.
Lemma footprint_perm_staterep:
forall p clsnm me b ofs b'
lo hi,
footprint_perm_w (
staterep p clsnm me b ofs)
b'
lo hi.
Proof.
Hint Resolve decidable_footprint_staterep footprint_perm_staterep.
End Staterep.
The struct_in_bounds predicate.
Section StructInBounds.
Variable env :
composite_env.
Hypothesis env_consistent:
composite_env_consistent env.
Definition struct_in_bounds (
min max ofs:
Z) (
flds:
Ctypes.members) :=
min <=
ofs /\
ofs +
sizeof_struct env 0
flds <=
max.
Lemma struct_in_bounds_sizeof:
forall id co,
env!
id =
Some co ->
struct_in_bounds 0 (
sizeof_struct env 0 (
co_members co)) 0 (
co_members co).
Proof.
Lemma struct_in_bounds_weaken:
forall min'
max'
min max ofs flds,
struct_in_bounds min max ofs flds ->
min' <=
min ->
max <=
max' ->
struct_in_bounds min'
max'
ofs flds.
Proof.
Lemma struct_in_bounds_field:
forall min max ofs flds id d,
struct_in_bounds min max ofs flds ->
field_offset env id flds =
Errors.OK d ->
min <=
ofs +
d <=
max.
Proof.
Lemma struct_in_struct_in_bounds:
forall min max ofs flds id sid d co a,
struct_in_bounds min max ofs flds ->
field_offset env id flds =
Errors.OK d ->
field_type id flds =
Errors.OK (
Tstruct sid a) ->
env!
sid =
Some co ->
co_su co =
Struct ->
struct_in_bounds min max (
ofs +
d) (
co_members co).
Proof.
End StructInBounds.
Section StateRepProperties.
Variable prog:
program.
Variable gcenv:
composite_env.
Hypothesis gcenv_consistent:
composite_env_consistent gcenv.
Hypothesis make_members_co:
forall clsnm cls prog',
find_class clsnm prog =
Some (
cls,
prog') ->
(
exists co,
gcenv!
clsnm =
Some co
/\
co_su co =
Struct
/\
co_members co =
make_members cls
/\
attr_alignas (
co_attr co) =
None
/\
NoDupMembers (
co_members co)
/\
co.(
co_sizeof) <=
Ptrofs.max_unsigned).
Lemma struct_in_struct_in_bounds':
forall min max ofs clsid cls o c cls'
prog'
prog'',
wt_program prog ->
find_class clsid prog =
Some (
cls,
prog') ->
struct_in_bounds gcenv min max ofs (
make_members cls) ->
In (
o,
c)
cls.(
c_objs) ->
find_class c prog' =
Some (
cls',
prog'') ->
exists d,
field_offset gcenv o (
make_members cls) =
Errors.OK d
/\
struct_in_bounds gcenv min max (
ofs +
d) (
make_members cls').
Proof.
Hint Resolve Z.divide_trans.
Lemma range_staterep:
forall b clsnm,
wt_program prog ->
find_class clsnm prog <>
None ->
range_w b 0 (
sizeof gcenv (
type_of_inst clsnm)) -*>
staterep gcenv prog clsnm mempty b 0.
Proof.
intros *
WTp Hfind.
cut (
forall lo,
(
alignof gcenv (
type_of_inst clsnm) |
lo) ->
massert_imp (
range_w b lo (
lo +
sizeof gcenv (
type_of_inst clsnm)))
(
staterep gcenv prog clsnm mempty b lo)).
now intro HH;
apply HH;
apply Z.divide_0_r.
revert clsnm Hfind.
remember prog as prog1.
assert (
WTp' :=
WTp).
rewrite Heqprog1 in make_members_co,
WTp.
assert (
suffix prog1 prog)
as Hsub
by now rewrite Heqprog1.
clear Heqprog1.
induction prog1 as [|
cls prog'
IH];
intros clsnm Hfind lo Halign.
now apply not_None_is_Some in Hfind;
destruct Hfind;
discriminate.
inversion_clear WTp'
as [|? ?
WTc WTp''
Hnodup];
subst.
destruct (
ident_eqb cls.(
c_name)
clsnm)
eqn:
Hclsnm.
-
apply not_None_is_Some in Hfind.
destruct Hfind as ((
cls',
prog'') &
Hfind).
assert (
find_class clsnm prog =
Some (
cls',
prog''))
as Hprog
by apply find_class_sub_same with (1:=
Hfind) (2:=
WTp) (3:=
Hsub).
destruct (
make_members_co _ _ _ Hprog)
as (
co &
Hg &
Hsu &
Hmem &
Hattr &
Hndup & ?).
simpl in Hfind.
rewrite Hclsnm in Hfind.
injection Hfind;
intros He1 He2;
rewrite <-
He1, <-
He2 in *.
clear Hfind He1 He2.
pose proof (
co_members_alignof _ _ (
gcenv_consistent _ _ Hg)
Hattr)
as Hcoal.
rewrite Hmem in Hcoal.
unfold make_members in Hcoal.
apply Forall_app in Hcoal.
destruct Hcoal as [
Hcoal1 Hcoal2].
simpl in Halign.
rewrite Hg,
align_noattr in Halign.
assert (
Hndup':=
Hndup).
rewrite Hmem in Hndup'.
simpl.
unfold staterep_mems.
rewrite ident_eqb_sym in Hclsnm.
rewrite Hclsnm,
Hg, <-
Hmem.
rewrite split_range_fields
with (1:=
gcenv_consistent) (2:=
Hg) (3:=
Hsu) (4:=
Hndup).
rewrite Hmem at 2.
unfold make_members.
rewrite sepall_app.
apply sep_imp'.
+
pose proof (
field_translate_mem_type _ _ _ _ Hprog)
as Htype.
clear Hcoal2.
induction cls.(
c_mems)
as [|
m ms];
auto.
apply Forall_cons2 in Hcoal1.
destruct Hcoal1 as [
Hcoal1 Hcoal2].
apply sep_imp';
auto with datatypes.
destruct m;
simpl.
destruct (
field_offset gcenv i (
co_members co))
eqn:
Hfo;
auto.
setoid_rewrite Env.gempty.
rewrite sizeof_translate_chunk;
eauto.
apply range_contains';
auto with mem.
apply field_offset_aligned with (
ty:=
cltype t)
in Hfo.
apply Z.divide_add_r;
eauto.
rewrite <-
Hmem in Htype.
apply Htype;
auto with datatypes.
+
pose proof (
field_translate_obj_type _ _ _ _ Hprog)
as Htype.
rewrite <-
Hmem in Htype.
destruct WTc as [
Ho Hm];
clear Hm.
induction cls.(
c_objs)
as [|
o os];
auto.
simpl.
apply sep_imp'.
2:
now inv Ho;
apply Forall_cons2 in Hcoal2;
intuition.
apply Forall_forall with (
x:=
o)
in Ho;
auto with datatypes.
destruct o as [
o c].
apply Forall_cons2 in Hcoal2.
destruct Hcoal2 as [
Hcoal2 Hcoal3].
specialize (
Htype o c (
in_eq _ _)).
clear IHos Hcoal1 Hcoal3 os.
simpl in *.
destruct (
field_offset gcenv o (
co_members co))
eqn:
Hfo;
auto.
rewrite instance_match_empty.
specialize (
IH WTp'' (
suffix_cons _ _ _ Hsub)
c Ho (
lo +
z)%
Z).
apply not_None_is_Some in Ho.
destruct Ho as ((
c' &
prog''') &
Ho).
assert (
find_class c prog =
Some (
c',
prog'''))
as Hcin'
by apply find_class_sub_same with (1:=
Ho) (2:=
WTp)
(3:=
suffix_cons _ _ _ Hsub).
destruct (
make_members_co _ _ _ Hcin')
as (
co' &
Hg' &
Hsu' &
Hmem' &
Hattr' &
Hnodup').
rewrite Hg',
align_noattr in *.
apply IH.
apply Z.divide_add_r;
eauto.
eapply field_offset_aligned in Hfo;
eauto.
apply Z.divide_trans with (2:=
Hfo).
simpl.
rewrite Hg',
align_noattr.
apply Z.divide_refl.
-
simpl in Hfind.
rewrite Hclsnm in Hfind.
specialize (
IH WTp'' (
suffix_cons _ _ _ Hsub)
clsnm Hfind lo Halign).
rewrite ident_eqb_sym in Hclsnm.
apply ident_eqb_neq in Hclsnm.
rewrite staterep_skip_cons with (1:=
Hclsnm).
apply IH.
Qed.
Lemma staterep_deref_mem:
forall clsnm c prog prog'
m me b ofs x ty d v P,
find_class clsnm prog =
Some (
c,
prog') ->
m |=
staterep gcenv prog clsnm me b ofs **
P ->
In (
x,
ty)
c.(
c_mems) ->
find_val x me =
Some v ->
field_offset gcenv x (
make_members c) =
Errors.OK d ->
Clight.deref_loc (
cltype ty)
m b (
Ptrofs.repr (
ofs +
d))
v.
Proof.
Lemma staterep_field_offset:
forall m me c prog'
cls prog b ofs x ty P,
find_class c prog =
Some (
cls,
prog') ->
m |=
staterep gcenv prog c me b ofs **
P ->
In (
x,
ty) (
c_mems cls) ->
exists d,
field_offset gcenv x (
make_members cls) =
Errors.OK d
/\ 0 <=
ofs +
d <=
Ptrofs.max_unsigned.
Proof.
Lemma staterep_extract:
forall cid c prog'
me b ofs m i c'
P,
wt_program prog ->
find_class cid prog =
Some (
c,
prog') ->
(
In (
i,
c')
c.(
c_objs)
/\
m |=
staterep gcenv prog cid me b ofs **
P)
<->
exists objs objs'
d,
c.(
c_objs) =
objs ++ (
i,
c') ::
objs'
/\
field_offset gcenv i (
make_members c) =
Errors.OK d
/\
m |=
staterep gcenv prog c' (
instance_match i me)
b (
ofs +
d)
**
sepall (
staterep_mems gcenv c me b ofs)
c.(
c_mems)
**
sepall (
staterep_objs gcenv prog c me b ofs) (
objs ++
objs')
**
P.
Proof.
clear make_members_co.
intros *
WT Find.
pose proof Find as Fcid;
apply find_class_name in Fcid;
subst.
rewrite staterep_skip,
staterep_cons,
sep_assoc;
eauto.
split.
-
intros (
Hin &
Hmem).
apply sepall_in in Hin as (
objs &
objs' &
E &
Hp).
rewrite Hp,
sep_assoc,
sep_swap in Hmem.
unfold staterep_objs at 1
in Hmem.
destruct (
field_offset gcenv i (
make_members c))
as [
d|].
+
exists objs,
objs',
d;
intuition.
assert (
In (
i,
c') (
c_objs c))
by (
rewrite E,
in_app;
right;
apply in_eq).
apply find_class_app in Find as (
prog''&?&
Find);
subst.
assert (
find_class c'
prog'' =
None)
by (
eapply wt_program_not_class_in;
eauto).
assert (
c' <>
c_name c)
by (
eapply wt_program_not_same_name;
eauto;
eapply wt_program_app;
eauto).
rewrite staterep_skip_app,
staterep_skip_cons;
auto.
eapply sep_imp with (1 :=
Hmem);
auto.
repeat apply sep_imp';
auto.
apply sepall_weakenp;
intros (
i' &
c'')
Hin';
unfold staterep_objs.
cases.
assert (
In (
i',
c'') (
c_objs c))
by (
rewrite E,
in_app,
in_cns;
rewrite in_app in Hin';
tauto).
assert (
find_class c''
prog'' =
None)
by (
eapply wt_program_not_class_in;
eauto).
assert (
c'' <>
c_name c)
by (
eapply wt_program_not_same_name;
eauto;
eapply wt_program_app;
eauto).
rewrite staterep_skip_app,
staterep_skip_cons;
auto.
+
destruct Hmem;
contradiction.
-
intros (
objs &
objs' &
d &
E &
Hofs &
Hmem).
split.
+
rewrite E;
apply in_app;
right;
left;
auto.
+
rewrite (
sepall_breakout (
c_objs c)),
sep_assoc,
sep_swap;
eauto.
unfold staterep_objs at 1.
rewrite Hofs;
auto.
assert (
In (
i,
c') (
c_objs c))
by (
rewrite E,
in_app;
right;
apply in_eq).
apply find_class_app in Find as (
prog''&?&
Find);
subst.
assert (
find_class c'
prog'' =
None)
by (
eapply wt_program_not_class_in;
eauto).
assert (
c' <>
c_name c)
by (
eapply wt_program_not_same_name;
eauto;
eapply wt_program_app;
eauto).
rewrite staterep_skip_app,
staterep_skip_cons in Hmem;
auto.
eapply sep_imp with (1 :=
Hmem);
auto.
repeat apply sep_imp';
auto.
apply sepall_weakenp;
intros (
i' &
c'')
Hin';
unfold staterep_objs.
cases.
assert (
In (
i',
c'') (
c_objs c))
by (
rewrite E,
in_app,
in_cns;
rewrite in_app in Hin';
tauto).
assert (
find_class c''
prog'' =
None)
by (
eapply wt_program_not_class_in;
eauto).
assert (
c'' <>
c_name c)
by (
eapply wt_program_not_same_name;
eauto;
eapply wt_program_app;
eauto).
rewrite staterep_skip_app,
staterep_skip_cons;
auto.
Qed.
End StateRepProperties.
Section Fieldsrep.
Variable ge :
composite_env.
Hypothesis ge_consistent :
composite_env_consistent ge.
Definition fieldrep (
ve:
venv) (
flds:
members) (
b:
block) '((
x,
ty) :
ident *
Ctypes.type) :
massert :=
match field_offset ge x flds,
access_mode ty with
|
Errors.OK d,
By_value chunk =>
contains chunk b d (
match_value (
Env.find x ve))
|
_,
_ =>
sepfalse
end.
Definition fieldsrep (
ve:
venv) (
flds:
members) (
b:
block) :
massert :=
sepall (
fieldrep ve flds b)
flds.
Lemma fieldsrep_deref_mem:
forall m ve flds b x ty d v P,
m |=
fieldsrep ve flds b **
P ->
In (
x,
ty)
flds ->
Env.find x ve =
Some v ->
field_offset ge x flds =
Errors.OK d ->
Clight.deref_loc ty m b (
Ptrofs.repr d)
v.
Proof.
intros *
Hm Hin Hv Hoff.
unfold fieldsrep in Hm.
apply sepall_in in Hin.
destruct Hin as [
ws [
xs [
Hsplit Hin]]].
rewrite Hin in Hm.
clear Hsplit Hin.
do 2
apply sep_proj1 in Hm.
clear ws xs.
unfold fieldrep in Hm;
rewrite Hoff in Hm.
clear Hoff.
destruct (
access_mode ty)
eqn:
Haccess;
try contradiction.
apply loadv_rule in Hm;
auto with mem.
destruct Hm as [
v' [
Hloadv Hmatch]].
unfold match_value in Hmatch.
rewrite Hv in Hmatch.
clear Hv.
rewrite Hmatch in Hloadv.
clear Hmatch.
apply Clight.deref_loc_value with (1:=
Haccess) (2:=
Hloadv).
Qed.
Lemma footprint_perm_fieldsrep:
forall ve flds b b'
lo hi,
footprint_perm (
fieldsrep ve flds b)
b'
lo hi.
Proof.
Lemma footprint_decidable_fieldsrep:
forall ve flds b,
decidable_footprint (
fieldsrep ve flds b).
Proof.
Lemma fieldsrep_empty':
forall flds b,
NoDupMembers flds ->
(
forall x ty,
In (
x,
ty)
flds ->
exists chunk,
access_mode ty =
By_value chunk
/\ (
Memdata.align_chunk chunk |
alignof ge ty)) ->
sepall (
field_range ge flds b 0)
flds <-*->
fieldsrep vempty flds b.
Proof.
Lemma fieldsrep_empty:
forall nm co b,
ge!
nm =
Some co ->
co_su co =
Struct ->
NoDupMembers (
co_members co) ->
(
forall x ty,
In (
x,
ty) (
co_members co) ->
exists chunk,
access_mode ty =
By_value chunk
/\ (
Memdata.align_chunk chunk |
alignof ge ty)) ->
range b 0 (
co_sizeof co) -*>
fieldsrep vempty (
co_members co)
b.
Proof.
intros *
Hco Hstruct Hndups Hchunk.
rewrite split_range_fields
with (1:=
ge_consistent) (2:=
Hco) (3:=
Hstruct) (4:=
Hndups).
rewrite fieldsrep_empty'
with (1:=
Hndups) (2:=
Hchunk).
reflexivity.
Qed.
Lemma fieldsrep_any_empty:
forall flds ve b,
fieldsrep ve flds b -*>
fieldsrep vempty flds b.
Proof.
Lemma fieldsrep_nodup:
forall (
xs:
list (
ident *
type))
vs flds ve ob,
NoDup (
map fst xs ++
map fst flds) ->
fieldsrep ve flds ob <-*->
fieldsrep (
Env.adds (
map fst xs)
vs ve)
flds ob.
Proof.
Lemma fieldsrep_findvars:
forall ve xs vs b,
Forall2 (
fun x v =>
Env.find x ve =
v) (
map fst xs)
vs ->
fieldsrep ve xs b -*>
fieldsrep (
Env.adds_opt (
map fst xs)
vs vempty)
xs b.
Proof.
Lemma fieldsrep_field_offset:
forall m ve flds b P,
m |=
fieldsrep ve flds b **
P ->
forall x ty,
In (
x,
ty)
flds ->
exists d,
field_offset ge x flds =
Errors.OK d
/\ 0 <=
d <=
Ptrofs.max_unsigned.
Proof.
Lemma fieldsrep_add:
forall outb ve x v flds,
~
InMembers x flds ->
fieldsrep ve flds outb -*>
fieldsrep (
Env.add x v ve)
flds outb.
Proof.
End Fieldsrep.
Hint Resolve footprint_perm_fieldsrep footprint_decidable_fieldsrep.
Section SubRep.
Variable ge :
composite_env.
Definition fieldsrep_of (
id:
ident) (
b:
block):
massert :=
match ge !
id with
|
Some co =>
fieldsrep ge vempty (
co_members co)
b
|
None =>
sepfalse
end.
Definition subrep_inst '((
_, (
b,
t)):
ident * (
block *
Ctypes.type)):
massert :=
match t with
|
Tstruct id _ =>
fieldsrep_of id b
|
_ =>
sepfalse
end.
Definition subrep_inst_env (
e:
Clight.env) '((
x,
t):
ident *
Ctypes.type):
massert :=
match e !
x with
|
Some (
b,
Tstruct id _ as t') =>
if type_eq t t'
then fieldsrep_of id b else sepfalse
|
_ =>
sepfalse
end.
Definition subrep (
f:
method) (
e:
Clight.env) :
massert :=
sepall (
subrep_inst_env e)
(
make_out_vars (
instance_methods f)).
Lemma subrep_eqv:
forall f e,
Permutation.Permutation (
make_out_vars (
instance_methods f))
(
map drop_block (
PTree.elements e)) ->
subrep f e <-*->
sepall subrep_inst (
PTree.elements e).
Proof.
Definition range_inst '((
_, (
b,
t)):
ident * (
block *
Ctypes.type)) :
massert :=
range b 0 (
Ctypes.sizeof ge t).
Definition range_inst_env (
e:
Clight.env) (
x:
ident) :
massert :=
match e !
x with
|
Some (
b,
t) =>
range b 0 (
Ctypes.sizeof ge t)
|
None =>
sepfalse
end.
Definition subrep_range (
e:
Clight.env) :
massert :=
sepall range_inst (
PTree.elements e).
Lemma subrep_range_eqv:
forall e,
subrep_range e <-*->
sepall (
range_inst_env e) (
map fst (
PTree.elements e)).
Proof.
Remark decidable_footprint_subrep_inst:
forall x,
decidable_footprint (
subrep_inst x).
Proof.
intros (
x, (
b,
t)).
simpl;
destruct t;
auto.
unfold fieldsrep_of;
now destruct ge !
i.
Qed.
Lemma decidable_subrep:
forall f e,
decidable_footprint (
subrep f e).
Proof.
Remark footprint_perm_subrep_inst:
forall x b lo hi,
footprint_perm (
subrep_inst x)
b lo hi.
Proof.
intros (
x, (
b,
t))
b'
lo hi.
simpl;
destruct t;
auto;
unfold fieldsrep_of;
now destruct ge !
i.
Qed.
Remark disjoint_footprint_range_inst:
forall l b lo hi,
~
InMembers b (
map snd l) ->
disjoint_footprint (
range b lo hi) (
sepall range_inst l).
Proof.
induction l as [|(
x, (
b',
t'))];
simpl;
intros b lo hi Notin.
-
apply sepemp_disjoint.
-
rewrite disjoint_footprint_sepconj;
split.
+
intros blk ofs Hfp Hfp'.
apply Notin.
left.
simpl in *.
destruct Hfp',
Hfp.
now transitivity blk.
+
apply IHl.
intro;
apply Notin;
now right.
Qed.
Hint Resolve decidable_footprint_subrep_inst decidable_subrep footprint_perm_subrep_inst.
Lemma range_wand_equiv:
forall e,
composite_env_consistent ge ->
Forall (
wf_struct ge) (
map drop_block (
PTree.elements e)) ->
NoDupMembers (
map snd (
PTree.elements e)) ->
subrep_range e <-*->
sepall subrep_inst (
PTree.elements e)
** (
sepall subrep_inst (
PTree.elements e) -*
subrep_range e).
Proof.
unfold subrep_range.
intros *
Consistent Forall Nodup.
split.
2:
now rewrite sep_unwand;
auto.
induction (
PTree.elements e)
as [|(
x, (
b,
t))];
simpl in *.
-
rewrite <-
hide_in_sepwand;
auto.
now rewrite <-
sepemp_right.
-
inversion_clear Forall as [|? ?
Hidco Forall'];
subst;
rename Forall'
into Forall.
destruct Hidco as (
id &
co &
Ht &
Hco & ? & ? & ?);
simpl in Ht.
inversion_clear Nodup as [|? ? ?
Notin Nodup'].
unfold fieldsrep_of.
rewrite Ht,
Hco.
rewrite sep_assoc.
rewrite IHl at 1;
auto.
rewrite <-
unify_distinct_wands;
auto.
+
repeat rewrite <-
sep_assoc.
apply sep_imp';
auto.
rewrite sep_comm,
sep_assoc,
sep_swap.
apply sep_imp';
auto.
rewrite <-
range_imp_with_wand;
auto.
simpl.
rewrite Hco.
eapply fieldsrep_empty;
eauto.
+
now apply disjoint_footprint_range_inst.
+
simpl;
rewrite Hco.
rewrite fieldsrep_empty;
eauto.
reflexivity.
+
apply subseteq_footprint_sepall.
intros (
x', (
b',
t'))
Hin;
simpl.
assert (
In (
x',
t') (
map drop_block l))
by (
change (
x',
t')
with (
drop_block (
x', (
b',
t')));
apply in_map;
auto).
eapply Forall_forall in Forall;
eauto.
simpl in Forall.
destruct Forall as (
id' &
co' &
Ht' &
Hco' & ? & ? & ?).
unfold fieldsrep_of.
rewrite Ht',
Hco'.
simpl.
rewrite Hco'.
rewrite fieldsrep_empty;
eauto.
reflexivity.
Qed.
Lemma subrep_extract:
forall f f'
e m o c'
P,
M.MapsTo (
o,
f')
c' (
instance_methods f) ->
m |=
subrep f e **
P <->
exists b co ws xs,
e ! (
prefix_out f'
o) =
Some (
b,
type_of_inst (
prefix_fun f'
c'))
/\
ge ! (
prefix_fun f'
c') =
Some co
/\
make_out_vars (
instance_methods f) =
ws ++ (
prefix_out f'
o,
type_of_inst (
prefix_fun f'
c')) ::
xs
/\
m |=
fieldsrep ge vempty (
co_members co)
b
**
sepall (
subrep_inst_env e) (
ws ++
xs)
**
P.
Proof.
intros *
Hin.
unfold subrep.
assert (
In (
prefix_out f'
o,
type_of_inst (
prefix_fun f'
c'))
(
make_out_vars (
instance_methods f)))
as Hin'.
{
apply M.elements_1,
setoid_in_key_elt in Hin.
apply in_map with
(
f:=
fun x =>
let '(
o0,
f0,
cid) :=
x in (
prefix_out f0 o0,
type_of_inst (
prefix_fun f0 cid)))
in Hin.
unfold make_out_vars;
auto.
}
clear Hin.
split.
-
apply sepall_in in Hin';
destruct Hin'
as (
ws &
xs &
Hin &
Heq).
rewrite Heq,
sep_assoc.
intro Hmem.
unfold subrep_inst_env at 1
in Hmem.
destruct e ! (
prefix_out f'
o)
as [(
oblk,
t)|]; [|
destruct Hmem;
contradiction].
destruct t;
try (
destruct Hmem;
contradiction).
destruct (
type_eq (
type_of_inst (
prefix_fun f'
c')) (
Tstruct i a))
as [
Eq|]; [|
destruct Hmem;
contradiction].
unfold type_of_inst in Eq.
inv Eq.
unfold fieldsrep_of in *.
destruct ge ! (
prefix_fun f'
c'); [|
destruct Hmem;
contradiction].
exists oblk,
c,
ws,
xs;
intuition.
-
intros (
oblk &
c &
ws' &
xs' &
He &
Hge &
Eq &?).
rewrite sepall_breakout,
sep_assoc;
eauto.
eapply sep_imp;
eauto.
unfold subrep_inst_env.
rewrite He;
unfold type_of_inst;
rewrite type_eq_refl.
unfold fieldsrep_of;
rewrite Hge;
auto.
Qed.
End SubRep.
Lemma free_exists:
forall ge e m P,
let gcenv :=
Clight.genv_cenv ge in
m |=
subrep_range gcenv e **
P ->
exists m',
Mem.free_list m (
blocks_of_env ge e) =
Some m'
/\
m' |=
P.
Proof.
Definition varsrep (
f:
method) (
ve:
venv) (
le:
temp_env) :
massert :=
pure (
Forall (
match_var ve le) (
map fst (
f.(
m_in) ++
f.(
m_vars)))).
Lemma varsrep_any_empty:
forall f ve le,
varsrep f ve le -*>
varsrep f vempty le.
Proof.
Lemma varsrep_corres_out:
forall f ve le x t v,
In (
x,
t) (
m_out f) ->
varsrep f ve le -*>
varsrep f (
Env.add x v ve)
le.
Proof.
Lemma varsrep_add:
forall f ve le x v,
varsrep f ve le -*>
varsrep f (
Env.add x v ve) (
PTree.set x v le).
Proof.
Lemma varsrep_add':
forall f ve le x v y v',
~
InMembers y (
m_in f ++
m_vars f) ->
varsrep f ve le -*>
varsrep f (
Env.add x v ve) (
PTree.set x v (
PTree.set y v'
le)).
Proof.
Lemma varsrep_add'':
forall f ve le x v y v',
~
InMembers y (
m_in f ++
m_vars f) ->
x <>
y ->
varsrep f (
Env.add x v ve)
le -*>
varsrep f (
Env.add x v ve) (
PTree.set y v'
le).
Proof.
Lemma varsrep_add''':
forall f ve le x v,
~
InMembers x (
m_in f ++
m_vars f) ->
varsrep f ve le -*>
varsrep f ve (
PTree.set x v le).
Proof.
Definition var_ptr (
b:
block) :
val :=
Vptr b Ptrofs.zero.
Section MatchStates.
Variable ge :
composite_env.
Definition outputrep
(
c:
class) (
f:
method) (
ve:
venv) (
le:
temp_env)
(
outb_co:
option (
block *
composite)) :
massert :=
case_out f
sepemp
(
fun x _ =>
pure (
match_var ve le x))
(
fun _ =>
match outb_co with
|
Some (
outb,
outco) =>
pure (
le ! (
prefix obc2c out) =
Some (
var_ptr outb))
**
pure (
ge ! (
prefix_fun f.(
m_name)
c.(
c_name)) =
Some outco)
**
fieldsrep ge ve outco.(
co_members)
outb
|
None =>
sepfalse
end).
Lemma outputrep_add_prefix:
forall c f ve le outb_co f'
x v,
atom f' ->
outputrep c f ve le outb_co <-*->
outputrep c f ve (
PTree.set (
prefix_temp f'
x)
v le)
outb_co.
Proof.
Lemma outputrep_nil:
forall c f ve le outb_co,
f.(
m_out) = [] ->
outputrep c f ve le outb_co <-*->
sepemp.
Proof.
Lemma outputrep_singleton:
forall c f ve le m outb_co x t P,
f.(
m_out) = [(
x,
t)] ->
(
m |=
outputrep c f ve le outb_co **
P <->
m |=
P /\
match_var ve le x).
Proof.
Lemma outputrep_notnil:
forall c f ve le m outb_co P,
(1 <
length f.(
m_out))%
nat ->
(
m |=
outputrep c f ve le outb_co **
P <->
exists outb outco,
outb_co =
Some (
outb,
outco)
/\
m |=
fieldsrep ge ve outco.(
co_members)
outb **
P
/\
le ! (
prefix obc2c out) =
Some (
var_ptr outb)
/\
ge ! (
prefix_fun f.(
m_name)
c.(
c_name)) =
Some outco).
Proof.
intros *
Length.
unfold outputrep,
case_out;
split;
intros *
H;
destruct_list f.(
m_out)
as (?, ?) ? ?;
((
now contradict Length;
simpl;
apply lt_irrefl)
|| (
now contradict Length;
simpl;
apply lt_n_0)
||
idtac).
-
destruct outb_co as [(?, ?)|].
+
repeat rewrite sep_assoc in H;
repeat rewrite sep_pure in H.
do 3
econstructor;
tauto.
+
apply sep_proj1 in H;
contradiction.
-
destruct H as (? & ? &
H & ?).
rewrite H;
repeat rewrite sep_assoc;
repeat rewrite sep_pure;
tauto.
Qed.
Definition prefix_out_env (
e:
Clight.env) :
Prop :=
forall x b t,
e !
x =
Some (
b,
t) ->
exists o f,
x =
prefix_out o f.
Definition bounded_struct_of_class (
c:
class) (
sofs:
ptrofs) :
Prop :=
struct_in_bounds ge 0
Ptrofs.max_unsigned (
Ptrofs.unsigned sofs) (
make_members c).
Lemma bounded_struct_of_class_ge0:
forall c sofs,
bounded_struct_of_class c sofs ->
0 <=
Ptrofs.unsigned sofs.
Proof.
Hint Resolve bounded_struct_of_class_ge0.
Definition selfrep (
p:
program) (
c:
class) (
me:
menv) (
le:
Clight.temp_env) (
sb:
block) (
sofs:
ptrofs) :
massert :=
pure (
le ! (
prefix obc2c self) =
Some (
Vptr sb sofs))
**
pure (
bounded_struct_of_class c sofs)
**
staterep ge p c.(
c_name)
me sb (
Ptrofs.unsigned sofs).
Lemma selfrep_conj:
forall m p c me le sb sofs P,
m |=
selfrep p c me le sb sofs **
P
<->
m |=
staterep ge p c.(
c_name)
me sb (
Ptrofs.unsigned sofs) **
P
/\
le ! (
prefix obc2c self) =
Some (
Vptr sb sofs)
/\
bounded_struct_of_class c sofs.
Proof.
Definition outputsrep (
f:
method) (
e:
Clight.env) :
massert :=
pure (
prefix_out_env e)
**
subrep ge f e
** (
subrep ge f e -*
subrep_range ge e).
Definition match_states
(
p:
program) (
c:
class) (
f:
method) '((
me,
ve):
menv *
venv)
'((
e,
le):
Clight.env *
Clight.temp_env)
(
sb:
block) (
sofs:
ptrofs) (
outb_co:
option (
block *
composite)):
massert :=
pure (
wt_state p me ve c (
meth_vars f))
**
selfrep p c me le sb sofs
**
outputrep c f ve le outb_co
**
outputsrep f e
**
varsrep f ve le.
Lemma match_states_conj:
forall p c f me ve e le m sb sofs outb_co P,
m |=
match_states p c f (
me,
ve) (
e,
le)
sb sofs outb_co **
P <->
m |=
staterep ge p c.(
c_name)
me sb (
Ptrofs.unsigned sofs)
**
outputrep c f ve le outb_co
**
subrep ge f e
** (
subrep ge f e -*
subrep_range ge e)
**
varsrep f ve le
**
P
/\
bounded_struct_of_class c sofs
/\
wt_state p me ve c (
meth_vars f)
/\
le ! (
prefix obc2c self)=
Some (
Vptr sb sofs)
/\
prefix_out_env e.
Proof.
Lemma match_states_wt_state:
forall p c f me ve e le m sb sofs outb_co P,
m |=
match_states p c f (
me,
ve) (
e,
le)
sb sofs outb_co **
P ->
wt_state p me ve c (
meth_vars f).
Proof.
Section MatchStatesPreservation.
various basic 'Hoare triples' for memory assignments *
Variable
Obc program
(
prog :
program)
Obc class
(
ownerid :
ident) (
owner :
class) (
prog' :
program)
Obc method
(
callerid :
ident) (
caller :
method)
Obc state
(
me :
menv) (
ve :
venv)
Clight state
(
m :
Mem.mem) (
e :
Clight.env) (
le :
temp_env)
Clight self structure
(
sb :
block) (
sofs :
ptrofs)
Clight output structure
(
outb_co :
option (
block *
composite))
frame
(
P :
massert).
Hypothesis (
Findcl :
find_class ownerid prog =
Some (
owner,
prog'))
(
Findmth :
find_method callerid owner.(
c_methods) =
Some caller)
(
OutputMatch :
forall outco , (1 <
length (
m_out caller))%
nat ->
ge ! (
prefix_fun callerid ownerid) =
Some outco ->
map translate_param caller.(
m_out) =
outco.(
co_members)).
Variable (
v :
val) (
x :
ident) (
ty :
type).
Hypothesis (
WTv :
wt_val v ty).
Lemma outputrep_assign_gt1_mem:
In (
x,
ty)
caller.(
m_out) ->
(1 <
length (
m_out caller))%
nat ->
m |=
outputrep owner caller ve le outb_co **
P ->
exists m'
b co d,
outb_co =
Some (
b,
co)
/\
field_offset ge x (
co_members co) =
Errors.OK d
/\
Clight.assign_loc ge (
cltype ty)
m b (
Ptrofs.repr d)
v m'
/\
m' |=
outputrep owner caller (
Env.add x v ve)
le outb_co **
P.
Proof.
intros *
Hin Len Hmem.
apply outputrep_notnil in Hmem as (
b &
co &
Hout &
Hrep &?&
Hco);
auto.
erewrite find_class_name,
find_method_name in Hco;
eauto.
apply in_map with (
f:=
translate_param)
in Hin.
erewrite OutputMatch in Hin;
eauto.
pose proof (
m_nodupvars caller)
as Nodup.
apply sepall_in in Hin as [
ws [
ys [
Hys Heq]]].
unfold fieldsrep in Hrep.
Local Opaque sepconj match_states.
rewrite Heq in Hrep;
simpl in *.
destruct (
field_offset ge x (
co_members co))
as [
d|]
eqn:
Hofs;
rewrite sep_assoc in Hrep;
try (
destruct Hrep;
contradiction).
rewrite cltype_access_by_value in Hrep.
eapply Separation.storev_rule'
with (
v:=
v)
in Hrep as (
m' & ? &
Hrep);
eauto with mem.
exists m',
b,
co,
d;
intuition;
eauto using assign_loc.
rewrite outputrep_notnil;
auto.
erewrite find_class_name,
find_method_name;
eauto.
exists b,
co;
split;
intuition.
unfold fieldsrep,
fieldrep.
rewrite Heq,
Hofs,
cltype_access_by_value,
sep_assoc.
eapply sep_imp;
eauto.
-
unfold hasvalue,
match_value;
simpl.
rewrite Env.gss.
now rewrite <-
wt_val_load_result.
-
apply sep_imp';
auto.
do 2
apply NoDupMembers_app_r in Nodup.
rewrite fst_NoDupMembers, <-
translate_param_fst, <-
fst_NoDupMembers in Nodup;
auto.
erewrite OutputMatch,
Hys in Nodup;
auto.
apply NoDupMembers_app_cons in Nodup.
destruct Nodup as (
Notin &
Nodup).
rewrite sepall_swapp;
eauto.
intros (
x' &
t')
Hin.
rewrite Env.gso;
auto.
intro;
subst x'.
apply Notin.
eapply In_InMembers;
eauto.
Qed.
Lemma outputrep_assign_singleton_mem:
m_out caller = [(
x,
ty)] ->
outputrep owner caller ve le outb_co -*>
outputrep owner caller (
Env.add x v ve) (
PTree.set x v le)
outb_co.
Proof.
Lemma outputrep_assign_var_mem:
~
InMembers x (
m_out caller) ->
In (
x,
ty) (
meth_vars caller) ->
m |=
outputrep owner caller ve le outb_co **
P ->
m |=
outputrep owner caller (
Env.add x v ve) (
PTree.set x v le)
outb_co **
P.
Proof.
Lemma match_states_assign_state_mem:
m |=
match_states prog owner caller (
me,
ve) (
e,
le)
sb sofs outb_co
**
P ->
In (
x,
ty)
owner.(
c_mems) ->
exists m'
d,
field_offset ge x (
make_members owner) =
Errors.OK d
/\
Clight.assign_loc ge (
cltype ty)
m sb (
Ptrofs.repr (
Ptrofs.unsigned sofs +
d))
v m'
/\
m' |=
match_states prog owner caller (
add_val x v me,
ve) (
e,
le)
sb sofs outb_co
**
P.
Proof.
End MatchStatesPreservation.
End MatchStates.
Section FunctionEntry.
results about allocation of the environment and temporary *
environment at function entry *
Remark bind_parameter_temps_exists:
forall xs s ts o to ys vs sptr optr,
s <>
o ->
NoDupMembers xs ->
~
InMembers s xs ->
~
InMembers o xs ->
~
InMembers s ys ->
~
InMembers o ys ->
length xs =
length vs ->
exists le',
bind_parameter_temps ((
s,
ts) :: (
o,
to) ::
xs)
(
sptr ::
optr ::
vs)
(
create_undef_temps ys) =
Some le'
/\
Forall (
match_var (
Env.adds (
map fst xs)
vs vempty)
le') (
map fst (
xs ++
ys)).
Proof.
Remark bind_parameter_temps_exists_noout:
forall xs s ts ys vs sptr,
NoDupMembers xs ->
~
InMembers s xs ->
~
InMembers s ys ->
length xs =
length vs ->
exists le',
bind_parameter_temps ((
s,
ts) ::
xs)
(
sptr ::
vs)
(
create_undef_temps ys) =
Some le'
/\
Forall (
match_var (
Env.adds (
map fst xs)
vs vempty)
le') (
map fst (
xs ++
ys)).
Proof.
Remark alloc_mem_vars:
forall ge vars e m e'
m'
P,
let gcenv :=
Clight.genv_cenv ge in
m |=
P ->
NoDupMembers vars ->
Forall (
fun xt =>
sizeof gcenv (
snd xt) <=
Ptrofs.max_unsigned)
vars ->
alloc_variables ge e m vars e'
m' ->
m' |=
sepall (
range_inst_env gcenv e') (
var_names vars) **
P.
Proof.
Lemma alloc_result:
forall ge f m P,
let vars :=
instance_methods f in
let gcenv :=
Clight.genv_cenv ge in
composite_env_consistent ge ->
Forall (
fun xt =>
sizeof ge (
snd xt) <=
Ptrofs.max_unsigned /\
wf_struct gcenv xt)
(
make_out_vars vars) ->
NoDupMembers (
make_out_vars vars) ->
m |=
P ->
exists e'
m',
alloc_variables ge empty_env m (
make_out_vars vars)
e'
m'
/\
prefix_out_env e'
/\
m' |=
subrep gcenv f e'
** (
subrep gcenv f e' -*
subrep_range gcenv e')
**
P.
Proof.
'Hoare triple' for function entry, depending on the number *
of outputs (and inputs, consequently): *
0 and 1: no 'out' pointer parameter, we only need *
staterep for the sub-state, and we get *
match_states in the callee *
1 < n : 'out' pointer parameter, we need both *
staterep for the sub-state and fieldsrep for the *
output structure, we get match_states in the *
callee *
Variable (
main_node :
ident)
(
prog :
program)
(
tprog :
Clight.program)
(
do_sync :
bool)
(
all_public :
bool).
Let tge :=
Clight.globalenv tprog.
Let gcenv :=
Clight.genv_cenv tge.
Hypothesis (
TRANSL :
translate do_sync all_public main_node prog =
Errors.OK tprog)
(
WT :
wt_program prog).
Lemma function_entry_match_states:
forall cid c prog'
fid f fd me vs,
method_spec c f prog fd ->
find_class cid prog =
Some (
c,
prog') ->
find_method fid c.(
c_methods) =
Some f ->
wt_mem me prog c ->
Forall2 (
fun v xt =>
wt_val v (
snd xt))
vs (
m_in f) ->
case_out f
(
forall m sb sofs P,
bounded_struct_of_class gcenv c sofs ->
m |=
staterep gcenv prog cid me sb (
Ptrofs.unsigned sofs) **
P ->
exists e_f le_f m_f,
function_entry2 tge fd (
Vptr sb sofs ::
vs)
m e_f le_f m_f
/\
m_f |=
match_states gcenv prog c f (
me,
Env.adds (
map fst f.(
m_in))
vs vempty) (
e_f,
le_f)
sb sofs None
**
P)
(
fun _ _ =>
forall m sb sofs P,
bounded_struct_of_class gcenv c sofs ->
m |=
staterep gcenv prog cid me sb (
Ptrofs.unsigned sofs) **
P ->
exists e_f le_f m_f,
function_entry2 tge fd (
Vptr sb sofs ::
vs)
m e_f le_f m_f
/\
m_f |=
match_states gcenv prog c f (
me,
Env.adds (
map fst f.(
m_in))
vs vempty) (
e_f,
le_f)
sb sofs None
**
P)
(
fun _ =>
forall m sb sofs instb instco P,
bounded_struct_of_class gcenv c sofs ->
m |=
staterep gcenv prog cid me sb (
Ptrofs.unsigned sofs)
**
fieldsrep gcenv vempty (
co_members instco)
instb
**
P ->
gcenv ! (
prefix_fun fid cid) =
Some instco ->
exists e_f le_f m_f,
function_entry2 tge fd (
Vptr sb sofs ::
var_ptr instb ::
vs)
m e_f le_f m_f
/\
m_f |=
match_states gcenv prog c f (
me,
Env.adds (
map fst f.(
m_in))
vs vempty) (
e_f,
le_f)
sb sofs
(
Some (
instb,
instco))
**
P).
Proof.
intros *
Spec Findcl Findmth WTmem WTvs.
assert (
NoDupMembers (
make_out_vars (
instance_methods f)))
by (
eapply NoDupMembers_make_out_vars;
eauto;
eapply wt_program_find_class;
eauto).
assert (
Forall (
fun xt =>
sizeof tge (
snd xt) <=
Ptrofs.max_unsigned /\
wf_struct gcenv xt)
(
make_out_vars (
instance_methods f)))
by (
eapply instance_methods_caract;
eauto).
assert (
Datatypes.length (
map translate_param (
m_in f)) =
Datatypes.length vs)
by (
symmetry;
rewrite map_length;
eapply Forall2_length;
eauto).
assert (
wt_state prog me vempty c (
meth_vars f))
by (
split;
eauto).
assert (
NoDup (
map fst (
m_in f)))
by (
apply fst_NoDupMembers,
m_nodupin).
assert (
Forall2 (
fun y xt =>
In (
y,
snd xt) (
meth_vars f)) (
map fst (
m_in f)) (
m_in f))
by (
apply Forall2_map_1,
Forall2_same,
Forall_forall;
intros (
x,
t)
Hin;
simpl;
apply in_app;
auto).
unfold method_spec,
case_out in *.
subst gcenv tge.
destruct_list (
m_out f)
as (
a,
ta) (?,?) ? :
Hout;
simpl in Spec;
destruct Spec as (
P_f &?&?&?&
T_f &?&?&?&?);
intros * ?
Hmem;
try intros Hinstco.
-
edestruct alloc_result as (
e_f &
m_f &?&?&?);
eauto.
edestruct
(
bind_parameter_temps_exists_noout (
map translate_param f.(
m_in))
(
prefix obc2c self) (
type_of_inst_p (
c_name c))
(
make_out_temps (
instance_methods_temp (
rev prog)
f)
++
map translate_param (
m_vars f))
vs (
Vptr sb sofs))
as (
le_f &
Bind &
Vars);
eauto.
assert (
le_f ! (
prefix obc2c self) =
Some (
Vptr sb sofs))
by (
eapply bind_parameter_temps_implies in Bind;
eauto).
setoid_rewrite <-
P_f in Bind.
exists e_f,
le_f,
m_f;
split.
+
constructor;
auto;
try congruence.
+
apply match_states_conj;
intuition;
eauto using m_nodupvars.
erewrite find_class_name;
eauto.
rewrite sep_swap,
outputrep_nil, <-
sepemp_left,
sep_swap,
sep_swap23,
sep_swap34,
sep_swap23,
sep_swap;
auto.
apply sep_pure;
split;
auto.
repeat rewrite map_app in *.
repeat rewrite translate_param_fst in Vars.
rewrite 2
Forall_app in Vars;
rewrite Forall_app;
tauto.
-
assert (
prefix obc2c self <>
a).
{
intro contra;
subst.
pose proof (
m_good_out f)
as Good.
rewrite Hout in Good.
assert (
In (
prefix obc2c self,
ta) [(
prefix obc2c self,
ta)])
as Hin by (
left;
auto).
apply Good,
AtomOrGensym_inv in Hin;
auto. }
edestruct alloc_result as (
e_f &
m_f &?&?&?);
eauto.
edestruct
(
bind_parameter_temps_exists_noout (
map translate_param f.(
m_in))
(
prefix obc2c self) (
type_of_inst_p (
c_name c))
((
a,
cltype ta) ::
make_out_temps (
instance_methods_temp (
rev prog)
f)
++
map translate_param (
m_vars f))
vs (
Vptr sb sofs))
as (
le_f &
Bind &
Vars);
eauto;
try eapply NotInMembers_cons;
eauto.
assert (
le_f ! (
prefix obc2c self) =
Some (
Vptr sb sofs))
by (
eapply bind_parameter_temps_implies in Bind;
eauto).
setoid_rewrite <-
P_f in Bind.
exists e_f,
le_f,
m_f;
split.
+
constructor;
auto;
congruence.
+
apply match_states_conj;
intuition;
eauto using m_nodupvars.
erewrite find_class_name;
eauto.
rewrite sep_swap,
outputrep_singleton,
sep_swap,
sep_swap23,
sep_swap34,
sep_swap23,
sep_swap;
eauto.
repeat rewrite map_app,
map_cons,
map_app in *.
repeat rewrite translate_param_fst in Vars.
rewrite Forall_app,
Forall_cons2,
Forall_app in Vars.
setoid_rewrite sep_pure;
split; [
split|];
auto;
try tauto.
rewrite map_app,
Forall_app;
tauto.
-
assert (1 <
Datatypes.length (
m_out f))%
nat
by (
rewrite Hout;
simpl;
omega).
assert (
prefix obc2c self <>
prefix obc2c out)
as Hnso
by (
apply prefix_injective';
right;
prove_str_to_pos_neq).
edestruct alloc_result as (
e_f &
m_f &?&?&?);
eauto.
edestruct
(
bind_parameter_temps_exists (
map translate_param f.(
m_in)) (
prefix obc2c self) (
type_of_inst_p (
c_name c))
(
prefix obc2c out) (
type_of_inst_p (
prefix_fun (
m_name f) (
c_name c)))
(
make_out_temps (
instance_methods_temp (
rev prog)
f)
++
map translate_param f.(
m_vars))
vs (
Vptr sb sofs) (
var_ptr instb))
as (
le_f &
Bind &
Vars);
eauto.
assert (
le_f ! (
prefix obc2c self) =
Some (
Vptr sb sofs) /\
le_f ! (
prefix obc2c out) =
Some (
var_ptr instb))
as (?&?)
by (
eapply bind_parameter_temps_implies_two in Bind;
eauto).
setoid_rewrite <-
P_f in Bind;
setoid_rewrite <-
T_f in Bind.
exists e_f,
le_f,
m_f;
split.
+
constructor;
auto;
congruence.
+
apply match_states_conj;
intuition;
eauto using m_nodupvars.
erewrite find_class_name;
eauto.
rewrite sep_swap,
outputrep_notnil;
auto.
erewrite find_class_name,
find_method_name;
eauto.
exists instb,
instco;
intuition;
auto.
rewrite sep_swap23,
sep_swap,
sep_swap34,
sep_swap23,
sep_swap34,
sep_swap45,
sep_swap34,
sep_swap23,
sep_swap.
setoid_rewrite sep_pure;
split.
*
repeat rewrite map_app in *.
repeat rewrite translate_param_fst in Vars.
rewrite 2
Forall_app in Vars.
rewrite Forall_app;
tauto.
*
eapply sep_imp;
eauto.
repeat apply sep_imp';
auto.
rewrite fieldsrep_nodup;
eauto.
erewrite <-
output_match;
eauto.
rewrite translate_param_fst.
eapply NoDup_app_weaken.
rewrite Permutation.Permutation_app_comm,
NoDup_swap, <-2
map_app.
apply fst_NoDupMembers,
m_nodupvars.
Qed.
End FunctionEntry.
Section MainProgram.
Variable (
main_node :
ident)
(
prog :
program)
(
tprog :
Clight.program)
(
do_sync :
bool)
(
all_public :
bool).
Let tge :=
Clight.globalenv tprog.
Let gcenv :=
Clight.genv_cenv tge.
Hypothesis (
TRANSL :
translate do_sync all_public main_node prog =
Errors.OK tprog)
(
WT :
wt_program prog).
Let out_step :=
prefix out step.
Let t_out_step :=
type_of_inst (
prefix_fun step main_node).
Let main_step :=
main_step _ _ _ _ _ TRANSL.
Let main_f :=
main_f _ _ _ _ _ TRANSL.
Lemma main_with_output_structure:
forall m P,
(1 <
length (
m_out main_step))%
nat ->
m |=
P ->
exists m'
step_b step_co,
alloc_variables tge empty_env m (
fn_vars main_f)
(
PTree.set out_step (
step_b,
t_out_step)
empty_env)
m'
/\
gcenv ! (
prefix_fun step main_node) =
Some step_co
/\
m' |=
fieldsrep gcenv vempty step_co.(
co_members)
step_b **
P.
Proof.
Lemma init_mem:
exists m sb,
Genv.init_mem tprog =
Some m
/\
Genv.find_symbol tge (
prefix_glob (
prefix self main_id)) =
Some sb
/\
m |=
staterep gcenv prog main_node mempty sb Z0.
Proof.
End MainProgram.
Hint Resolve match_states_wt_state bounded_struct_of_class_ge0.