(** Properties of [switch] compilation *)
Remark switch_table_shift:
forall n sl base dfl,
switch_target n (S dfl) (switch_table sl (S base)) =
S (switch_target n dfl (switch_table sl base)).
Remark length_switch_table:
forall sl base1 base2,
length (switch_table sl base1) = length (switch_table sl base2).
Inductive transl_lblstmt_cont(cenv: compilenv) (xenv: exit_env): lbl_stmt -> cont -> cont -> Prop :=
| tlsc_default: forall s k ts,
transl_stmt cenv (switch_env (LSdefault s) xenv) s = OK ts ->
transl_lblstmt_cont cenv xenv (LSdefault s) k (Kblock (Kseq ts k))
| tlsc_case: forall i s ls k ts k',
transl_stmt cenv (switch_env (LScase i s ls) xenv) s = OK ts ->
transl_lblstmt_cont cenv xenv ls k k' ->
transl_lblstmt_cont cenv xenv (LScase i s ls) k (Kblock (Kseq ts k')).

(* Specifications: *)
Lemma switch_descent:
forall cenv xenv k ls body s,
transl_lblstmt cenv (switch_env ls xenv) ls body = OK s ->
exists k',
transl_lblstmt_cont cenv xenv ls k k'
/\ (forall f sp e m,
plus step tge (State f s k sp e m) E0 (State f body k' sp e m)).
Lemma switch_ascent:
forall f n sp e m cenv xenv k ls k1,
let tbl := switch_table ls O in
let ls' := select_switch n ls in
transl_lblstmt_cont cenv xenv ls k k1 ->
exists k2,
star step tge (State f (Sexit (switch_target n (length tbl) tbl)) k1 sp e m)
E0 (State f (Sexit O) k2 sp e m)
/\ transl_lblstmt_cont cenv xenv ls' k k2.
Lemma switch_match_cont:
forall cenv xenv k cs tk ls tk',
match_cont k tk cenv xenv cs ->
transl_lblstmt_cont cenv xenv ls tk tk' ->
match_cont (Csharpminor.Kseq (seq_of_lbl_stmt ls) k) tk' cenv (false :: switch_env ls xenv) cs.
Lemma transl_lblstmt_suffix:
forall n cenv xenv ls body ts,
transl_lblstmt cenv (switch_env ls xenv) ls body = OK ts ->
let ls' := select_switch n ls in
exists body', exists ts',
transl_lblstmt cenv (switch_env ls' xenv) ls' body' = OK ts'.
Lemma switch_match_states:
forall fn k e le m tfn ts tk sp te tm cenv xenv f lo hi cs sz ls body tk'
(TRF: transl_funbody cenv sz fn = OK tfn)
(TR: transl_lblstmt cenv (switch_env ls xenv) ls body = OK ts)
(MINJ: Mem.inject f m tm)
(MCS: match_callstack f m tm
(Frame cenv tfn e le te sp lo hi :: cs)
(Mem.nextblock m) (Mem.nextblock tm))
(MK: match_cont k tk cenv xenv cs)
(TK: transl_lblstmt_cont cenv xenv ls tk tk'),
exists S,
plus step tge (State tfn (Sexit O) tk' (Vptr sp Int.zero) te tm) E0 S
/\ match_states (Csharpminor.State fn (seq_of_lbl_stmt ls) k e le m) S.
Lemma switch_descent:
forall cenv xenv k ls body s,
transl_lblstmt cenv (switch_env ls xenv) ls body = OK s ->
exists k',
transl_lblstmt_cont cenv xenv ls k k'
/\ (forall f sp e m,
plus step tge (State f s k sp e m) E0 (State f body k' sp e m)).
Lemma switch_ascent:
forall f n sp e m cenv xenv k ls k1,
let tbl := switch_table ls O in
let ls' := select_switch n ls in
transl_lblstmt_cont cenv xenv ls k k1 ->
exists k2,
star step tge (State f (Sexit (switch_target n (length tbl) tbl)) k1 sp e m)
E0 (State f (Sexit O) k2 sp e m)
/\ transl_lblstmt_cont cenv xenv ls' k k2.
Lemma switch_match_cont:
forall cenv xenv k cs tk ls tk',
match_cont k tk cenv xenv cs ->
transl_lblstmt_cont cenv xenv ls tk tk' ->
match_cont (Csharpminor.Kseq (seq_of_lbl_stmt ls) k) tk' cenv (false :: switch_env ls xenv) cs.
Lemma transl_lblstmt_suffix:
forall n cenv xenv ls body ts,
transl_lblstmt cenv (switch_env ls xenv) ls body = OK ts ->
let ls' := select_switch n ls in
exists body', exists ts',
transl_lblstmt cenv (switch_env ls' xenv) ls' body' = OK ts'.
Lemma switch_match_states:
forall fn k e le m tfn ts tk sp te tm cenv xenv f lo hi cs sz ls body tk'
(TRF: transl_funbody cenv sz fn = OK tfn)
(TR: transl_lblstmt cenv (switch_env ls xenv) ls body = OK ts)
(MINJ: Mem.inject f m tm)
(MCS: match_callstack f m tm
(Frame cenv tfn e le te sp lo hi :: cs)
(Mem.nextblock m) (Mem.nextblock tm))
(MK: match_cont k tk cenv xenv cs)
(TK: transl_lblstmt_cont cenv xenv ls tk tk'),
exists S,
plus step tge (State tfn (Sexit O) tk' (Vptr sp Int.zero) te tm) E0 S
/\ match_states (Csharpminor.State fn (seq_of_lbl_stmt ls) k e le m) S.