Definition AccessMap_IE_Property  j12 j12' m1 m1' m2 m3'
(AM:ZMap.t (Z -> perm_kind -> option permission)):Prop :=
forall b2,
(Mem.valid_block m2 b2 -> forall k ofs2,
match source j12 m1 b2 ofs2 with
Some(b1,ofs1) =>  PMap.get b2 AM ofs2 k =
PMap.get b1 m1'.(Mem.mem_access) ofs1 k
| None => PMap.get b2 AM ofs2 k =
PMap.get b2 m2.(Mem.mem_access) ofs2 k
end)
/\ (~ Mem.valid_block m2 b2 -> forall k ofs2,
match source j12' m1' b2 ofs2 with
Some(b1,ofs1) => PMap.get b2 AM ofs2 k =
PMap.get b1 m1'.(Mem.mem_access) ofs1 k
| None => PMap.get b2 AM ofs2 k =
PMap.get b2 m3'.(Mem.mem_access) ofs2 k
end).
Definition Content_IE_Property j12 (m1 m1' m2 m3':Mem.mem)
(CM:ZMap.t (ZMap.t memval)):=
forall b2,
(Mem.valid_block m2 b2 -> forall ofs2,
match source j12 m1 b2 ofs2 with
Some(b1,ofs1) => ZMap.get ofs2 (PMap.get b2 CM) =
ZMap.get ofs2 (PMap.get b2 m3'.(Mem.mem_contents))
| None => ZMap.get ofs2 (PMap.get b2 CM) =
ZMap.get ofs2 (PMap.get b2 m2.(Mem.mem_contents))
end)
/\ (~ Mem.valid_block m2 b2 -> forall (HM3': Mem.valid_block m3' b2) ofs2,
ZMap.get ofs2 (PMap.get b2 CM) =
ZMap.get ofs2 (PMap.get b2 m3'.(Mem.mem_contents)))
/\ fst CM !! b2 = Undef.
Definition AccessMap_IE_FUN (j12 j12':meminj) (m1 m1' m2 m3':Mem.mem) (b2:block):
Z -> perm_kind -> option permission :=
if plt b2 (Mem.nextblock m2)
then (fun ofs2 k =>
match source j12 m1 b2 ofs2 with
Some(b1,ofs1) => PMap.get b1 m1'.(Mem.mem_access) ofs1 k
| None => PMap.get b2 m2.(Mem.mem_access) ofs2 k
end)
else (fun ofs2 k =>
match source j12' m1' b2 ofs2 with
Some(b1,ofs1) => PMap.get b1 m1'.(Mem.mem_access) ofs1 k
| None => PMap.get b2 m3'.(Mem.mem_access) ofs2 k
end).
Definition ContentMap_IE_ValidBlock_FUN (j12:meminj) m1 m2 m3'
b2 ofs2: memval :=
match source j12 m1 b2 ofs2 with
Some(b1,ofs1) => ZMap.get ofs2 (PMap.get b2 m3'.(Mem.mem_contents))
| None => ZMap.get ofs2 (PMap.get b2 m2.(Mem.mem_contents))
end.
Definition ContentMap_IE_InvalidBlock_FUN m3' b2 ofs2: memval :=
ZMap.get ofs2 (PMap.get b2 m3'.(Mem.mem_contents)).
Definition ContentMap_IE_Block_FUN j12 m1 m2 m3' b ofs : memval:=
if plt b (Mem.nextblock m2)
then ContentMap_IE_ValidBlock_FUN j12 m1 m2 m3' b ofs
else ContentMap_IE_InvalidBlock_FUN m3' b ofs.
Definition ContentsMap_IE_FUN (j12:meminj) (m1 m2 m3':Mem.mem) (b:block):
ZMap.t memval.
destruct (plt b (Mem.nextblock m3')).
apply(CM_block_IE_existsT j12 m1 m2 m3' b).
apply (ZMap.init Undef).
Defined.
Definition mkIE (j j': meminj) (m1 m1' m2 m3':Mem.mem)
(VB': forall (b1 b3 : block) (delta : Z),
j' b1 = Some (b3, delta) ->
(Mem.valid_block m1' b1 /\ Mem.valid_block m3' b3))
(VB: (Mem.nextblock m2 <= Mem.nextblock m3')%positive)
: Mem.mem'.
destruct (mkAccessMap_IE_existsT j j' m1 m1' m2 m3' VB' VB) as [AM [ADefault PAM]].
destruct (ContentsMap_IE_existsT j m1 m2 m3') as [CM [CDefault PCM]].
eapply Mem.mkmem with (nextblock:=m3'.(Mem.nextblock))
(mem_access:=AM)
(mem_contents:=CM).
(* apply (mkContentsMap_IE_exists j m1 m1' m2 m3').*)
(*  apply m3'.*)
(*access_max*)
intros. rewrite PAM. unfold AccessMap_IE_FUN.
destruct (plt b (Mem.nextblock m2)).
(*valid_block m2 b*)
remember (source j m1 b ofs) as src.
destruct src.
destruct p0. apply m1'.
apply m2.
(*invalid_block m2 b*)
remember (source j' m1' b ofs) as src.
destruct src.
destruct p. apply m1'.
apply m3'.
(*nextblock_noaccess*)
intros. rewrite PAM.
unfold AccessMap_IE_FUN.
destruct (plt b (Mem.nextblock m2)).
exfalso. apply H; clear - VB p. xomega.
remember (source j' m1' b ofs) as src.
destruct src.
destruct p.
exfalso. apply H. clear - Heqsrc VB'.
apply source_SomeE in Heqsrc.
destruct Heqsrc as [b1 [delta [ofs1
[PBO [Bounds [J1 [P1 Off2]]]]]]]; subst.
apply (VB' _ _ _ J1).
apply m3'. apply H.
(*contents_default*)
intros. rewrite PCM.
unfold ContentsMap_IE_FUN.
destruct (plt b (Mem.nextblock m3')).
remember (CM_block_IE_existsT j m1 m2 m3' b).
destruct s. apply a.
reflexivity.
Defined.

Lemma interpolate_IE: forall m1 m1' m2 j (Minj12 : Mem.inject j m1 m2)
(Fwd1: mem_forward m1 m1') j' (InjInc: inject_incr j j')
(Sep12 : inject_separated j j' m1 m2)
(UnchLUj: Mem.unchanged_on (loc_unmapped j) m1 m1')
m3 m3' (Ext23 : Mem.extends m2 m3)
(Fwd3: mem_forward m3 m3')
(UnchLOORj1_3: Mem.unchanged_on (loc_out_of_reach j m1) m3 m3')
(Inj13' : Mem.inject j' m1' m3')
(UnchLOOB23_3': Mem.unchanged_on
(loc_out_of_bounds m2) m3 m3'),
exists m2',  mem_forward m2 m2' /\ Mem.extends m2' m3' /\
Mem.inject j' m1' m2' /\
Mem.unchanged_on (loc_out_of_reach j m1) m2 m2' .