Definition compose_sm (mu1 mu2 : SM_Injection) : SM_Injection :=
 Build_SM_Injection
   (locBlocksSrc mu1) (locBlocksTgt mu2)
   (pubBlocksSrc mu1) (pubBlocksTgt mu2)
   (compose_meminj (local_of mu1) (local_of mu2))
   (extBlocksSrc mu1) (extBlocksTgt mu2)
   (frgnBlocksSrc mu1) (frgnBlocksTgt mu2)
   (compose_meminj (extern_of mu1) (extern_of mu2)).

(* Specifications: *)
Lemma compose_sm_valid: forall mu1 mu2 m1 m2 m2' m3 (SMV1: sm_valid mu1 m1 m2) (SMV2: sm_valid mu2 m2' m3), sm_valid (compose_sm mu1 mu2) m1 m3.
Lemma compose_sm_pub: forall mu12 mu23 (HypPub: forall b, pubBlocksTgt mu12 b = true -> pubBlocksSrc mu23 b = true) (WD1:SM_wd mu12), pub_of (compose_sm mu12 mu23) = compose_meminj (pub_of mu12) (pub_of mu23).
Lemma compose_sm_DomSrc: forall mu12 mu23, DomSrc (compose_sm mu12 mu23) = DomSrc mu12.
Lemma compose_sm_DomTgt: forall mu12 mu23, DomTgt (compose_sm mu12 mu23) = DomTgt mu23.
Lemma compose_sm_foreign: forall mu12 mu23 (HypFrg: forall b, frgnBlocksTgt mu12 b = true -> frgnBlocksSrc mu23 b = true) (WD1:SM_wd mu12), foreign_of (compose_sm mu12 mu23) = compose_meminj (foreign_of mu12) (foreign_of mu23).
Lemma compose_sm_priv: forall mu12 mu23, priv_of (compose_sm mu12 mu23) = compose_meminj (priv_of mu12) (local_of mu23).
Lemma compose_sm_unknown: forall mu12 mu23, unknown_of (compose_sm mu12 mu23) = compose_meminj (unknown_of mu12) (extern_of mu23).
Lemma compose_sm_local: forall mu12 mu23, local_of (compose_sm mu12 mu23) = compose_meminj (local_of mu12) (local_of mu23).
Lemma compose_sm_extern: forall mu12 mu23, extern_of (compose_sm mu12 mu23) = compose_meminj (extern_of mu12) (extern_of mu23).
Lemma compose_sm_shared: forall mu12 mu23 (HypPub: forall b, pubBlocksTgt mu12 b = true -> pubBlocksSrc mu23 b = true) (HypFrg: forall b, frgnBlocksTgt mu12 b = true -> frgnBlocksSrc mu23 b = true) (WD1:SM_wd mu12) (WD2:SM_wd mu23), shared_of (compose_sm mu12 mu23) = compose_meminj (shared_of mu12) (shared_of mu23).
Lemma compose_sm_wd: forall mu1 mu2 (WD1: SM_wd mu1) (WD2:SM_wd mu2) (HypPub: forall b, pubBlocksTgt mu1 b = true -> pubBlocksSrc mu2 b = true) (HypFrg: forall b, frgnBlocksTgt mu1 b = true -> frgnBlocksSrc mu2 b = true), SM_wd (compose_sm mu1 mu2).
Lemma compose_sm_as_inj: forall mu12 mu23 (WD1: SM_wd mu12) (WD2: SM_wd mu23) (SrcTgtLoc: locBlocksTgt mu12 = locBlocksSrc mu23) (SrcTgtExt: extBlocksTgt mu12 = extBlocksSrc mu23), as_inj (compose_sm mu12 mu23) = compose_meminj (as_inj mu12) (as_inj mu23).
Lemma compose_sm_intern_incr: forall mu12 mu12' mu23 mu23' (inc12: intern_incr mu12 mu12') (inc23: intern_incr mu23 mu23'), intern_incr (compose_sm mu12 mu23) (compose_sm mu12' mu23').
Lemma compose_sm_extern_incr: forall mu12 mu12' mu23 mu23' (inc12: extern_incr mu12 mu12') (inc23: extern_incr mu23 mu23') (FRG': forall b1 b2 d1, foreign_of mu12' b1 = Some(b2,d1) -> exists b3 d2, foreign_of mu23' b2 = Some(b3,d2)) (WD12': SM_wd mu12') (WD23': SM_wd mu23'), extern_incr (compose_sm mu12 mu23) (compose_sm mu12' mu23').
Lemma extern_incr_inject_incr: forall nu12 nu23 nu' (WDnu' : SM_wd nu') (EXT: extern_incr (compose_sm nu12 nu23) nu') (GlueInvNu: SM_wd nu12 /\ SM_wd nu23 /\ locBlocksTgt nu12 = locBlocksSrc nu23 /\ extBlocksTgt nu12 = extBlocksSrc nu23 /\ (forall b, pubBlocksTgt nu12 b = true -> pubBlocksSrc nu23 b = true) /\ (forall b, frgnBlocksTgt nu12 b = true -> frgnBlocksSrc nu23 b = true)), inject_incr (compose_meminj (as_inj nu12) (as_inj nu23)) (as_inj nu').
Lemma compose_sm_as_injD: forall mu1 mu2 b1 b3 d (I: as_inj (compose_sm mu1 mu2) b1 = Some (b3, d)) (WD1: SM_wd mu1) (WD2: SM_wd mu2), exists b2 d1 d2, as_inj mu1 b1 = Some(b2,d1) /\ as_inj mu2 b2 = Some(b3,d2) /\ d=d1+d2.
Lemma compose_sm_intern_separated: forall mu12 mu12' mu23 mu23' m1 m2 m3 (inc12: intern_incr mu12 mu12') (inc23: intern_incr mu23 mu23') (InjSep12 : sm_inject_separated mu12 mu12' m1 m2) (InjSep23 : sm_inject_separated mu23 mu23' m2 m3) (WD12: SM_wd mu12) (WD12': SM_wd mu12') (WD23: SM_wd mu23) (WD23': SM_wd mu23') (BlocksLoc: locBlocksTgt mu12 = locBlocksSrc mu23) (BlocksExt: extBlocksTgt mu12 = extBlocksSrc mu23), sm_inject_separated (compose_sm mu12 mu23) (compose_sm mu12' mu23') m1 m3.
Lemma vis_compose_sm: forall mu nu, vis (compose_sm mu nu) = vis mu.
Lemma restrict_compose: forall j k X, restrict (compose_meminj j k) X = compose_meminj (restrict j X) k.