Module MemObsEq.
(* A compcert injection would not work because it allows permissions to go up *)
(* Moreover, we require that undefined values are matched by the target memory, unlike compcert injections. Although the latter is not neccessary and in retrospect may be a limiting factor. For example we would be able to reuse this development for our final erasure if we allowed undefined values to become more defined. *)
(** Weak injection between memories *)
Record weak_mem_obs_eq (f : memren) (mc mf : mem) :=
{
domain_invalid: forall b, ~(Mem.valid_block mc b) -> f b = None;
domain_valid: forall b, Mem.valid_block mc b -> exists b', f b = Some b';
codomain_valid: forall b1 b2, f b1 = Some b2 -> Mem.valid_block mf b2;
injective: forall b1 b1' b2, f b1 = Some b2 ->
f b1' = Some b2 ->
b1 = b1';
perm_obs_weak :
forall b1 b2 ofs (Hrenaming: f b1 = Some b2),
Mem.perm_order''
(permission_at mc b1 ofs Cur)
(permission_at mf b2 ofs Cur)}.
(** Strong injection between memories *)
Record strong_mem_obs_eq (f : memren) (mc mf : mem) :=
{ perm_obs_strong :
forall b1 b2 ofs (Hrenaming: f b1 = Some b2),
permission_at mf b2 ofs Cur =
(permission_at mc b1 ofs Cur);
val_obs_eq :
forall b1 b2 ofs (Hrenaming: f b1 = Some b2)
(Hperm: Mem.perm mc b1 ofs Cur Readable),
memval_obs_eq f (Maps.ZMap.get ofs mc.(Mem.mem_contents)#b1)
(Maps.ZMap.get ofs mf.(Mem.mem_contents)#b2)}.
(** Renaming between memories *)
Record mem_obs_eq (f : memren) (mc mf : mem) :=
{ weak_obs_eq : weak_mem_obs_eq f mc mf;
strong_obs_eq : strong_mem_obs_eq f mc mf }.
Proof with eauto with renamings id_renamings val_renamings.
intros.
constructor; constructor;
eauto with id_renamings; unfold id_ren; intros;
repeat match goal with
| [H: context[valid_block_dec ?M ?B] |- _] =>
destruct (valid_block_dec M B); simpl in *
| [H: _ = Some _ |- _] => inv H; clear H
end; auto.
rewrite setMaxPerm_Cur;
apply po_refl.
rewrite setMaxPerm_Cur; auto.
destruct (ZMap.get ofs (Mem.mem_contents m) # b2) eqn:Hget;
constructor.
destruct v0; constructor.
specialize (H _ v _ _ Hget).
simpl in H.
(*this gives an anomaly: erewrite Coqlib2.if_true with (E:= {Mem.valid_block m b} + {~ Mem.valid_block m b}). *)
destruct (valid_block_dec m b); simpl; tauto.
Qed.
Proof with eauto with renamings id_renamings val_renamings.
intros.
constructor; constructor;
eauto with id_renamings; unfold id_ren; intros;
repeat match goal with
| [H: context[valid_block_dec ?M ?B] |- _] =>
destruct (valid_block_dec M B); simpl in *
| [H: _ = Some _ |- _] => inv H; clear H
end; auto.
now apply po_refl.
destruct (ZMap.get ofs (Mem.mem_contents m) # b2) eqn:Hget;
constructor.
destruct v0; constructor.
specialize (H _ v _ _ Hget).
simpl in H.
destruct (valid_block_dec m b); simpl; tauto.
Qed.
Transparent Mem.load.
Opaque Mem.load.
Transparent Mem.loadbytes.
Opaque Mem.loadbytes.
(** ** Lemmas about [Mem.store] and [mem_obs_eq]*)
(** Storing related values on related memories results in related memories*)
Transparent Mem.store.
Opaque Mem.store.
Transparent Mem.storebytes.
Opaque Mem.storebytes.
Transparent Mem.free.
Opaque Mem.free.
Proof with eauto with val_renamings.
intros.
destruct v1, v1'; inversion Hval_obs;
inversion Hval_obs'; subst; simpl; eauto with val_renamings;
unfold Val.cmpu,Val.of_optbool, Val.cmpu_bool, Vtrue, Vfalse...
- destruct (Int.cmpu comp i0 i2)...
- assert (Int.eq i0 Int.zero &&
(Mem.valid_pointer m b1 (Ptrofs.unsigned ofs)
|| Mem.valid_pointer m b1 (Ptrofs.unsigned ofs - 1))
= Int.eq i0 Int.zero &&
(Mem.valid_pointer m' b2 (Ptrofs.unsigned ofs)
|| Mem.valid_pointer m' b2 (Ptrofs.unsigned ofs - 1))).
{ destruct (Int.eq i0 Int.zero); simpl; try reflexivity.
erewrite valid_pointer_ren; eauto.
erewrite valid_pointer_ren with (ofs := (Ptrofs.unsigned ofs - 1)%Z);
eauto.
}
rewrite H.
repeat match goal with
| [|- context[match ?Expr with _ => _ end]] =>
destruct Expr eqn:?
end...
- assert (Int.eq i1 Int.zero &&
(Mem.valid_pointer m b (Ptrofs.unsigned i0)
|| Mem.valid_pointer m b (Ptrofs.unsigned i0 - 1))
= Int.eq i1 Int.zero &&
(Mem.valid_pointer m' b0 (Ptrofs.unsigned i0)
|| Mem.valid_pointer m' b0 (Ptrofs.unsigned i0 - 1))).
{ destruct (Int.eq i1 Int.zero); simpl; try reflexivity.
erewrite valid_pointer_ren; eauto.
erewrite valid_pointer_ren with (ofs := (Ptrofs.unsigned i0 - 1)%Z);
eauto.
}
rewrite H.
repeat match goal with
| [|- context[match ?Expr with _ => _ end]] =>
destruct Expr eqn:?
end...
- assert (Hequiv: (eq_block b b3) <-> (eq_block b0 b4)).
{ split.
- intros Heq.
destruct (eq_block b b3); subst.
+ rewrite H4 in H0; inversion H0; subst.
destruct (eq_block b0 b0); auto.
+ by exfalso.
- intros Heq.
destruct (eq_block b b3); subst.
+ rewrite H4 in H0; inversion H0; subst.
destruct (eq_block b0 b0); auto.
+ destruct (eq_block b0 b4); subst; auto.
assert (Hinjective := injective (weak_obs_eq Hmem_obs_eq)).
specialize (Hinjective _ _ _ H4 H0); subst.
by exfalso.
}
destruct (eq_block b b3) eqn:Hb;
destruct (eq_block b0 b4) eqn:Hb0; simpl in *; subst;
destruct Hequiv; try (by exfalso; eauto).
assert (Hif: (Mem.valid_pointer m b3 (Ptrofs.unsigned i0)
|| Mem.valid_pointer m b3 (Ptrofs.unsigned i0 - 1))
&&
(Mem.valid_pointer m b3 (Ptrofs.unsigned ofs0)
|| Mem.valid_pointer m b3 (Ptrofs.unsigned ofs0 - 1))
=
(Mem.valid_pointer m' b4 (Ptrofs.unsigned i0)
|| Mem.valid_pointer m' b4 (Ptrofs.unsigned i0 - 1))
&&
(Mem.valid_pointer m' b4 (Ptrofs.unsigned ofs0)
|| Mem.valid_pointer m' b4 (Ptrofs.unsigned ofs0 - 1))).
{ erewrite valid_pointer_ren; eauto.
erewrite valid_pointer_ren with
(m := m) (b1:=b3) (ofs := (Ptrofs.unsigned i0 - 1)%Z); eauto.
erewrite valid_pointer_ren with
(m := m) (b1:=b3) (ofs := Ptrofs.unsigned ofs0); eauto.
erewrite valid_pointer_ren with
(m := m) (b1:=b3) (ofs := (Ptrofs.unsigned ofs0 - 1)%Z); eauto.
}
rewrite Hif.
repeat match goal with
| [|- context[match ?Expr with _ => _ end]] =>
destruct Expr eqn:?
end...
erewrite valid_pointer_ren; eauto.
erewrite valid_pointer_ren with (b1 := b3); eauto.
repeat match goal with
| [|- context[match ?Expr with _ => _ end]] =>
destruct Expr eqn:?
end...
Qed.
Hint Resolve val_obs_cmpu : val_renamings.
Proof with eauto with val_renamings.
intros.
destruct v1, v1'; inversion Hval_obs;
inversion Hval_obs'; subst; simpl; eauto with val_renamings;
unfold Val.cmpu,Val.of_optbool, Val.cmpu_bool, Vtrue, Vfalse...
Qed.
Hint Resolve val_obs_cmplu : val_renamings.

Lemma mem_obs_eq_of_weak_strong:
forall m m' f pmap1 pmap1' pmap2 pmap2'
(Hlt1: permMapLt pmap1 (getMaxPerm m))
(Hlt2: permMapLt pmap2 (getMaxPerm m'))
(Hlt1': permMapLt pmap1' (getMaxPerm m))
(Hlt2': permMapLt pmap2' (getMaxPerm m'))
(Hstrong_obs: strong_mem_obs_eq f (restrPermMap Hlt1) (restrPermMap Hlt2))
(Hweak: weak_mem_obs_eq f (restrPermMap Hlt1') (restrPermMap Hlt2')),
mem_obs_eq f (restrPermMap Hlt1) (restrPermMap Hlt2).