(*The join of all four components - useful for stating
  match_state conditions*)
Definition as_inj (mu: SM_Injection) : meminj :=
  join (extern_of mu) (local_of mu).

(* Specifications: *)
Lemma local_in_all: forall j (PR:SM_wd j), inject_incr (local_of j) (as_inj j).
Lemma pub_in_all: forall j (PR:SM_wd j), inject_incr (pub_of j) (as_inj j).
Lemma priv_in_all: forall j (PR:SM_wd j), inject_incr (priv_of j) (as_inj j).
Lemma extern_in_all: forall mu, inject_incr (extern_of mu) (as_inj mu).
Lemma foreign_in_all: forall mu, inject_incr (foreign_of mu) (as_inj mu).
Lemma unknown_in_all: forall mu, inject_incr (unknown_of mu) (as_inj mu).
Lemma shared_in_all: forall j (PR:SM_wd j), inject_incr (shared_of j) (as_inj j).
Lemma as_injD_None: forall mu b1, as_inj mu b1 = None -> extern_of mu b1 = None /\ local_of mu b1 = None.
Lemma local_ofD_None: forall mu b1, local_of mu b1 = None -> pub_of mu b1 = None /\ priv_of mu b1 = None.
Lemma extern_ofD_None: forall mu b1, extern_of mu b1 = None -> foreign_of mu b1 = None /\ unknown_of mu b1 = None.
Lemma disjoint_foreign_priv: forall mu (WD: SM_wd mu), disjoint (foreign_of mu) (priv_of mu).
Lemma disjoint_foreign_local: forall mu (WD: SM_wd mu), disjoint (foreign_of mu) (local_of mu).
Lemma disjoint_unknown_local: forall mu (WD: SM_wd mu), disjoint (unknown_of mu) (local_of mu).
Lemma disjoint_unknown_pub: forall mu (WD: SM_wd mu), disjoint (unknown_of mu) (pub_of mu).
Lemma disjoint_unknown_priv: forall mu (WD: SM_wd mu), disjoint (unknown_of mu) (priv_of mu).
Lemma disjoint_shared_priv: forall mu (WD: SM_wd mu), disjoint (shared_of mu) (priv_of mu).
Lemma disjoint_shared_unknown: forall mu (WD: SM_wd mu), disjoint (shared_of mu) (unknown_of mu).
Lemma as_inj_DomRng: forall mu b1 b2 d, as_inj mu b1 = Some(b2, d) -> SM_wd mu -> DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma local_locBlocks: forall mu (WD:SM_wd mu) b1 b2 z (L: local_of mu b1 = Some(b2,z)), locBlocksSrc mu b1 = true /\ locBlocksTgt mu b2 = true /\ extBlocksSrc mu b1 = false /\ extBlocksTgt mu b2 = false /\ frgnBlocksSrc mu b1 = false /\ frgnBlocksTgt mu b2 = false /\ DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma pub_locBlocks: forall mu (WD:SM_wd mu) b1 b2 z (L: pub_of mu b1 = Some(b2,z)), pubBlocksSrc mu b1 = true /\ pubBlocksTgt mu b2 = true /\ locBlocksSrc mu b1 = true /\ locBlocksTgt mu b2 = true /\ extBlocksSrc mu b1 = false /\ extBlocksTgt mu b2 = false /\ frgnBlocksSrc mu b1 = false /\ frgnBlocksTgt mu b2 = false /\ DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma priv_locBlocks: forall mu (WD:SM_wd mu) b1 b2 z (L: priv_of mu b1 = Some(b2,z)), pubBlocksSrc mu b1 = false /\ locBlocksSrc mu b1 = true /\ locBlocksTgt mu b2 = true /\ extBlocksSrc mu b1 = false /\ extBlocksTgt mu b2 = false /\ frgnBlocksSrc mu b1 = false /\ frgnBlocksTgt mu b2 = false /\ DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma extern_DomRng': forall mu (WD:SM_wd mu) b1 b2 d (L:extern_of mu b1 = Some(b2,d)), pubBlocksSrc mu b1 = false /\ pubBlocksTgt mu b2 = false /\ locBlocksSrc mu b1 = false /\ locBlocksTgt mu b2 = false /\ extBlocksSrc mu b1 = true /\ extBlocksTgt mu b2 = true /\ DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma foreign_DomRng: forall mu (WD:SM_wd mu) b1 b2 d (L:foreign_of mu b1 = Some(b2,d)), pubBlocksSrc mu b1 = false /\ pubBlocksTgt mu b2 = false /\ locBlocksSrc mu b1 = false /\ locBlocksTgt mu b2 = false /\ frgnBlocksSrc mu b1 = true /\ frgnBlocksTgt mu b2 = true /\ extBlocksSrc mu b1 = true /\ extBlocksTgt mu b2 = true /\ DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma unknown_DomRng: forall mu (WD:SM_wd mu) b1 b2 d (L: unknown_of mu b1 = Some(b2,d)), pubBlocksSrc mu b1 = false /\ pubBlocksTgt mu b2 = false /\ locBlocksSrc mu b1 = false /\ locBlocksTgt mu b2 = false /\ extBlocksSrc mu b1 = true /\ extBlocksTgt mu b2 = true /\ frgnBlocksSrc mu b1 = false /\ DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma local_in_all: forall j (PR:SM_wd j), inject_incr (local_of j) (as_inj j).
Lemma pub_in_all: forall j (PR:SM_wd j), inject_incr (pub_of j) (as_inj j).
Lemma priv_in_all: forall j (PR:SM_wd j), inject_incr (priv_of j) (as_inj j).
Lemma extern_in_all: forall mu, inject_incr (extern_of mu) (as_inj mu).
Lemma foreign_in_all: forall mu, inject_incr (foreign_of mu) (as_inj mu).
Lemma unknown_in_all: forall mu, inject_incr (unknown_of mu) (as_inj mu).
Lemma shared_in_all: forall j (PR:SM_wd j), inject_incr (shared_of j) (as_inj j).
Lemma as_injD_None: forall mu b1, as_inj mu b1 = None -> extern_of mu b1 = None /\ local_of mu b1 = None.
Lemma local_ofD_None: forall mu b1, local_of mu b1 = None -> pub_of mu b1 = None /\ priv_of mu b1 = None.
Lemma extern_ofD_None: forall mu b1, extern_of mu b1 = None -> foreign_of mu b1 = None /\ unknown_of mu b1 = None.
Lemma disjoint_foreign_priv: forall mu (WD: SM_wd mu), disjoint (foreign_of mu) (priv_of mu).
Lemma disjoint_foreign_local: forall mu (WD: SM_wd mu), disjoint (foreign_of mu) (local_of mu).
Lemma disjoint_unknown_local: forall mu (WD: SM_wd mu), disjoint (unknown_of mu) (local_of mu).
Lemma disjoint_unknown_pub: forall mu (WD: SM_wd mu), disjoint (unknown_of mu) (pub_of mu).
Lemma disjoint_unknown_priv: forall mu (WD: SM_wd mu), disjoint (unknown_of mu) (priv_of mu).
Lemma disjoint_shared_priv: forall mu (WD: SM_wd mu), disjoint (shared_of mu) (priv_of mu).
Lemma disjoint_shared_unknown: forall mu (WD: SM_wd mu), disjoint (shared_of mu) (unknown_of mu).
Lemma as_inj_DomRng: forall mu b1 b2 d, as_inj mu b1 = Some(b2, d) -> SM_wd mu -> DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma local_locBlocks: forall mu (WD:SM_wd mu) b1 b2 z (L: local_of mu b1 = Some(b2,z)), locBlocksSrc mu b1 = true /\ locBlocksTgt mu b2 = true /\ extBlocksSrc mu b1 = false /\ extBlocksTgt mu b2 = false /\ frgnBlocksSrc mu b1 = false /\ frgnBlocksTgt mu b2 = false /\ DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma pub_locBlocks: forall mu (WD:SM_wd mu) b1 b2 z (L: pub_of mu b1 = Some(b2,z)), pubBlocksSrc mu b1 = true /\ pubBlocksTgt mu b2 = true /\ locBlocksSrc mu b1 = true /\ locBlocksTgt mu b2 = true /\ extBlocksSrc mu b1 = false /\ extBlocksTgt mu b2 = false /\ frgnBlocksSrc mu b1 = false /\ frgnBlocksTgt mu b2 = false /\ DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma priv_locBlocks: forall mu (WD:SM_wd mu) b1 b2 z (L: priv_of mu b1 = Some(b2,z)), pubBlocksSrc mu b1 = false /\ locBlocksSrc mu b1 = true /\ locBlocksTgt mu b2 = true /\ extBlocksSrc mu b1 = false /\ extBlocksTgt mu b2 = false /\ frgnBlocksSrc mu b1 = false /\ frgnBlocksTgt mu b2 = false /\ DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma extern_DomRng': forall mu (WD:SM_wd mu) b1 b2 d (L:extern_of mu b1 = Some(b2,d)), pubBlocksSrc mu b1 = false /\ pubBlocksTgt mu b2 = false /\ locBlocksSrc mu b1 = false /\ locBlocksTgt mu b2 = false /\ extBlocksSrc mu b1 = true /\ extBlocksTgt mu b2 = true /\ DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma foreign_DomRng: forall mu (WD:SM_wd mu) b1 b2 d (L:foreign_of mu b1 = Some(b2,d)), pubBlocksSrc mu b1 = false /\ pubBlocksTgt mu b2 = false /\ locBlocksSrc mu b1 = false /\ locBlocksTgt mu b2 = false /\ frgnBlocksSrc mu b1 = true /\ frgnBlocksTgt mu b2 = true /\ extBlocksSrc mu b1 = true /\ extBlocksTgt mu b2 = true /\ DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma unknown_DomRng: forall mu (WD:SM_wd mu) b1 b2 d (L: unknown_of mu b1 = Some(b2,d)), pubBlocksSrc mu b1 = false /\ pubBlocksTgt mu b2 = false /\ locBlocksSrc mu b1 = false /\ locBlocksTgt mu b2 = false /\ extBlocksSrc mu b1 = true /\ extBlocksTgt mu b2 = true /\ frgnBlocksSrc mu b1 = false /\ DomSrc mu b1 = true /\ DomTgt mu b2 = true.