Definition AccessMap_EI_Property (j:meminj) (m1 m1' m2 : mem)
(AM:ZMap.t (Z -> perm_kind -> option permission)):Prop :=
forall b2,
(Mem.valid_block m2 b2 -> forall k ofs2,
match j b2 with
None => PMap.get b2 AM ofs2 k  =
PMap.get b2 m2.(Mem.mem_access) ofs2 k
| Some (b3,d3) =>
(Mem.perm m1 b2 ofs2 Max Nonempty ->
PMap.get b2 AM ofs2 k = PMap.get b2 m1'.(Mem.mem_access) ofs2 k)
/\ (~Mem.perm m1 b2 ofs2 Max Nonempty ->
PMap.get b2 AM ofs2 k  = PMap.get b2 m2.(Mem.mem_access) ofs2 k)
end)
/\ (~ Mem.valid_block m2 b2 -> forall k ofs2,
(Mem.perm m1' b2 ofs2 Max Nonempty ->
PMap.get b2 AM ofs2 k = PMap.get b2 m1'.(Mem.mem_access) ofs2 k)
/\ (~Mem.perm m1' b2 ofs2 Max Nonempty -> PMap.get b2 AM ofs2 k = None)).
Definition Content_EI_Property (j:meminj) (m1 m1' m2:Mem.mem)
(CM:ZMap.t (ZMap.t memval)):=
forall b2,
(Mem.valid_block m2 b2 -> forall ofs2,
match j b2 with
None =>  ZMap.get ofs2 (PMap.get b2 CM) =
ZMap.get ofs2 (PMap.get b2 m2.(Mem.mem_contents))
| Some (b3,delta3) =>
(Mem.perm m1 b2 ofs2 Max Nonempty ->
ZMap.get ofs2 (PMap.get b2 CM) =
ZMap.get ofs2 (PMap.get b2 m1'.(Mem.mem_contents)))
/\ (~Mem.perm m1 b2 ofs2 Max Nonempty ->
ZMap.get ofs2 (PMap.get b2 CM) =
ZMap.get ofs2 (PMap.get b2 m2.(Mem.mem_contents)))
end)
/\ (~ Mem.valid_block m2 b2 -> forall (HM1': Mem.valid_block m1' b2) ofs2,
(Mem.perm m1' b2 ofs2 Cur Readable ->
ZMap.get ofs2 (PMap.get b2 CM) =
ZMap.get ofs2 (PMap.get b2 m1'.(Mem.mem_contents)))
/\ (~Mem.perm m1' b2 ofs2 Cur Readable ->
ZMap.get ofs2 (PMap.get b2 CM) =Undef))
/\ fst CM !! b2 = Undef.
Definition AccessMap_EI_FUN (j:meminj) (m1 m1' m2 : mem) (b2:block):
Z -> perm_kind -> option permission :=
if plt b2 (Mem.nextblock m2)
then (fun ofs2 k =>
match j b2 with
None => PMap.get b2 m2.(Mem.mem_access) ofs2 k
| Some (b3,d3) =>
if Mem.perm_dec m1 b2 ofs2 Max Nonempty
then PMap.get b2 m1'.(Mem.mem_access) ofs2 k
else PMap.get b2 m2.(Mem.mem_access) ofs2 k
end)
else (fun ofs2 k =>
if Mem.perm_dec m1' b2 ofs2 Max Nonempty
then PMap.get b2 m1'.(Mem.mem_access) ofs2 k
else None).
Definition ContentMap_EI_ValidBlock_FUN (j:meminj) m1 m1' m2 b2 ofs2: memval :=
match j b2 with
None => ZMap.get ofs2 (PMap.get b2 m2.(Mem.mem_contents))
| Some (b3,delta3) =>
if Mem.perm_dec m1 b2 ofs2 Max Nonempty
then ZMap.get ofs2 (PMap.get b2 m1'.(Mem.mem_contents))
else ZMap.get ofs2 (PMap.get b2 m2.(Mem.mem_contents))
end.
Definition ContentMap_EI_InvalidBlock_FUN m1' b2 ofs2: memval :=
if Mem.perm_dec m1' b2 ofs2 Cur Readable
then ZMap.get ofs2 (PMap.get b2 m1'.(Mem.mem_contents))
else Undef.
Definition ContentMap_EI_Block_FUN j m1 m1' m2 b ofs : memval:=
if plt b (Mem.nextblock m2)
then ContentMap_EI_ValidBlock_FUN j m1 m1' m2 b ofs
else ContentMap_EI_InvalidBlock_FUN m1' b ofs.
Definition ContentsMap_EI_FUN (j:meminj) (m1 m1' m2:Mem.mem) (b:block):
ZMap.t memval.
destruct (plt b (Mem.nextblock m1')).
apply(CM_block_EI_existsT j m1 m1' m2 b).
apply (ZMap.init Undef).
Defined.
Definition mkEI (j j': meminj) (m1 m2 m1':mem)
(Ext12: Mem.extends m1 m2)
(Fwd1: mem_forward m1 m1') m3
(Inj23: Mem.inject j m2 m3)
m3' (Fwd3: mem_forward m3 m3')
(Inj13': Mem.inject j' m1' m3')
(UnchOn3: Mem.unchanged_on (loc_out_of_reach j m1) m3 m3')
(InjInc: inject_incr j j') (injSep: inject_separated j j' m1 m3)
(UnchOn1: Mem.unchanged_on (loc_unmapped j) m1 m1')
: Mem.mem'.
assert (VB: (Mem.nextblock m2 <= Mem.nextblock m1')%positive).
destruct Ext12. rewrite <- mext_next.
apply (forward_nextblock _ _ Fwd1).
destruct (mkAccessMap_EI_existsT j m1 m1' m2) as [AM [ADefault PAM]].
assumption.
destruct (ContentsMap_EI_existsT j m1 m1' m2) as [CM [CDefault PCM]].
eapply Mem.mkmem with (nextblock:=m1'.(Mem.nextblock))
(mem_access:=AM)
(mem_contents:=CM).
(*apply (mkContentsMap_EI_exists j m1 m1' m2).*)
(*  apply m1'.*)
(*access_max*)
intros. rewrite PAM. unfold AccessMap_EI_FUN.
destruct (plt b (Mem.nextblock m2)).
(*valid_block m2 b*)
destruct (j b).
destruct p0.
destruct (Mem.perm_dec m1 b ofs Max Nonempty).
apply m1'.
apply m2.
apply m2.
(*~ valid_block m2 b*)
destruct (Mem.perm_dec m1' b ofs Max Nonempty).
apply m1'.
reflexivity.
(*nextblock_noaccess*)
intros. rewrite PAM.
unfold AccessMap_EI_FUN.
destruct (plt b (Mem.nextblock m2)).
exfalso. apply H; clear - VB p. xomega.
destruct (Mem.perm_dec m1' b ofs Max Nonempty); trivial.
exfalso. apply H. apply (Mem.perm_valid_block _ _ _ _ _ p).
(*contents_default*)
intros. rewrite PCM.
unfold ContentsMap_EI_FUN.
destruct (plt b (Mem.nextblock m1')).
remember (CM_block_EI_existsT j m1 m1' m2 b).
destruct s. apply a.
reflexivity.
Defined.

Lemma interpolate_EI: forall (m1 m2 m1':mem)
(Ext12: Mem.extends m1 m2) (Fwd1: mem_forward m1 m1')
m3 j (Inj23: Mem.inject j m2 m3) m3'
(Fwd3: mem_forward m3 m3') j'
(Inj13': Mem.inject j' m1' m3')
(UnchOn3: Mem.unchanged_on (loc_out_of_reach j m1) m3 m3')
(InjInc: inject_incr j j')
(injSep: inject_separated j j' m1 m3)
(UnchOn1:  Mem.unchanged_on (loc_unmapped j) m1 m1'),
exists m2', mem_forward m2 m2' /\ Mem.extends m1' m2' /\
Mem.inject j' m2' m3' /\
Mem.unchanged_on (loc_out_of_bounds m1) m2 m2' /\
Mem.unchanged_on (loc_unmapped j) m2 m2'.