(** The simulation diagram. *)

Fixpoint seq_left_depth (s: Csharpminor.stmt) : nat :=
  match s with
  | Csharpminor.Sseq s1 s2 => S (seq_left_depth s1)
  | _ => O
  end.Definition measure (S: Csharpminor.state) : nat :=
  match S with
  | Csharpminor.State fn s k e le m => seq_left_depth s
  | _ => O
  end.(*LENB: Refactoring of original proof:
  1. isolate lemmas for individual cases
  2. Have individual cases be more specific about
     which of the 2 disjuncts they imply
  3. make place swhere meminj's are extended more explicit.
     This is done by exposing meminj's as additional parameter
     of match_state, so that individual lemmas can
     explicitly exisitenitally quantify over the extensions and
     impose additional conditions (eg in case Builtin)
  Other steps one could do:
   - refactoring of states into cores and memories
   - add knowlegsde the amounts to "at_external"*)

Inductive match_statesInj: meminj -> Csharpminor.state -> Cminor.state -> Prop :=
  | matchInj_state:
      forall fn s k e le m tfn ts tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = 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),
      match_statesInj f (Csharpminor.State fn s k e le m)
                   (State tfn ts tk (Vptr sp Int.zero) te tm)
  | matchInj_state_seq:
      forall fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (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 (Csharpminor.Kseq s2 k) tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn (Csharpminor.Sseq s1 s2) k e le m)
                   (State tfn ts1 tk (Vptr sp Int.zero) te tm)
  | matchInj_callstate:
      forall fd args k m tfd targs tk tm f cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject f args targs),
      match_statesInj f (Csharpminor.Callstate fd args k m)
                   (Callstate tfd targs tk tm)
  | matchInj_returnstate:
      forall v k m tv tk tm f cs cenv
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject f v tv),
      match_statesInj f (Csharpminor.Returnstate v k m)
                   (Returnstate tv tk tm).(*LENB: Refactoring of original proof:
  1. isolate lemmas for individual cases
  2. Have individual cases be more specific about
     which of the 2 disjuncts they imply
  3. make place swhere meminj's are extended more explicit.
     This is done by exposing meminj's as additional parameter
     of match_state, so that individual lemmas can
     explicitly exisitenitally quantify over the extensions and
     impose additional conditions (eg in case Builtin)
  Other steps one could do:
   - refactoring of states into cores and memories
   - add knowlegsde the amounts to "at_external"*)

Inductive match_statesInj: meminj -> Csharpminor.state -> Cminor.state -> Prop :=
  | matchInj_state:
      forall fn s k e le m tfn ts tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = 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),
      match_statesInj f (Csharpminor.State fn s k e le m)
                   (State tfn ts tk (Vptr sp Int.zero) te tm)
  | matchInj_state_seq:
      forall fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (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 (Csharpminor.Kseq s2 k) tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn (Csharpminor.Sseq s1 s2) k e le m)
                   (State tfn ts1 tk (Vptr sp Int.zero) te tm)
  | matchInj_callstate:
      forall fd args k m tfd targs tk tm f cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject f args targs),
      match_statesInj f (Csharpminor.Callstate fd args k m)
                   (Callstate tfd targs tk tm)
  | matchInj_returnstate:
      forall v k m tv tk tm f cs cenv
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject f v tv),
      match_statesInj f (Csharpminor.Returnstate v k m)
                   (Returnstate tv tk tm).(*LENB: Refactoring of original proof:
  1. isolate lemmas for individual cases
  2. Have individual cases be more specific about
     which of the 2 disjuncts they imply
  3. make place swhere meminj's are extended more explicit.
     This is done by exposing meminj's as additional parameter
     of match_state, so that individual lemmas can
     explicitly exisitenitally quantify over the extensions and
     impose additional conditions (eg in case Builtin)
  Other steps one could do:
   - refactoring of states into cores and memories
   - add knowlegsde the amounts to "at_external"*)

