End EXPRESSIONS.
(** Semantic preservation for functions and statements. *)
Inductive match_cont: Cminor.program -> helper_functions -> Cminor.cont -> CminorSel.cont -> Prop :=
| match_cont_stop: forall cunit hf,
match_cont cunit hf Cminor.Kstop Kstop
| match_cont_seq: forall cunit hf s s' k k',
sel_stmt (prog_defmap cunit) s = OK s' ->
match_cont cunit hf k k' ->
match_cont cunit hf (Cminor.Kseq s k) (Kseq s' k')
| match_cont_block: forall cunit hf k k',
match_cont cunit hf k k' ->
match_cont cunit hf (Cminor.Kblock k) (Kblock k')
| match_cont_call: forall cunit' hf' cunit hf id f sp e k f' e' k',
linkorder cunit prog ->
helper_functions_declared cunit hf ->
sel_function (prog_defmap cunit) hf f = OK f' ->
match_cont cunit hf k k' -> env_lessdef e e' ->
match_cont cunit' hf' (Cminor.Kcall id f sp e k) (Kcall id f' sp e' k').
Definition match_call_cont (k: Cminor.cont) (k': CminorSel.cont) : Prop :=
forall cunit hf, match_cont cunit hf k k'.
Inductive match_states: Cminor.state -> CminorSel.state -> Prop :=
| match_state: forall cunit hf f f' s k s' k' sp e m e' m'
(LINK: linkorder cunit prog)
(HF: helper_functions_declared cunit hf)
(TF: sel_function (prog_defmap cunit) hf f = OK f')
(TS: sel_stmt (prog_defmap cunit) s = OK s')
(MC: match_cont cunit hf k k')
(LD: env_lessdef e e')
(ME: Mem.extends m m'),
match_states
(Cminor.State f s k sp e m)
(State f' s' k' sp e' m')
| match_callstate: forall cunit f f' args args' k k' m m'
(LINK: linkorder cunit prog)
(TF: match_fundef cunit f f')
(MC: match_call_cont k k')
(LD: Val.lessdef_list args args')
(ME: Mem.extends m m'),
match_states
(Cminor.Callstate f args k m)
(Callstate f' args' k' m')
| match_returnstate: forall v v' k k' m m'
(MC: match_call_cont k k')
(LD: Val.lessdef v v')
(ME: Mem.extends m m'),
match_states
(Cminor.Returnstate v k m)
(Returnstate v' k' m')
| match_builtin_1: forall cunit hf ef args args' optid f sp e k m al f' e' k' m'
(LINK: linkorder cunit prog)
(HF: helper_functions_declared cunit hf)
(TF: sel_function (prog_defmap cunit) hf f = OK f')
(MC: match_cont cunit hf k k')
(LDA: Val.lessdef_list args args')
(LDE: env_lessdef e e')
(ME: Mem.extends m m')
(EA: list_forall2 (CminorSel.eval_builtin_arg tge sp e' m') al args'),
match_states
(Cminor.Callstate (External ef) args (Cminor.Kcall optid f sp e k) m)
(State f' (Sbuiltin (sel_builtin_res optid) ef al) k' sp e' m')
| match_builtin_2: forall cunit hf v v' optid f sp e k m f' e' m' k'
(LINK: linkorder cunit prog)
(HF: helper_functions_declared cunit hf)
(TF: sel_function (prog_defmap cunit) hf f = OK f')
(MC: match_cont cunit hf k k')
(LDV: Val.lessdef v v')
(LDE: env_lessdef e e')
(ME: Mem.extends m m'),
match_states
(Cminor.Returnstate v (Cminor.Kcall optid f sp e k) m)
(State f' Sskip k' sp (set_builtin_res (sel_builtin_res optid) v' e') m').
Remark call_cont_commut:
forall cunit hf k k', match_cont cunit hf k k' -> match_call_cont (Cminor.call_cont k) (call_cont k').
Remark match_is_call_cont:
forall cunit hf k k', match_cont cunit hf k k' -> Cminor.is_call_cont k -> match_call_cont k k'.
Remark match_call_cont_cont:
forall k k', match_call_cont k k' -> exists cunit hf, match_cont cunit hf k k'.
Remark find_label_commut:
forall cunit hf lbl s k s' k',
match_cont cunit hf k k' ->
sel_stmt (prog_defmap cunit) s = OK s' ->
match Cminor.find_label lbl s k, find_label lbl s' k' with
| None, None => True
| Some(s1, k1), Some(s1', k1') => sel_stmt (prog_defmap cunit) s1 = OK s1' /\ match_cont cunit hf k1 k1'
| _, _ => False
end.
Definition measure (s: Cminor.state) : nat :=
match s with
| Cminor.Callstate _ _ _ _ => 0%nat
| Cminor.State _ _ _ _ _ _ => 1%nat
| Cminor.Returnstate _ _ _ => 2%nat
end.

Lemma sel_step_correct:
forall S1 t S2, Cminor.step ge S1 t S2 ->
forall T1, match_states S1 T1 ->
(exists T2, step tge T1 t T2 /\ match_states S2 T2)
\/ (measure S2 < measure S1 /\ t = E0 /\ match_states S2 T1)%nat.