Section SelfSim.
Variable Sem: semantics.
(*Separate state and memory*)
Variable core: Type.
Variable state_to_memcore: state Sem -> (core * Mem.mem).
Variable memcore_to_state: core -> Mem.mem -> state Sem.
Hypothesis state_to_memcore_correct:
forall c m, state_to_memcore (memcore_to_state c m) = (c,m).
Hypothesis memcore_to_state_correct: forall s c m,
state_to_memcore  s = (c,m) -> s = memcore_to_state c m.
(*extension of a mem_injection (slightly stengthens the old inject_separated - LENB: not sure you need the stronger prop*)
Definition is_ext (f1:meminj)(nb1: positive)(f2:meminj)(nb2:positive) : Prop:=
forall b1 b2 ofs,
f2 b1 = Some (b2, ofs) ->
f1 b1 = None ->
(ofs = 0 /\ ~ Plt b1 nb1 /\  ~ Plt b2 nb2).
(*The code is also injected*)
Variable code_inject: meminj -> core -> core -> Prop.
Variable code_inj_incr: forall c1 mu c2 mu',
code_inject mu c1 c2 ->
inject_incr mu mu' ->
code_inject mu' c1 c2.
(*The current permisions OF THIS THREAD are unchanged! *)
(*This is slightly stronger than Mem.inject/mi_inj which allows permissions to grow (on compilation). *)
(*also it could be restricted to take only the Cur permissions*)
(*NEVERMIND... BOTH FOLLOW from Mem.inject!*)
Definition perm_inject1 (f:meminj)(m1:mem)(m2:mem): Prop:=
forall b1 b2 delta,
f b1 = Some (b2, delta) ->
forall ofs p,
Mem.perm m1 b1 (ofs ) Cur p  ->
Mem.perm m2 b2 (ofs + delta) Cur p.
Definition perm_inject2 (f:meminj)(m1:mem)(m2:mem): Prop:=
forall b1 b2 delta,
f b1 = Some (b2, delta) ->
forall ofs p,
Mem.perm m2 b2 (ofs + delta) Cur p ->
Mem.perm m1 b1 (ofs ) Cur p \/ ~ Mem.perm m1 b1 ofs Cur Nonempty.
Record match_mem (f: meminj) (m1:mem) (m2:mem): Prop:=
{ minject: Mem.inject f m1 m2
; pimage: perm_image f (getCurPerm m1)
; ppreimage: perm_surj f (getCurPerm m1) (getCurPerm m2)
}.
Instance proper_match_mem:
Proper (Logic.eq ==> mem_equiv ==> mem_equiv ==> iff) match_mem.
Record match_self (f: meminj) (c1:core) (m1:mem) (c2:core) (m2:mem): Prop:=
{ cinject: code_inject f c1 c2
; matchmem: match_mem f m1 m2
}.

Lemma match_source_forward:
forall mu c1 m1 c2 m2,
match_self mu c1 m1 c2 m2 ->
forall mu' m1' m2',
inject_incr mu mu' ->
Mem.inject mu' m1' m2' ->
same_visible m1 m1' ->
same_visible m2 m2' ->
match_self mu' c1 m1' c2 m2'.