(* A minimal preservation property we sometimes require.*)
Definition mem_forward (m1 m2:mem) :=
(forall b, Mem.valid_block m1 b ->
Mem.valid_block m2 b /\
forall ofs p, Mem.perm m2 b ofs Max p -> Mem.perm m1 b ofs Max p).

(* Specifications: *)
Lemma mem_forward_refl: forall m, mem_forward m m.
Lemma forward_unchanged_trans: forall P m1 m2 m3,
Mem.unchanged_on P m1 m2 -> Mem.unchanged_on P m2 m3 ->
mem_forward m1 m2 -> mem_forward m2 m3 ->
mem_forward m1 m3 /\ Mem.unchanged_on P m1 m3.
Lemma matchOptE: forall {A} (a:option A) (P: A -> Prop),
match a with Some b => P b | None => False end ->
exists b, a = Some b /\ P b.
Lemma compose_meminjD_Some: forall j jj b b2 ofs2,
(compose_meminj j jj) b = Some(b2,ofs2) ->
exists b1, exists ofs1, exists ofs,
j b = Some(b1,ofs1) /\ jj b1 = Some(b2,ofs) /\ ofs2=ofs1+ofs.
Lemma compose_meminj_inject_incr: forall j12 j12' j23 j23'
(InjIncr12: inject_incr j12 j12') (InjIncr23: inject_incr j23 j23'),
inject_incr (compose_meminj j12 j23) (compose_meminj j12' j23').
Lemma compose_meminj_inject_separated: forall j12 j12' j23 j23' m1 m2 m3
(InjSep12 : inject_separated j12 j12' m1 m2)
(InjSep23 : inject_separated j23 j23' m2 m3)
(InjIncr12: inject_incr j12 j12') (InjIncr23: inject_incr j23 j23')
(BV12: forall b1 b2 ofs, j12 b1 = Some (b2,ofs) -> Mem.valid_block m1 b1 /\ Mem.valid_block m2 b2)
(BV23: forall b1 b2 ofs, j23 b1 = Some (b2,ofs) -> Mem.valid_block m2 b1 /\ Mem.valid_block m3 b2),
inject_separated (compose_meminj j12 j23) (compose_meminj j12' j23') m1 m3.
Lemma compose_meminj_inject_separated': forall j12 j12' j23 j23' m1 m2 m3
(InjSep12 : inject_separated j12 j12' m1 m2)
(InjSep23 : inject_separated j23 j23' m2 m3)
(InjIncr12: inject_incr j12 j12') (InjIncr23: inject_incr j23 j23')
(MInj12: Mem.inject j12 m1 m2)
(MInj23: Mem.inject j23 m2 m3),
inject_separated (compose_meminj j12 j23) (compose_meminj j12' j23') m1 m3.
Lemma forall_lessdef_refl: forall vals,  Forall2 Val.lessdef vals vals.
Lemma valinject_hastype:  forall j v v'
(V: (val_inject j) v v') T,
Val.has_type v' T -> Val.has_type v T.
Lemma mem_forward_refl: forall m, mem_forward m m.
Lemma forward_unchanged_trans: forall P m1 m2 m3,
Mem.unchanged_on P m1 m2 -> Mem.unchanged_on P m2 m3 ->
mem_forward m1 m2 -> mem_forward m2 m3 ->
mem_forward m1 m3 /\ Mem.unchanged_on P m1 m3.
Lemma matchOptE: forall {A} (a:option A) (P: A -> Prop),
match a with Some b => P b | None => False end ->
exists b, a = Some b /\ P b.
Lemma compose_meminjD_Some: forall j jj b b2 ofs2,
(compose_meminj j jj) b = Some(b2,ofs2) ->
exists b1, exists ofs1, exists ofs,
j b = Some(b1,ofs1) /\ jj b1 = Some(b2,ofs) /\ ofs2=ofs1+ofs.
Lemma compose_meminj_inject_incr: forall j12 j12' j23 j23'
(InjIncr12: inject_incr j12 j12') (InjIncr23: inject_incr j23 j23'),
inject_incr (compose_meminj j12 j23) (compose_meminj j12' j23').
Lemma compose_meminj_inject_separated: forall j12 j12' j23 j23' m1 m2 m3
(InjSep12 : inject_separated j12 j12' m1 m2)
(InjSep23 : inject_separated j23 j23' m2 m3)
(InjIncr12: inject_incr j12 j12') (InjIncr23: inject_incr j23 j23')
(BV12: forall b1 b2 ofs, j12 b1 = Some (b2,ofs) -> Mem.valid_block m1 b1 /\ Mem.valid_block m2 b2)
(BV23: forall b1 b2 ofs, j23 b1 = Some (b2,ofs) -> Mem.valid_block m2 b1 /\ Mem.valid_block m3 b2),
inject_separated (compose_meminj j12 j23) (compose_meminj j12' j23') m1 m3.
Lemma compose_meminj_inject_separated': forall j12 j12' j23 j23' m1 m2 m3
(InjSep12 : inject_separated j12 j12' m1 m2)
(InjSep23 : inject_separated j23 j23' m2 m3)
(InjIncr12: inject_incr j12 j12') (InjIncr23: inject_incr j23 j23')
(MInj12: Mem.inject j12 m1 m2)
(MInj23: Mem.inject j23 m2 m3),
inject_separated (compose_meminj j12 j23) (compose_meminj j12' j23') m1 m3.
Lemma forall_lessdef_refl: forall vals,  Forall2 Val.lessdef vals vals.
Lemma valinject_hastype:  forall j v v'
(V: (val_inject j) v v') T,
Val.has_type v' T -> Val.has_type v T.