Inductive match_statesInj: meminj -> Csharpminor.state -> Cminor.state -> Prop :=
  | matchInj_state:
      forall fn s k e le m tfn ts tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = 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),
      match_statesInj f (Csharpminor.State fn s k e le m)
                   (State tfn ts tk (Vptr sp Int.zero) te tm)
  | matchInj_state_seq:
      forall fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (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 (Csharpminor.Kseq s2 k) tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn (Csharpminor.Sseq s1 s2) k e le m)
                   (State tfn ts1 tk (Vptr sp Int.zero) te tm)
  | matchInj_callstate:
      forall fd args k m tfd targs tk tm f cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject f args targs),
      match_statesInj f (Csharpminor.Callstate fd args k m)
                   (Callstate tfd targs tk tm)
  | matchInj_returnstate:
      forall v k m tv tk tm f cs cenv
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject f v tv),
      match_statesInj f (Csharpminor.Returnstate v k m)
                   (Returnstate tv tk tm).(*LENB: Refactoring of original proof:
  1. isolate lemmas for individual cases
  2. Have individual cases be more specific about
     which of the 2 disjuncts they imply
  3. make place swhere meminj's are extended more explicit.
     This is done by exposing meminj's as additional parameter
     of match_state, so that individual lemmas can
     explicitly exisitenitally quantify over the extensions and
     impose additional conditions (eg in case Builtin)
  Other steps one could do:
   - refactoring of states into cores and memories
   - add knowlegsde the amounts to "at_external"*)

Inductive match_statesInj: meminj -> Csharpminor.state -> Cminor.state -> Prop :=
  | matchInj_state:
      forall fn s k e le m tfn ts tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = 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),
      match_statesInj f (Csharpminor.State fn s k e le m)
                   (State tfn ts tk (Vptr sp Int.zero) te tm)
  | matchInj_state_seq:
      forall fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (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 (Csharpminor.Kseq s2 k) tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn (Csharpminor.Sseq s1 s2) k e le m)
                   (State tfn ts1 tk (Vptr sp Int.zero) te tm)
  | matchInj_callstate:
      forall fd args k m tfd targs tk tm f cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject f args targs),
      match_statesInj f (Csharpminor.Callstate fd args k m)
                   (Callstate tfd targs tk tm)
  | matchInj_returnstate:
      forall v k m tv tk tm f cs cenv
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject f v tv),
      match_statesInj f (Csharpminor.Returnstate v k m)
                   (Returnstate tv tk tm).(*LENB: Refactoring of original proof:
  1. isolate lemmas for individual cases
  2. Have individual cases be more specific about
     which of the 2 disjuncts they imply
  3. make place swhere meminj's are extended more explicit.
     This is done by exposing meminj's as additional parameter
     of match_state, so that individual lemmas can
     explicitly exisitenitally quantify over the extensions and
     impose additional conditions (eg in case Builtin)
  Other steps one could do:
   - refactoring of states into cores and memories
   - add knowlegsde the amounts to "at_external"*)

Inductive match_statesInj: meminj -> Csharpminor.state -> Cminor.state -> Prop :=
  | matchInj_state:
      forall fn s k e le m tfn ts tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = 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),
      match_statesInj f (Csharpminor.State fn s k e le m)
                   (State tfn ts tk (Vptr sp Int.zero) te tm)
  | matchInj_state_seq:
      forall fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (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 (Csharpminor.Kseq s2 k) tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn (Csharpminor.Sseq s1 s2) k e le m)
                   (State tfn ts1 tk (Vptr sp Int.zero) te tm)
  | matchInj_callstate:
      forall fd args k m tfd targs tk tm f cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject f args targs),
      match_statesInj f (Csharpminor.Callstate fd args k m)
                   (Callstate tfd targs tk tm)
  | matchInj_returnstate:
      forall v k m tv tk tm f cs cenv
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject f v tv),
      match_statesInj f (Csharpminor.Returnstate v k m)
                   (Returnstate tv tk tm).

