(***********************************************************************)
Goal forall mu (WD: SM_wd mu) m1 m2 m2'
(U: Mem.unchanged_on (local_out_of_reach mu m1) m2 m2'),
Mem.unchanged_on (fun b ofs => pubBlocksTgt mu b = true /\
loc_out_of_reach (pub_of mu) m1 b ofs) m2 m2'.
Goal forall mu (WD: SM_wd mu) m1 m2 m2'
(U: Mem.unchanged_on (local_out_of_reach mu m1) m2 m2'),
Mem.unchanged_on (fun b ofs => locBlocksTgt mu b = true /\
pubBlocksTgt mu b = false) m2 m2'.
intros.
eapply mem_unchanged_on_sub; try eassumption.
intros. unfold local_out_of_reach. destruct H.
split; trivial. intros.
remember (pubBlocksSrc mu b0) as d.
destruct d; try (right; reflexivity).
apply eq_sym in Heqd.
destruct (pubSrc _ WD _ Heqd) as [b2 [dd [PUB TGT]]].
apply pub_in_local in PUB. rewrite PUB in H1. inv H1.
rewrite TGT in H0. discriminate.
Qed.
Goal forall mu m1 m2 m2' (WD:SM_wd mu)
(U1: Mem.unchanged_on (fun b ofs => locBlocksTgt mu b = true /\
pubBlocksTgt mu b = false) m2 m2')
(U2: Mem.unchanged_on (fun b ofs => pubBlocksTgt mu b = true /\
loc_out_of_reach (pub_of mu) m1 b ofs) m2 m2'),
Mem.unchanged_on (local_out_of_reach mu m1) m2 m2'.
intros.
destruct U1 as [P1 C1]. destruct U2 as [P2 C2].
split; intros.
clear C1 C2.
specialize (P1 b ofs k p). specialize (P2 b ofs k p).
remember (locBlocksTgt mu b) as d.
destruct d; apply eq_sym in Heqd; simpl in *.
remember (pubBlocksTgt mu b) as q.
destruct q; apply eq_sym in Heqq; simpl in *.
clear P1.
apply P2; trivial. split; trivial.
intros b0; intros.
destruct H. destruct (H2 b0 delta).
apply pub_in_local; trivial.
assumption.
unfold pub_of in H1. destruct mu. simpl in *.  rewrite H3 in H1.  discriminate.
apply P1; trivial. split; trivial.
clear P1.
remember (pubBlocksTgt mu b) as q.
destruct q; apply eq_sym in Heqq; simpl in *.
assert (locBlocksTgt mu b = true). eapply (pubBlocksLocalTgt _ WD). eassumption.
rewrite H1 in Heqd. discriminate.
destruct H. rewrite H in Heqd. discriminate.
destruct H.
clear P1 P2.
specialize (C1 b ofs). specialize (C2 b ofs).
rewrite H in *.
remember (pubBlocksTgt mu b) as d.
destruct d; apply eq_sym in Heqd.
clear C1. apply C2; trivial; clear C2.
split; trivial. intros b1; intros.
destruct (pub_locBlocks _ WD _ _ _ H2).
apply pub_in_local in H2.
destruct (H1 _ _ H2). assumption. rewrite H5 in *. inv H3.
clear C2. apply C1; eauto.
Qed.

(* Specifications: *)
Lemma eff_atexternal_check:
forall {F1 V1 C1 F2 V2 C2:Type} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2)
mu (WDmu: SM_wd mu)
(GenvsDomEq: genvs_domain_eq ge1 ge2)
m1 m2 (MemInjMu: Mem.inject (as_inj mu) m1 m2)
vals1 vals2 (ValInjMu: Forall2 (val_inject (as_inj mu)) vals1 vals2)
(MatchGenv: meminj_preserves_globals ge1 (extern_of mu) /\
(forall b, isGlobalBlock ge1 b = true -> frgnBlocksSrc mu b = true)),
(forall b, isGlobalBlock ge1 b = true -> REACH m1 (exportedSrc mu vals1) b = true) /\
(forall b, isGlobalBlock ge2 b = true -> REACH m2 (exportedTgt mu vals2) b = true).
Lemma eff_after_check1:
forall mu (WD: SM_wd mu) m1 m2 (SMValMu: sm_valid mu m1 m2)
(MemInjMu: Mem.inject (as_inj mu) m1 m2)
vals1 vals2 (ValInjMu: Forall2 (val_inject (as_inj mu)) vals1 vals2)
pubSrc' (pubSrcHyp: pubSrc' = fun b => andb (locBlocksSrc mu b)
(REACH m1 (exportedSrc mu vals1) b))
pubTgt' (pubTgtHyp: pubTgt' = fun b => andb (locBlocksTgt mu b)
(REACH m2 (exportedTgt mu vals2) b))
nu (NuHyp: nu = replace_locals mu pubSrc' pubTgt'),
SM_wd nu /\ sm_valid nu m1 m2 /\
Mem.inject (as_inj nu) m1 m2 /\
Forall2 (val_inject (as_inj nu)) vals1 vals2.