Section Injection.
Definition preserves_atx_inj {index:Type} {L1 L2} match_states
:=
forall (i:index)(j:meminj) s1 s2,
match_states i j s1 s2 ->
forall f args,
@at_external L1 s1 = Some (f,args) ->
exists args',
@at_external L2 s2 = Some (f,args') /\
Val.inject_list j args args'.
Definition simulation_atx_inj {index:Type} {L1 L2}
(match_states: index -> meminj -> _ -> _ -> Prop)
:=
forall s1 f args,
@at_external L1 s1 = Some (f,args) ->
forall t s1', Step L1 s1 t s1' ->
forall i f s2, match_states i f s1 s2 ->
exists i', exists s2' f' t',
Step L2 s2 t' s2' /\
match_states i' f' s1' s2' /\
Values.inject_incr f f' /\
inject_trace_strong f' t t'.
Record fsim_properties_inj: Type :=
{  Injindex: Type;
Injorder: Injindex -> Injindex -> Prop;
Injmatch_states: Injindex -> meminj -> state L1 -> state L2 -> Prop;
Injfsim_order_wf: well_founded Injorder;
Injfsim_match_meminj: forall i f s1 s2, Injmatch_states i f s1 s2 ->  Mem.inject f (get_mem1 s1) (get_mem2 s2);
Injfsim_match_full: forall i f s1 s2, Injmatch_states i f s1 s2 ->  injection_full f (get_mem1 s1);
Injfsim_match_initial_states:
forall s1, initial_state L1 s1 ->
exists i f s2, initial_state L2 s2 /\ Injmatch_states i f s1 s2;
Injfsim_match_final_states:
forall i s1 s2 r f,
Injmatch_states i f s1 s2 -> final_state L1 s1 r -> (final_state L2 s2 r);
Injfsim_simulation:
forall s1 t s1' f, Step L1 s1 t s1' ->
forall i s2, Injmatch_states i f s1 s2 ->
exists i', exists s2' f' t',
(Plus L2 s2 t' s2' \/ (Star L2 s2 t' s2' /\ Injorder i' i))
/\ Injmatch_states i' f' s1' s2' /\
Values.inject_incr f f' /\
inject_trace_strong f' t t';
Injsim_simulation_atx:
simulation_atx_inj Injmatch_states;
Injsim_atx:
preserves_atx_inj Injmatch_states;
Injfsim_public_preserved:
forall id, Senv.public_symbol (symbolenv L2) id = Senv.public_symbol (symbolenv L1) id
}.
Definition simulation_atx_inj_relaxed {index:Type} {L1 L2}
(match_states: index -> meminj -> _ -> _ -> Prop)
:=
forall s1 f args,
@at_external L1 s1 = Some (f,args) ->
forall t s1', Step L1 s1 t s1' ->
forall i f s2, match_states i f s1 s2 ->
exists f',
Values.inject_incr f f' /\
(exists i' s2' t',
Step L2 s2 t' s2' /\
match_states i' f' s1' s2' /\
inject_trace_strong f' t t') /\
forall t',
inject_trace f' t t' ->
exists i', exists s2',
Step L2 s2 t' s2' /\
match_states i' f' s1' s2'.
Record fsim_properties_inj_relaxed: Type :=
{  InjindexX: Type;
InjorderX: InjindexX -> InjindexX -> Prop;
Injmatch_statesX: InjindexX -> meminj -> state L1 -> state L2 -> Prop;
Injfsim_order_wfX: well_founded InjorderX;
Injfsim_match_meminjX: forall i f s1 s2, Injmatch_statesX i f s1 s2 ->  Mem.inject f (get_mem1 s1) (get_mem2 s2);
Injfsim_match_fullX: forall i f s1 s2, Injmatch_statesX i f s1 s2 ->  injection_full f (get_mem1 s1);
Injfsim_match_initial_statesX:
forall s1, initial_state L1 s1 ->
exists i f s2, initial_state L2 s2 /\ Injmatch_statesX i f s1 s2;
Injfsim_match_final_statesX:
forall i s1 s2 r f,
Injmatch_statesX i f s1 s2 -> final_state L1 s1 r -> (final_state L2 s2 r);
Injfsim_simulationX:
forall s1 t s1' f, Step L1 s1 t s1' ->
forall i s2, Injmatch_statesX i f s1 s2 ->
exists i', exists s2' f' t',
(Plus L2 s2 t' s2' \/ (Star L2 s2 t' s2' /\ InjorderX i' i))
/\ Injmatch_statesX i' f' s1' s2' /\
Values.inject_incr f f' /\
inject_trace f' t t';
Injsim_simulation_atxX:
simulation_atx_inj_relaxed Injmatch_statesX;
Injsim_atxX:
preserves_atx_inj Injmatch_statesX;
Injfsim_public_preservedX:
forall id, Senv.public_symbol (symbolenv L2) id = Senv.public_symbol (symbolenv L1) id
}.
(** An alternate form of the simulation diagram *)

Lemma Injfsim_simulation':
forall (SIM:fsim_properties_inj),
forall i s1 t s1' f,
Step L1 s1 t s1' ->
forall s2, Injmatch_states SIM i f s1 s2 ->
(exists i', exists s2' f' t',
Plus L2 s2 t' s2' /\
Injmatch_states SIM i' f' s1' s2'
/\ inject_incr f f' /\ inject_trace_strong f' t t')
\/ (exists i' f', Injorder SIM i' i /\ t = E0 /\ Injmatch_states SIM i' f' s1' s2
/\ inject_incr f f').