Definition vis mu := fun b => locBlocksSrc mu b || frgnBlocksSrc mu b.
Definition visTgt mu := fun b => locBlocksTgt mu b || frgnBlocksTgt mu b.
Inductive reach (m:mem) (B:block -> Prop): list (block * Z) -> block -> Prop :=
reach_nil: forall b, B b -> reach m B nil b
| reach_cons: forall b L b' z off n q,
reach m B L b' ->
Mem.perm m b' z Cur Readable ->
ZMap.get z (PMap.get b' (Mem.mem_contents m)) =
Fragment (Vptr b off) q n ->
reach m B ((b',z)::L) b.
Fixpoint reach' (m:mem) (B:block -> Prop) (L:list (block * Z)): block -> Prop:=
match L with
nil => B
| l::L => match l with
(b',z) => match ZMap.get z (PMap.get b' (Mem.mem_contents m))
with Fragment (Vptr b off) q  n => fun bb => bb = b /\
Mem.perm m b' z Cur Readable /\
reach' m B L b'
| _ => fun bb => False
end
end
end.
Fixpoint reach'' (m:mem) (B:block -> bool) (L:list (block * Z)): block -> bool:=
match L with
nil => B
| l::L => match l with
(b',z) => match ZMap.get z (PMap.get b' (Mem.mem_contents m))
with Fragment (Vptr b off) q  n => fun bb => eq_block bb b &&
Mem.perm_dec m b' z Cur Readable  &&
reach'' m B L b'
| _ => fun bb => false
end
end
end.
Parameter REACH : mem -> (block -> bool) -> block -> bool.
Definition replace_locals (mu:SM_Injection) pSrc' pTgt': SM_Injection :=
match mu with
Build_SM_Injection locBSrc locBTgt pSrc pTgt local extBSrc extBTgt fSrc fTgt extern =>
Build_SM_Injection locBSrc locBTgt pSrc' pTgt' local extBSrc extBTgt fSrc fTgt extern
end.
(*typically, we have forall b, pSrc b -> pSrc' b and forall b, pTgt b -> pTgt' b, i.e. only reclassify private entries as public*)
Definition replace_externs (mu:SM_Injection) fSrc' fTgt': SM_Injection :=
match mu with
Build_SM_Injection locBSrc locBTgt pSrc pTgt local extBSrc extBTgt fSrc fTgt extern =>
Build_SM_Injection locBSrc locBTgt pSrc pTgt local extBSrc extBTgt fSrc' fTgt' extern
end.
(*typically, we have forall b, fSrc b -> fSrc' b and forall b, fTgt b -> fTgt' b, i.e. only reclassify unknown entries as foreign*)
Definition getBlocks (V:list val) (b: block): bool :=
in_dec eq_block b
(fold_right (fun v L => match v with Vptr b' z => b'::L | _ => L end) nil V).
Definition REACH_closed m (X: Values.block -> bool) : Prop :=
(forall b, REACH m X b = true -> X b = true).
Definition mapped (j:meminj) b : bool :=
match j b with None => false | Some _ => true end.
(*The blocks explicitly exported via call arguments, plus the already shared blocks*)
Definition exportedSrc mu vals b := orb (getBlocks vals b) (sharedSrc mu b).
Definition exportedTgt mu vals b := orb (getBlocks vals b) (sharedTgt mu b).

Lemma REACH_as_inj: forall mu (WD: SM_wd mu) m1 m2 vals1 vals2
(MemInjMu : Mem.inject (as_inj mu) m1 m2)
(ValInjMu : Forall2 (val_inject (as_inj mu)) vals1 vals2) b1
(R : REACH m1 (exportedSrc mu vals1) b1 = true)
B (HB: forall b b2 d, shared_of mu b = Some(b2,d) -> B b2 = true),
exists b2 d, as_inj mu b1 = Some (b2, d) /\
REACH m2 (fun b => orb (getBlocks vals2 b) (B b)) b2 = true.