(* Specifications: *)
Lemma matchInj_Intro: forall S T, match_states S T -> exists j, match_statesInj j S T.
Lemma matchInj_Elim: forall j S T, match_statesInj j S T -> match_states S T.
Lemma transl_step_case_SkipSeq: forall cenv sz f tfn j m tm e le te sp lo hi cs s k tk xenv (TR: transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j m tm (Frame cenv tfn e le te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont (Csharpminor.Kseq s k) tk cenv xenv cs), exists T2 : state, plus step tge (State tfn Sskip tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.State f s k e le m) T2.
Lemma transl_step_case_SkipBlock: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j m tm (Frame cenv tfn e le te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont (Csharpminor.Kblock k) tk cenv xenv cs), exists T2 : state, plus step tge (State tfn Sskip tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.State f Csharpminor.Sskip k e le m) T2.
Lemma transl_step_case_SkipCall: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv m' (CC: Csharpminor.is_call_cont k) (FL: Mem.free_list m (blocks_of_env e) = Some m') (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j 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), exists T2 : state, plus step tge (State tfn Sskip tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.Returnstate Vundef k m') T2.
Lemma transl_step_case_Assign: forall cenv sz f tfn j m tm e lenv te sp lo hi cs k tk xenv x a x0 v id (EE: Csharpminor.eval_expr ge e lenv m a v) (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont k tk cenv xenv cs) (EQ : transl_expr cenv a = OK (x, x0)), exists T2 : state, plus step tge (State tfn (Sassign id x) tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.State f Csharpminor.Sskip k e (PTree.set id v lenv) m) T2.
Lemma transl_step_case_Store: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv x x0 x1 x2 chunk m' a addr vaddr v (CH: Mem.storev chunk m vaddr v = Some m') (EvAddr : Csharpminor.eval_expr ge e le m addr vaddr) (EvA : Csharpminor.eval_expr ge e le m a v) (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j 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) (EQ : transl_expr cenv addr = OK (x, x0)) (EQ1 : transl_expr cenv a = OK (x1, x2)), exists T2 : state, plus step tge (State tfn (make_store chunk x x1) tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.State f Csharpminor.Sskip k e le m') T2.
Lemma transl_step_case_Call: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv x x0 x1 a vf fd optid vargs bl (EvalA: Csharpminor.eval_expr ge e le m a vf) (EvalBL: Csharpminor.eval_exprlist ge e le m bl vargs) (FF: Genv.find_funct ge vf = Some fd) (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j 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) (EQ : transl_expr cenv a = OK (x, x0)) (EQ1 : transl_exprlist cenv bl = OK x1), exists T2 : state, plus step tge (State tfn (Scall optid (Csharpminor.funsig fd) x x1) tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.Callstate fd vargs (Csharpminor.Kcall optid f e le k) m) T2.
Lemma transl_step_case_Builtin: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv x t ef optid vres m' bl vargs (EvalArgs: Csharpminor.eval_exprlist ge e le m bl vargs) (ExtCall: external_call ef ge vargs m t vres m') (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j 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) (EQ : transl_exprlist cenv bl = OK x), exists T2 : state, plus step tge (State tfn (Sbuiltin optid ef x) tk (Vptr sp Int.zero) te tm) t T2 /\ exists j', inject_incr j j' /\ match_statesInj j' (Csharpminor.State f Csharpminor.Sskip k e (set_optvar optid vres le) m') T2.
Lemma transl_step_case_Ite: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv x x0 x1 x2 b v a s1 s2 (H : Csharpminor.eval_expr ge e le m a v) (BoolOfVal: Val.bool_of_val v b) (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j 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) (EQ : transl_expr cenv a = OK (x, x0)) (EQ1 : transl_stmt cenv xenv s1 = OK x1) (EQ0 : transl_stmt cenv xenv s2 = OK x2), exists T2 : state, plus step tge (State tfn (Sifthenelse x x1 x2) tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.State f (if b then s1 else s2) k e le m) T2.
Lemma transl_step_case_Loop: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv x s (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j 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) (EQ : transl_stmt cenv xenv s = OK x), exists T2 : state, plus step tge (State tfn (Sloop x) tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.State f s (Csharpminor.Kseq (Csharpminor.Sloop s) k) e le m) T2.
Lemma transl_step_case_Block: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv x s (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j 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) (EQ : transl_stmt cenv (true :: xenv) s = OK x), exists T2 : state, plus step tge (State tfn (Sblock x) tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.State f s (Csharpminor.Kblock k) e le m) T2.
Lemma transl_step_case_ExitSeq: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv n s (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j m tm (Frame cenv tfn e le te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont (Csharpminor.Kseq s k) tk cenv xenv cs), exists T2 : state, plus step tge (State tfn (Sexit (shift_exit xenv n)) tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.State f (Csharpminor.Sexit n) k e le m) T2.
Lemma transl_step_case_ExitBlockZero: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j m tm (Frame cenv tfn e le te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont (Csharpminor.Kblock k) tk cenv xenv cs), exists T2 : state, plus step tge (State tfn (Sexit (shift_exit xenv 0)) tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.State f Csharpminor.Sskip k e le m) T2.
Lemma transl_step_case_ExitBlockNonzero: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv n (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j m tm (Frame cenv tfn e le te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont (Csharpminor.Kblock k) tk cenv xenv cs), exists T2 : state, plus step tge (State tfn (Sexit (shift_exit xenv (S n))) tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.State f (Csharpminor.Sexit n) k e le m) T2.
Lemma switch_match_statesInj: forall fn k e le m tfn ts tk sp te tm cenv xenv j 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 j m tm) (MCS: match_callstack j 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_statesInj j (Csharpminor.State fn (seq_of_lbl_stmt ls) k e le m) S.
Lemma transl_step_case_Switch: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv a x x0 ts cases n (EvalA: Csharpminor.eval_expr ge e le m a (Vint n)) (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j 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) (EQ : transl_expr cenv a = OK (x, x0)) (EQ0 : transl_lblstmt cenv (switch_env cases xenv) cases (Sswitch x (switch_table cases 0) (length (switch_table cases 0))) = OK ts), exists T2 : state, plus step tge (State tfn ts tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.State f (seq_of_lbl_stmt (select_switch n cases)) k e le m) T2.
Lemma transl_step_case_ReturnNone: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv m' (Freelist : Mem.free_list m (blocks_of_env e) = Some m') (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j 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), exists T2 : state, plus step tge (State tfn (Sreturn None) tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.Returnstate Vundef (Csharpminor.call_cont k) m') T2.
Lemma transl_step_case_ReturnSome: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv a x x0 m' v (EvalA : Csharpminor.eval_expr ge e le m a v) (Freelist: Mem.free_list m (blocks_of_env e) = Some m') (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j 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) (EQ : transl_expr cenv a = OK (x, x0)), exists T2 : state, plus step tge (State tfn (Sreturn (Some x)) tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.Returnstate v (Csharpminor.call_cont k) m') T2.
Lemma transl_step_case_Label: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv lbl x s (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j 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) (EQ : transl_stmt cenv xenv s = OK x), exists T2 : state, plus step tge (State tfn (Slabel lbl x) tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.State f s k e le m) T2.
Lemma transl_step_case_Goto: forall cenv sz f tfn j m tm e le te sp lo hi cs k tk xenv lbl s' k' (FindLab: Csharpminor.find_label lbl (Csharpminor.fn_body f) (Csharpminor.call_cont k) = Some (s', k')) (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack j 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), exists T2 : state, plus step tge (State tfn (Sgoto lbl) tk (Vptr sp Int.zero) te tm) E0 T2 /\ match_statesInj j (Csharpminor.State f s' k' e le m) T2.
Lemma transl_step_case_InternalCall: forall cenv f j m tm e cs k tk vargs targs x m1 lenv (*(Param: list_norepet (fn_params_names f ++ fn_vars_names f))*) (Param1: list_norepet (map fst (Csharpminor.fn_vars f))) (Param2 : list_norepet (Csharpminor.fn_params f)) (Param3 : list_disjoint (Csharpminor.fn_params f) (fn_temps f)) (AlocVars : alloc_variables empty_env m (Csharpminor.fn_vars f) e m1) (BindParams: bind_parameters (Csharpminor.fn_params f) vargs (create_undef_temps (fn_temps f)) = Some lenv) (MINJ : Mem.inject j m tm) (MCS : match_callstack j m tm cs (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont k tk cenv nil cs) (ISCC : Csharpminor.is_call_cont k) (ARGSINJ : val_list_inject j vargs targs) (EQ : transl_function f = OK x), exists T2 : state, plus step tge (Callstate (Internal x) targs tk tm) E0 T2 /\ exists j', inject_incr j j' /\ match_statesInj j' (Csharpminor.State f (Csharpminor.fn_body f) k e lenv m1) T2.
Lemma transl_step_case_ExternalCall: forall ef vargs m t vres m' cenv cs tm j k tk targs (ExtCall : external_call ef ge vargs m t vres m') (MINJ : Mem.inject j m tm) (MCS : match_callstack j m tm cs (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont k tk cenv nil cs) (ISCC : Csharpminor.is_call_cont k) (ARGSINJ : val_list_inject j vargs targs), exists T2 : state, plus step tge (Callstate (External ef) targs tk tm) t T2 /\ exists j', inject_incr j j' /\ match_statesInj j' (Csharpminor.Returnstate vres k m') T2.
Lemma transl_step_case_Return: forall j m tm cs f e le k tk cenv v tv optid (MINJ : Mem.inject j m tm) (MCS : match_callstack j m tm cs (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont (Csharpminor.Kcall optid f e le k) tk cenv nil cs) (RESINJ : val_inject j v tv), exists T2 : state, @plus genv state step tge (Returnstate tv tk tm) E0 T2 /\ match_statesInj j (Csharpminor.State f Csharpminor.Sskip k e (set_optvar optid v le) m) T2.
Lemma transl_step_correct_MATCH: forall S1 t S2, Csharpminor.step ge S1 t S2 -> forall T1, match_states S1 T1 -> match S1 with Csharpminor.State f (Csharpminor.Sseq s1 s2) k e le m => (exists T2, plus step tge T1 t T2 /\ match_states S2 T2) \/ (measure S2 < measure S1 /\ t = E0 /\ match_states S2 T1)%nat | _ => (exists T2, plus step tge T1 t T2 /\ match_states S2 T2) end.
Lemma transl_step_correct: forall S1 t S2, Csharpminor.step ge S1 t S2 -> forall T1, match_states S1 T1 -> (exists T2, plus step tge T1 t T2 /\ match_states S2 T2) \/ (measure S2 < measure S1 /\ t = E0 /\ match_states S2 T1)%nat.
Lemma match_globalenvs_init: forall m, Genv.init_mem prog = Some m -> match_globalenvs (Mem.flat_inj (Mem.nextblock m)) (Mem.nextblock m).
Lemma transl_initial_states: forall S, Csharpminor.initial_state prog S -> exists R, Cminor.initial_state tprog R /\ match_states S R.
Lemma transl_final_states: forall S R r, match_states S R -> Csharpminor.final_state S r -> Cminor.final_state R r.
Theorem transl_program_correct: forward_simulation (Csharpminor.semantics prog) (Cminor.semantics tprog).