(* 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 mem_forward_trans: forall m1 m2 m3, mem_forward m1 m2 -> mem_forward m2 m3 -> mem_forward m1 m3.
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_None: forall j jj b, (compose_meminj j jj) b = None -> j b = None \/ (exists b', exists ofs, j b = Some(b',ofs) /\ jj b' = None).
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 lessdef_hastype: forall v v' (V:Val.lessdef v v') T, Val.has_type v' T -> Val.has_type v T.
Lemma forall_lessdef_hastype: forall vals vals' (V:Forall2 Val.lessdef vals vals') Ts (HTs: Forall2 Val.has_type vals' Ts), Forall2 Val.has_type vals Ts.
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 forall_valinject_hastype: forall j vals vals' (V: Forall2 (val_inject j) vals vals') Ts (HTs: Forall2 Val.has_type vals' Ts), Forall2 Val.has_type vals Ts.
Lemma mem_forward_refl: forall m, mem_forward m m.
Lemma mem_forward_trans: forall m1 m2 m3, mem_forward m1 m2 -> mem_forward m2 m3 -> mem_forward m1 m3.
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_None: forall j jj b, (compose_meminj j jj) b = None -> j b = None \/ (exists b', exists ofs, j b = Some(b',ofs) /\ jj b' = None).
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 lessdef_hastype: forall v v' (V:Val.lessdef v v') T, Val.has_type v' T -> Val.has_type v T.
Lemma forall_lessdef_hastype: forall vals vals' (V:Forall2 Val.lessdef vals vals') Ts (HTs: Forall2 Val.has_type vals' Ts), Forall2 Val.has_type vals Ts.
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 forall_valinject_hastype: forall j vals vals' (V: Forall2 (val_inject j) vals vals') Ts (HTs: Forall2 Val.has_type vals' Ts), Forall2 Val.has_type vals Ts.