(*FreshS/T: fresh blocks in src/tgt language*)
Definition sm_add_intern (mu: SM_Injection) j FreshS FreshT : SM_Injection :=
  Build_SM_Injection (fun b => locBlocksSrc mu b || FreshS b)
                     (fun b => locBlocksTgt mu b || FreshT b)
                     (pubBlocksSrc mu) (pubBlocksTgt mu)
                     (join (local_of mu) (fun b => match extern_of mu b with
                                             None => j b | Some _ => None end))
                     (extBlocksSrc mu) (extBlocksTgt mu)
                     (frgnBlocksSrc mu) (frgnBlocksTgt mu) (extern_of mu).

Lemma Match_AfterExternal: forall mu st1 st2 m1 e vals1 m2 ef_sig vals2 e' ef_sig' (MemInjMu : Mem.inject (as_inj mu) m1 m2) (MatchMu : Match_cores st1 mu st1 m1 st2 m2) (AtExtSrc : at_external cmin_eff_sem st1 = Some (e, ef_sig, vals1)) (AtExtTgt : at_external cminsel_eff_sem st2 = Some (e', ef_sig', vals2)) (ValInjMu : Forall2 (val_inject (restrict (as_inj mu) (vis mu))) vals1 vals2) (pubSrc' : Values.block -> bool) (pubSrcHyp : pubSrc' = (fun b : Values.block => locBlocksSrc mu b && REACH m1 (exportedSrc mu vals1) b)) (pubTgt' : Values.block -> bool) (pubTgtHyp : pubTgt' = (fun b : Values.block => locBlocksTgt mu b && REACH m2 (exportedTgt mu vals2) b)) nu (NuHyp : nu = replace_locals mu pubSrc' pubTgt') nu' ret1 m1' ret2 m2' (INC : extern_incr nu nu') (SEP : sm_inject_separated nu nu' m1 m2) (WDnu' : SM_wd nu') (SMvalNu' : sm_valid nu' m1' m2') (MemInjNu' : Mem.inject (as_inj nu') m1' m2') (RValInjNu' : val_inject (as_inj nu') ret1 ret2) (FwdSrc : mem_forward m1 m1') (FwdTgt : mem_forward m2 m2') (frgnSrc' : Values.block -> bool) (frgnSrcHyp : frgnSrc' = (fun b : Values.block => DomSrc nu' b && (negb (locBlocksSrc nu' b) && REACH m1' (exportedSrc nu' (ret1 :: nil)) b))) (frgnTgt' : Values.block -> bool) (frgnTgtHyp : frgnTgt' = (fun b : Values.block => DomTgt nu' b && (negb (locBlocksTgt nu' b) && REACH m2' (exportedTgt nu' (ret2 :: nil)) b))) mu' (Mu'Hyp : mu' = replace_externs nu' frgnSrc' frgnTgt') (UnchPrivSrc : Mem.unchanged_on (fun (b : Values.block) (_ : Z) => locBlocksSrc nu b = true /\ pubBlocksSrc nu b = false) m1 m1') (UnchLOOR : Mem.unchanged_on (local_out_of_reach nu m1) m2 m2'), exists (st1' : CMin_core) (st2' : CMinSel_core), after_external cmin_eff_sem (Some ret1) st1 = Some st1' /\ after_external cminsel_eff_sem (Some ret2) st2 = Some st2' /\ Match_cores st1' mu' st1' m1' st2' m2'.