Library Clight_sim

Require Import sepcomp.core_semantics.
Require Import sepcomp.forward_simulations.
Require Import sepcomp.forward_simulations_lemmas.

Require Import veric.base.
Require Import veric.Clight_lemmas.
Require Import veric.Clight_new.
Require Clight.
Module CC := Clight.

Definition CCstep ge := Clight.step ge Clight.function_entry2.

Lemma cc_step_fun: forall ge s1 s2 s2',
   CCstep ge s1 nil s2 -> CCstep ge s1 nil s2' -> s2=s2'.
Proof.
 intros.
 inv H; inv H0;
 repeat match goal with
  | H: _ \/ _ |- _ => destruct H; try discriminate
  end;
 try contradiction;
  repeat fun_tac; auto; try congruence.
  pose proof (assign_loc_fun H15 H4); subst m'0. auto.
  inversion2 H5 H18.
   pose proof (eval_exprlist_fun H16 H3); subst; auto.
  destruct (Events.external_call_determ _ _ _ _ _ _ _ _ _ _ H14 H2).
  destruct H0; subst; auto.
  inv H1; inv H6.
  inversion2 H9 H4.
  pose proof (alloc_variables_fun H8 H3). inv H4.
  auto.
  destruct (Events.external_call_determ _ _ _ _ _ _ _ _ _ _ H9 H1).
  destruct H0; subst; auto.
Qed.

Fixpoint strip_skip' (k: CC.cont) : CC.cont :=
 match k with
 | CC.Kseq Sskip k' => strip_skip' k'
 | _ => k
 end.

Inductive match_cont: cont -> CC.cont -> Prop :=
  | match_cont_nil: match_cont nil CC.Kstop
  | match_cont_seq: forall s k k',
         match_cont (strip_skip k) (strip_skip' k') ->
          match_cont (Kseq s :: k) (CC.Kseq s k')
  | match_cont_loop1: forall e3 s k k',
         match_cont (strip_skip k) (strip_skip' k') ->
          match_cont (Kseq Scontinue :: Kloop1 s e3 :: k) (CC.Kloop1 s e3 k')
  | match_cont_loop2: forall e3 s k k',
         match_cont (strip_skip k) (strip_skip' k') ->
          match_cont (Kloop2 s e3 :: k) (CC.Kloop2 s e3 k')
  | match_cont_switch: forall k k',
         match_cont (strip_skip k) (strip_skip' k') ->
          match_cont (Kswitch :: k) (CC.Kswitch k')
  | match_cont_call: forall lid fd f ve te k k'
         (CUR: current_function k = Some f),
         match_cont (strip_skip k) (strip_skip' k') ->
          match_cont (Kseq (Sreturn None) :: Kcall lid fd ve te :: k) (CC.Kcall lid f ve te k').


Lemma exec_skips:
 forall {s0 k s k'}
   (H1: match_cont (Kseq s0 :: k) (strip_skip' (CC.Kseq s k')))
   ge f ve te m,
   match s0 with Sskip => False | Scontinue => False | Sloop _ _ => False
            | Sifthenelse _ _ _ => False | Sreturn _ => False
            | _ => True end ->
   exists k2, strip_skip' (CC.Kseq s k') = CC.Kseq s0 k2 /\
     Smallstep.star CCstep ge (CC.State f s k' ve te m) Events.E0
              (CC.State f s0 k2 ve te m).
Proof.
 intros.
 remember (CC.Kseq s k') as k0.
 revert k s k' H1 Heqk0; induction k0; intros; inv Heqk0.
 assert ({s1=Sskip}+{s1<>Sskip}) by (destruct s1; try (left; congruence); right; congruence).
 destruct H0. subst s1.
 destruct k'; try solve [inv H1].
 specialize (IHk0 _ s k' H1 (eq_refl _)).
 destruct IHk0 as [k2 [? ?]].
 exists k2. split; simpl; auto.
 econstructor 2. constructor. eauto. auto.
 inv H1; contradiction. simpl in *. inv H1. contradiction.
  replace (strip_skip' (CC.Kseq s1 k')) with (CC.Kseq s1 k') in *
     by (destruct s1; try congruence; auto).
 inv H1.
 exists k'; split; auto.
 constructor 1.
Qed.

Lemma strip_skip_not:
  forall s k, s<>Sskip -> strip_skip (Kseq s :: k) = (Kseq s :: k).
Proof.
 destruct s; intros; auto. congruence.
Qed.
Lemma strip_skip'_not:
  forall s k, s<>Sskip -> strip_skip' (CC.Kseq s k) = (CC.Kseq s k).
Proof.
 destruct s; intros; auto. congruence.
Qed.

Lemma dec_skip: forall s, {s=Sskip}+{s<>Sskip}.
Proof.
 destruct s; try (left; congruence); right; congruence.
Qed.

Lemma dec_continue: forall s, {s=Scontinue}+{s<>Scontinue}.
Proof.
 destruct s; try (left; congruence); right; congruence.
Qed.

Lemma strip_step:
  forall ge ve te k m st' m',
     cl_step ge (State ve te (strip_skip k)) m st' m' <->
    cl_step ge (State ve te k) m st' m'.
Proof.
intros.
 induction k; intros; split; simpl; intros; try destruct IHk; auto.
 destruct a; try destruct s; auto.
  constructor; auto.
 destruct a; try destruct s; auto.
 inv H. auto.
Qed.

Lemma continue_cont_skip:
  forall k, continue_cont k = continue_cont (strip_skip k).
Proof.
 induction k; simpl; intros; auto.
 destruct a; auto. destruct s; auto.
Qed.

Lemma break_cont_skip:
    forall k, break_cont (strip_skip k) = break_cont k.
Proof. induction k; try destruct a; simpl; auto; destruct s; simpl; auto.
Qed.

Lemma continue_cont_is:
 forall k, match (continue_cont k) with nil => True | Kseq e3 :: Kloop2 s e3' :: _ => e3=e3' | _ => False end.
Proof.
 induction k; simpl; auto; try contradiction.
  destruct a; auto.
Qed.

Inductive step' ge : (corestate * mem) -> Events.trace -> (corestate * mem) -> Prop :=
 mk_step': forall q m q' m', cl_step ge q m q' m' -> step' ge (q,m) Events.E0 (q',m').

Definition ef_exit := EF_external exit_syscall_number (mksignature nil None).

Inductive initial_state (p: program): (corestate * mem) -> Prop :=

  .
A final state is a Returnstate with an empty continuation.

Inductive final_state: (corestate * mem) -> int -> Prop :=

 .
Lemma match_cont_strip:
   forall s k k', match_cont (strip_skip k) (strip_skip' k') ->
           match_cont (strip_skip (Kseq s :: k)) (strip_skip' (CC.Kseq s k')).
 Proof.
 intros. destruct (dec_skip s). subst. simpl; auto.
  rewrite strip_skip_not by auto. rewrite strip_skip'_not by auto.
  constructor; auto.
 Qed.

Lemma exec_skips':
  forall ge f s k' s0 k0' ve te m,
        strip_skip' (CC.Kseq s k') = CC.Kseq s0 k0' ->
        Smallstep.star CCstep ge (CC.State f s k' ve te m) Events.E0
                                   (CC.State f s0 k0' ve te m).
Proof.
 intros.
 destruct (dec_skip s). subst. simpl in *.
 induction k'; try solve [inv H].
 destruct (dec_skip s). subst. simpl in *.
 econstructor 2; eauto. constructor. auto. rewrite strip_skip'_not in * by auto.
 inv H. econstructor 2; eauto. constructor. constructor 1. auto.
 rewrite strip_skip'_not in H by auto. inv H. constructor 1.
Qed.

Lemma break_strip:
 forall ge f ve te m k,
     Smallstep.star CCstep ge (CC.State f Sbreak k ve te m) nil (CC.State f Sbreak (strip_skip' k) ve te m).
 Proof. induction k; try solve [constructor 1].
    destruct (dec_skip s). subst. simpl.
     econstructor 2. constructor. eauto. auto.
  rewrite strip_skip'_not; auto. constructor 1.
Qed.

Lemma plus_trans: forall ge s1 s2 s3,
   Smallstep.plus CCstep ge s1 Events.E0 s2 -> Smallstep.plus CCstep ge s2 Events.E0 s3 -> Smallstep.plus CCstep ge s1 Events.E0 s3.
Proof.
 intros. eapply Smallstep.plus_trans; eauto.
Qed.

Lemma star_plus_trans: forall ge s1 s2 s3,
   Smallstep.star CCstep ge s1 Events.E0 s2 -> Smallstep.plus CCstep ge s2 Events.E0 s3 -> Smallstep.plus CCstep ge s1 Events.E0 s3.
Proof.
 intros. eapply Smallstep.star_plus_trans; eauto.
Qed.

Lemma plus_star_trans: forall ge s1 s2 s3,
   Smallstep.plus CCstep ge s1 Events.E0 s2 -> Smallstep.star CCstep ge s2 Events.E0 s3 -> Smallstep.plus CCstep ge s1 Events.E0 s3.
Proof.
 intros. eapply Smallstep.plus_star_trans; eauto.
Qed.

Lemma star_trans: forall ge s1 s2 s3,
   Smallstep.star CCstep ge s1 Events.E0 s2 -> Smallstep.star CCstep ge s2 Events.E0 s3 -> Smallstep.star CCstep ge s1 Events.E0 s3.
Proof.
 intros. eapply Smallstep.star_trans; eauto.
Qed.

Lemma strip_skip'_loop2:
  forall ge f ve te m a3 s k1 k, CC.Kloop2 a3 s k1 = strip_skip' k ->
  Smallstep.star CCstep ge (CC.State f Sskip k ve te m) Events.E0 (CC.State f Sskip (CC.Kloop2 a3 s k1) ve te m).
Proof.
 induction k; intros; try solve [inv H].
 destruct (dec_skip s0). subst. eapply Smallstep.star_trans; try apply IHk; auto. apply Smallstep.star_one. constructor. auto.
 rewrite strip_skip'_not in * by auto.
 rewrite <- H. constructor 1. simpl in H. inv H. constructor 1.
Qed.

Lemma call_strip: forall k, call_cont (strip_skip k) = call_cont k.
Proof.
 induction k; simpl; intros; auto. destruct a; simpl; auto. destruct s; simpl; auto.
Qed.

Lemma strip_call: forall k, strip_skip (call_cont k) = call_cont k.
Proof.
 induction k; simpl; intros; auto. destruct a; simpl; auto.
Qed.

Lemma call_strip': forall k, CC.call_cont (strip_skip' k) = CC.call_cont k.
Proof.
 induction k; simpl; intros; auto. destruct s; simpl; auto.
Qed.

Lemma strip_call': forall k, strip_skip' (CC.call_cont k) = CC.call_cont k.
Proof.
 induction k; simpl; intros; auto.
Qed.

Lemma strip_skip'_loop1:
  forall ge f ve te m a3 s k1 k, CC.Kloop1 a3 s k1 = strip_skip' k ->
  Smallstep.star CCstep ge (CC.State f Sskip k ve te m) Events.E0 (CC.State f Sskip (CC.Kloop1 a3 s k1) ve te m).
Proof.
 induction k; intros; try solve [inv H].
 destruct (dec_skip s0). subst. eapply Smallstep.star_trans; try apply IHk; auto. apply Smallstep.star_one. constructor. auto.
 rewrite strip_skip'_not in * by auto.
 rewrite <- H. constructor 1. simpl in H. inv H. constructor 1.
Qed.

Lemma strip_skip'_call:
  forall ge f ve te m lid f' ve' te' k1 k, CC.Kcall lid f' ve' te' k1 = strip_skip' k ->
  Smallstep.star CCstep ge (CC.State f Sskip k ve te m) Events.E0 (CC.State f Sskip (CC.Kcall lid f' ve' te' k1) ve te m).
Proof.
 induction k; intros; try solve [inv H].
 destruct (dec_skip s). subst. eapply Smallstep.star_trans; try apply IHk; auto. apply Smallstep.star_one. constructor. auto.
 rewrite strip_skip'_not in * by auto.
 rewrite <- H. constructor 1. simpl in H. inv H. constructor 1.
Qed.

Lemma match_cont_call_strip:
 forall k k',
    call_cont k <> nil ->
    match_cont (strip_skip k) (strip_skip' k') ->
   match_cont (Kseq (Sreturn None) :: call_cont k) (CC.call_cont k').
Proof.
 intros.
 rewrite <- call_strip in *. rewrite <- call_strip'.
 forget (strip_skip k) as k1. forget (strip_skip' k') as k1'.
 revert H; induction H0; simpl; intros; try rewrite call_strip in *; try rewrite call_strip' in *; auto.
 congruence.
 constructor; auto.
Qed.

Lemma match_cont_strip1:
  forall k k', match_cont k k' -> match_cont (strip_skip k) (strip_skip' k').
 Proof. induction 1; try solve [constructor; auto].
 apply match_cont_strip. auto.
Qed.

Lemma match_find_label_None:
  forall lbl s1 k0 k0', match_cont (strip_skip k0) (strip_skip' k0') ->
     find_label lbl s1 k0 = None -> CC.find_label lbl s1 k0' = None
 with match_find_ls_None:
   forall lbl ls k0 k0', match_cont (strip_skip k0) (strip_skip' k0') ->
     find_label_ls lbl ls k0 = None -> CC.find_label_ls lbl ls k0' = None.
Proof. induction s1; intros; simpl in *; auto.
 revert H0; case_eq (find_label lbl s1_1 (Kseq s1_2 :: k0)); intros. inv H1.
 erewrite IHs1_1; eauto. apply match_cont_strip. auto.
 revert H0; case_eq (find_label lbl s1_1 k0); intros. inv H1.
 erewrite IHs1_1; eauto.
 revert H0; case_eq (find_label lbl s1_1 (Kseq Scontinue :: Kloop1 s1_1 s1_2 :: k0)); intros. inv H1.
 erewrite IHs1_1; eauto. erewrite IHs1_2; eauto. simpl. constructor. auto.
 simpl. constructor; auto.
 eapply match_find_ls_None; eauto. constructor. auto.
 if_tac. subst. inv H0. eapply match_find_label_None; eauto.
 induction ls; intros; simpl in *.
 eapply match_find_label_None; eauto.
 revert H0; case_eq (find_label lbl s (Kseq (seq_of_labeled_statement ls) :: k0)); intros.
 inv H1.
 erewrite match_find_label_None; eauto. apply match_cont_strip. auto.
Qed.

Lemma match_find_label: forall lbl k' s1 k0 k0',
     match_cont (strip_skip k0) (strip_skip' k0') ->
     (find_label lbl s1 k0 = Some k' ->
      exists s2 : statement, exists k2' : CC.cont,
       CC.find_label lbl s1 k0' = Some (s2, k2') /\
       match_cont k' (CC.Kseq s2 k2'))
 with match_find_label_ls: forall lbl k' s1 k0 k0',
     match_cont (strip_skip k0) (strip_skip' k0') ->
     (find_label_ls lbl s1 k0 = Some k' ->
      exists s2 : statement, exists k2' : CC.cont,
       CC.find_label_ls lbl s1 k0' = Some (s2, k2') /\
       match_cont k' (CC.Kseq s2 k2')).
Proof.
 induction s1; intros; simpl in *; intuition; try discriminate.
 revert H0; case_eq (find_label lbl s1_1 (Kseq s1_2 :: k0)); intros.
 inv H1.
 destruct (IHs1_1 (Kseq s1_2 :: k0) (CC.Kseq s1_2 k0')) as [s2 [k2' [? ?]]]; clear IHs1_1.
 apply match_cont_strip. auto. auto.
 exists s2; exists k2'; split; auto. rewrite H1; auto.
  destruct (IHs1_2 k0 k0') as [s2 [k2' [? ?]]]; clear IHs1_1 IHs1_2; auto.
 exists s2, k2'; split; auto.
 erewrite match_find_label_None; eauto.
  apply match_cont_strip. auto.
 revert H0; case_eq (find_label lbl s1_1 k0); intros. inv H1.
 destruct (IHs1_1 k0 k0') as [s2 [k2' [? ?]]]; clear IHs1_1; auto.
 exists s2, k2'; split; auto.
 rewrite H1. auto.
  destruct (IHs1_2 k0 k0') as [s2 [k2' [? ?]]]; clear IHs1_1 IHs1_2; auto.
 exists s2, k2'; split; auto.
 erewrite match_find_label_None; eauto.
 revert H0; case_eq (find_label lbl s1_1 (Kseq Scontinue :: Kloop1 s1_1 s1_2 :: k0)); intros.
 inv H1.
 destruct (IHs1_1 (Kseq Scontinue :: Kloop1 s1_1 s1_2 :: k0) (CC.Kloop1 s1_1 s1_2 k0')) as [s2 [k2' [? ?]]]; clear IHs1_1; auto.
 simpl. constructor; auto.
 exists s2, k2'; split; auto. rewrite H1. auto.
 destruct (IHs1_2 (Kloop2 s1_1 s1_2 :: k0) (CC.Kloop2 s1_1 s1_2 k0')) as [s2 [k2' [? ?]]]; clear IHs1_1; auto.
 constructor; auto.
 exists s2, k2'; split; auto.
 erewrite match_find_label_None; eauto. simpl. constructor; auto.
 destruct (match_find_label_ls lbl k' l (Kswitch :: k0) (CC.Kswitch k0')) as [s2 [k2' [? ?]]]; auto.
 constructor; auto.
 exists s2, k2'; split; auto.
 if_tac. subst l.
 exists s1, k0'; split; auto. inv H0; constructor; auto.
 destruct (IHs1 k0 k0') as [s2 [k2' [? ?]]]; auto.
 exists s2, k2'; split; auto.

 induction s1; intros. simpl in *.
 eauto.
 simpl in *.
 revert H0; case_eq (find_label lbl s (Kseq (seq_of_labeled_statement s1) :: k0)); intros.
 inv H1.
destruct (match_find_label lbl k' s (Kseq (seq_of_labeled_statement s1) :: k0) (CC.Kseq (seq_of_labeled_statement s1) k0')) as [s2 [k2' [? ?]]]; auto.
apply match_cont_strip. auto.
 exists s2, k2'; split; auto.
 rewrite H1. auto.
 erewrite match_find_label_None; eauto.
apply match_cont_strip. auto.
Qed.

Lemma current_function_strip: forall k, current_function (strip_skip k) = current_function k.
Proof.
 induction k; try destruct a; try destruct s; simpl; auto.
Qed.

 Lemma current_function_call_cont:
   forall k, current_function (call_cont k) = current_function k.
 Proof. induction k; try destruct a; simpl; auto. Qed.

 Lemma current_function_find_label:
  forall lbl f s k k', current_function k = Some f ->
              find_label lbl s k = Some k' ->
              current_function k' = Some f
 with current_function_find_label_ls:
  forall lbl f s k k', current_function k = Some f ->
              find_label_ls lbl s k = Some k' ->
              current_function k' = Some f.
 Proof.
   induction s; simpl; intros; try discriminate.
   revert H0; case_eq (find_label lbl s1 (Kseq s2 :: k)); intros. inv H1.
   eapply IHs1; [ | eauto]. simpl; auto.
   eapply IHs2; [ | eauto]. simpl; auto.
 revert H0; case_eq (find_label lbl s1 k); intros. inv H1.
   eapply IHs1; [ | eauto]. simpl; auto.
   eapply IHs2; [ | eauto]. simpl; auto.
 revert H0; case_eq (find_label lbl s1 (Kseq Scontinue :: Kloop1 s1 s2 :: k)); intros. inv H1.
   eapply IHs1; [ | eauto]. simpl; auto.
   eapply IHs2; [ | eauto]. simpl; auto.
  eapply current_function_find_label_ls; [ | eauto]. simpl; auto.
  if_tac in H0. inv H0. simpl. auto.
   eapply IHs; [ | eauto]. simpl; auto.
   induction s; simpl; intros; try discriminate.
  eapply current_function_find_label; [ | eauto]. simpl; auto.
  revert H0; case_eq (find_label lbl s (Kseq (seq_of_labeled_statement s0) :: k)); intros.
 inv H1.
  eapply current_function_find_label; [ | eauto]. simpl; auto.
   eapply IHs; [ | eauto]. simpl; auto.
 Qed.

Lemma step_continue_strip:
  forall ge f k ve te m,
           Smallstep.star CCstep ge (CC.State f Scontinue k ve te m) Events.E0
               (CC.State f Scontinue (strip_skip' k) ve te m).
Proof.
intros.
induction k; simpl; try constructor 1.
destruct (dec_skip s).
subst.
eapply Smallstep.star_trans.
  apply Smallstep.star_one. apply CC.step_continue_seq.
  apply IHk.
auto.
destruct s; try congruence; constructor 1.
Qed.

Inductive CC_core : Type :=
    CC_core_State : function ->
            statement -> CC.cont -> env -> temp_env -> CC_core
  | CC_core_Callstate : fundef -> list val -> CC.cont -> CC_core
  | CC_core_Returnstate : val -> CC.cont -> CC_core.

Definition CC_core_to_CC_state (c:CC_core) (m:mem) : CC.state :=
  match c with
     CC_core_State f st k e te => CC.State f st k e te m
  | CC_core_Callstate fd args k => CC.Callstate fd args k m
  | CC_core_Returnstate v k => CC.Returnstate v k m
 end.
Definition CC_state_to_CC_core (c:CC.state): CC_core * mem :=
  match c with
     CC.State f st k e te m => (CC_core_State f st k e te, m)
  | CC.Callstate fd args k m => (CC_core_Callstate fd args k, m)
  | CC.Returnstate v k m => (CC_core_Returnstate v k, m)
 end.

Lemma CC_core_CC_state_1: forall c m,
   CC_state_to_CC_core (CC_core_to_CC_state c m) = (c,m).
  Proof. intros. destruct c; auto. Qed.

Lemma CC_core_CC_state_2: forall s c m,
   CC_state_to_CC_core s = (c,m) -> s= CC_core_to_CC_state c m.
  Proof. intros. destruct s; simpl in *.
      destruct c; simpl in *; inv H; trivial.
      destruct c; simpl in *; inv H; trivial.
      destruct c; simpl in *; inv H; trivial.
  Qed.

Lemma CC_core_CC_state_3: forall s c m,
   s= CC_core_to_CC_state c m -> CC_state_to_CC_core s = (c,m).
  Proof. intros. subst. apply CC_core_CC_state_1. Qed.

Lemma CC_core_CC_state_4: forall s, exists c, exists m, s = CC_core_to_CC_state c m.
  Proof. intros. destruct s.
             exists (CC_core_State f s k e le). exists m; reflexivity.
             exists (CC_core_Callstate fd args k). exists m; reflexivity.
             exists (CC_core_Returnstate res k). exists m; reflexivity.
  Qed.

Lemma CC_core_to_CC_state_inj: forall c m c' m',
     CC_core_to_CC_state c m = CC_core_to_CC_state c' m' -> (c',m')=(c,m).
  Proof. intros.
       apply CC_core_CC_state_3 in H. rewrite CC_core_CC_state_1 in H. inv H. trivial.
  Qed.

Inductive match_states: forall (qm: corestate) (st: CC_core), Prop :=
 | match_states_seq: forall f ve te s k k'
      (CUR: current_function k = Some f),
      match_cont (strip_skip k) (strip_skip' (CC.Kseq s k')) ->
      match_states (State ve te k) (CC_core_State f s k' ve te)
 | match_states_ext: forall k f ef tyargs tyres args lid ve te k'
      (CUR: current_function k = Some f),
      match_cont (strip_skip k) (strip_skip' k') ->
      match_states (ExtCall ef (signature_of_type tyargs tyres) args lid ve te k)
           (CC_core_Callstate (External ef tyargs tyres) args (CC.Kcall lid f ve te k')).

Lemma Clightnew_Clight_sim_eq_noOrder_SSplusConclusion:
forall p (c1 : corestate) (m : mem) (c1' : corestate) (m' : mem),
corestep cl_core_sem (Genv.globalenv p) c1 m c1' m' ->
forall (c2 : CC_core),
 match_states c1 c2 ->
exists c2' : CC_core,
    Smallstep.plus CCstep (Genv.globalenv p) (CC_core_to_CC_state c2 m) Events.E0 (CC_core_to_CC_state c2' m') /\
    match_states c1' c2'.
Proof.
intros.
forget (Genv.globalenv p) as ge. clear p.
simpl in H.
revert c2 H0. induction H; intros.

Focus 1. inv H4.
simpl strip_skip in H9.
destruct (exec_skips H9 ge f ve te m) as [k2 [? ?]]; auto.
exists (CC_core_State f Sskip k2 ve te); split.
    eapply Smallstep.star_plus_trans. eassumption.
          apply Smallstep.plus_one. econstructor; eauto. reflexivity.
    constructor. apply CUR. rewrite H4 in H9. inv H9. simpl in *. apply H7.

Focus 1. inv H0.
destruct (exec_skips H5 ge f ve te m) as [k2 [? ?]]; auto.
exists (CC_core_State f Sskip k2 ve (PTree.set id v te)); split.
  eapply Smallstep.star_plus_trans. eassumption. apply Smallstep.plus_one. econstructor; eauto. auto.
  rewrite H0 in H5. inv H5; constructor; auto.

Focus 1. inv H7.
 destruct (exec_skips H12 ge f0 ve te m) as [k2 [? ?]]; auto.
 rewrite H7 in *. inv H12. simpl in CUR.
  exists (CC_core_State f (fn_body f) (CC.Kcall optid f0 ve te k2) ve' le').
  split.
eapply star_plus_trans. apply H8.
               eapply Smallstep.plus_two. econstructor; eauto.
              econstructor; eauto.
               apply list_norepet_app in H4. destruct H4 as [? [? ?]].
               econstructor; auto. reflexivity.
constructor.
              auto.
             apply match_cont_strip. simpl. constructor; auto.

Focus 1. inv H3.
 destruct (exec_skips H8 ge f ve te m) as [k2 [? ?]]; auto.
 rewrite H3 in *. inv H8. simpl in CUR.
  exists (CC_core_Callstate (External ef tyargs tyres) vargs (CC.Kcall optid f ve te k2)).
  split.
eapply star_plus_trans. eassumption. eapply Smallstep.plus_one. econstructor; eauto.
econstructor; eauto.

Focus 1.  inv H0.
 destruct (exec_skips H5 ge f ve te m) as [k2 [? ?]]; auto.
 rewrite H0 in *. inv H5.
 destruct (IHcl_step (CC_core_State f s1 (CC.Kseq s2 k2) ve te))
                as [st2 [? ?]]; clear IHcl_step.
 repeat constructor; auto.
 apply match_cont_strip. apply match_cont_strip. auto.
 exists st2; split; auto.
 eapply star_plus_trans; [ eassumption | ].
 eapply plus_trans. apply Smallstep.plus_one. constructor. eassumption.

 Focus 1.  inv H0.
 simpl strip_skip in H5.
 remember (strip_skip k) as k0.
 destruct k0.
 elimtype False; clear - H Heqk0.
 revert H; induction k; intros. inv H.
 forget (a::k) as k'; clear - Heqk0 H.
 remember (State ve te k') as s.
 revert ve te k' Heqs Heqk0; induction H; intros; inv Heqs; simpl in *; try congruence.
 eapply IHcl_step. reflexivity. auto.
 remember (strip_skip' (CC.Kseq s k')) as k0'.
 destruct k0'; inv H5;
  try solve [rewrite <- strip_step in H; rewrite <- Heqk0 in H; inv H].
 assert (s0<>Sskip).
 clear- Heqk0; intro; subst.
 revert Heqk0; induction k; simpl; intros. inv Heqk0. destruct a; try solve [inv Heqk0]; auto. destruct s; inv Heqk0; auto.
 destruct (IHcl_step (CC_core_State f s k' ve te))
                 as [st2 [? ?]]; clear IHcl_step.
 constructor; auto. rewrite <- Heqk0. rewrite <- Heqk0'.
 constructor 2; auto.
 exists st2; split; auto.

  destruct (IHcl_step (CC_core_State f Sskip (CC.Kloop1 s0 s1 k0') ve te))
                      as [st2 [? ?]]; clear IHcl_step.
 constructor; auto. simpl. rewrite <- Heqk0. constructor. auto.
  exists st2; split; auto.
 inv H0. destruct t1; inv H5. simpl in H0. subst t2.
 eapply plus_star_trans; try apply H4.
 clear - H3 Heqk0'.
 destruct s; inv Heqk0'.
 rewrite H0 in H3.
 eapply star_plus_trans; [ | apply Smallstep.plus_one; eauto ].
 rewrite <- H0;
 apply strip_skip'_loop1; auto.

 destruct (IHcl_step (CC_core_State f Sskip (CC.Kloop2 s0 s1 k0') ve te))
                      as [st2 [? ?]]; clear IHcl_step.
 destruct (dec_skip s). subst.
 econstructor; eauto. rewrite <- Heqk0. constructor. auto.
 rewrite strip_skip'_not in Heqk0' by auto. inv Heqk0'.
  exists st2; split; auto.
  destruct s; inv Heqk0'.
 eapply star_plus_trans; try apply H0.
 clear - H4; revert H4; induction k'; intros; inv H4.
 destruct (dec_skip s). subst.
 specialize (IHk' H0). econstructor 2. constructor. apply IHk'. auto.
 replace (CC.Kloop2 s0 s1 k0') with (CC.Kseq s k') by (destruct s; auto; congruence).
 constructor 1.
 constructor 1.

 destruct s; inv Heqk0'.
 destruct (IHcl_step (CC_core_State f Sskip (CC.Kcall o f0 e t k0') ve te))
                      as [st2 [? ?]]; clear IHcl_step.
 constructor; auto. rewrite <- Heqk0. constructor; auto.
  exists st2; split; auto.
  inv H0. destruct t1; inv H6. simpl in H0; subst t2.
 eapply plus_star_trans; [ | apply H5].
 inv H4.
 eapply star_plus_trans; [eapply strip_skip'_call; eauto | ].
 apply Smallstep.plus_one. constructor; auto.

 Focus 1.  inv H0.
 simpl strip_skip in H5.
 inv H5.
 Focus 1.  change (CC.Kseq Scontinue k'0 = strip_skip' (CC.Kseq s k')) in H3.
 symmetry in H3.
 rewrite continue_cont_skip in *.
 simpl in CUR.
 rewrite <- current_function_strip in CUR.
forget (strip_skip k) as k0. clear k. rename k0 into k.

 generalize (continue_cont_is k); case_eq (continue_cont k); intros; try contradiction.
 rewrite H0 in H; inv H.
 destruct c; try contradiction. destruct l; try contradiction. destruct c; try contradiction.
 subst s0.

 assert (Smallstep.star CCstep ge (CC.State f s k' ve te m) Events.E0
                             (CC.State f Scontinue k'0 ve te m)).
 clear - H3.
 destruct (dec_skip s). subst. simpl in H3.
 eapply exec_skips'; auto.
 rewrite strip_skip'_not in H3 by auto. inv H3. constructor.
 assert (Smallstep.star CCstep ge (CC.State f Scontinue k'0 ve te m) Events.E0
                                 (CC.State f Scontinue (strip_skip' k'0) ve te m)).
clear.
  induction k'0; try solve [constructor 1].
 destruct (dec_skip s). subst. simpl in *. econstructor 2. constructor. eassumption. auto.
  rewrite strip_skip'_not; auto. constructor 1.
 generalize (Smallstep.star_trans H2 H4 (eq_refl _)); clear H2 H4; intro.
 clear H3.
 forget (strip_skip' k'0) as k0'; clear k'0.
 assert (precontinue_cont k = Kloop1 s1 s2 :: l).
 revert H0; clear; induction k; simpl; try congruence. destruct a; try congruence; auto.
 assert (exists k1',
               Smallstep.star CCstep ge (CC.State f Scontinue k0' ve te m)
                  (Events.Eapp Events.E0 Events.E0)
                    (CC.State f Scontinue k1' ve te m) /\
               match_cont (Kseq Scontinue :: Kloop1 s1 s2 :: l) k1').
 clear - H1 H0.
 revert H0; induction H1; simpl; intros; try congruence.
 destruct IHmatch_cont as [k1' [? ?]].
 rewrite <- continue_cont_skip; auto.
 econstructor. split; [ | eassumption].
 eapply star_trans; try apply H.
 clear.
 eapply star_trans. apply Smallstep.star_one.
 apply CC.step_continue_seq.
 apply step_continue_strip.
 inv H0.
 econstructor; split. constructor 1. constructor. auto.
 destruct IHmatch_cont as [k1' [? ?]].
 rewrite <- continue_cont_skip; auto.
 econstructor. split; [ | eassumption].
 eapply star_trans; try apply H.
 eapply star_trans. apply Smallstep.star_one.
 apply CC.step_continue_switch.
 apply step_continue_strip.

 destruct H4 as [k1' [? ?]].
 generalize (Smallstep.star_trans H2 H4 (eq_refl _)); clear H2 H4; intro H2.
 rewrite H0 in *.
 assert (CUR': current_function l = Some f).
   clear - CUR H0. revert CUR H0; induction k; simpl; intros. inv CUR.
   destruct a; try discriminate; auto. inv H0. auto.
 clear H1 CUR k H0 H3.
 inv H5. inv H4. simpl in *.
 destruct (IHcl_step (CC_core_State f s2 (CC.Kloop2 s1 s2 k'0) ve te))
                      as [st2 [? ?]]; clear IHcl_step.
 constructor; auto. apply match_cont_strip. constructor. auto.
 exists st2; split; auto.
 eapply star_plus_trans; [apply H2 | ].
 eapply star_plus_trans; [ | apply H0].
 apply Smallstep.star_one. constructor. auto.

Focus 1.    change (CC.Kloop1 s0 e3 k'0 = strip_skip' (CC.Kseq s k')) in H1.
 destruct (dec_skip s); [ | destruct s; try congruence; inv H1].
 subst s.
 simpl in H.
 simpl in H1.
 simpl in *.
 assert (Smallstep.star CCstep ge (CC.State f Sskip k' ve te m) Events.E0
                   (CC.State f Sskip (CC.Kloop1 s0 e3 k'0) ve te m)).
 rewrite H1; clear.
 induction k'; intros; try solve [constructor 1].
  destruct (dec_skip s). subst. simpl in *. econstructor 2. constructor.
  apply IHk'. auto.
 rewrite strip_skip'_not; auto. constructor 1.
 forget (CC.State f Sskip k' ve te m) as st1.
 clear k' H1.
 assert (Smallstep.plus CCstep ge st1 Events.E0
                  (CC.State f e3 (CC.Kloop2 s0 e3 k'0) ve te m)).
 eapply Smallstep.star_plus_trans; try apply H0.
 econstructor. constructor. auto. constructor 1. reflexivity. auto.
 clear H0.
 destruct (IHcl_step (CC_core_State f e3 (CC.Kloop2 s0 e3 k'0) ve te))
                      as [st2 [? ?]]; clear IHcl_step.
 constructor; auto. apply match_cont_strip; constructor; auto.
 exists st2; split; auto.
 eapply plus_trans; eauto.

 Focus 1.
 inv H0. simpl strip_skip in H5.
 destruct (dec_skip s).
 subst. simpl strip_skip' in *.
 assert (exists k1', strip_skip' k' = CC.Kseq Sbreak k1').
     revert H5; clear. remember (strip_skip' k') as k0'.
     revert k' Heqk0'; induction k0'; intros; try solve [inv H5].
        inv H5. eauto.
 destruct H0 as [k1' H0].
 assert (Smallstep.star CCstep ge (CC.State f Sskip k' ve te m) Events.E0
                           (CC.State f Sbreak k1' ve te m)).
       revert k1' H0; clear; induction k'; intros; try solve [inv H0].
        destruct (dec_skip s). subst. simpl in *. specialize (IHk' _ H0).
            econstructor 2. constructor. eassumption. auto.
      rewrite strip_skip'_not in H0 by auto. inv H0.
         econstructor 2. constructor. constructor 1. auto.
 simpl.
 forget (CC.State f Sskip k' ve te m) as st1.
 rewrite H0 in *.
 clear k' H0.
 inv H5.
 rewrite <- break_cont_skip in *.
 simpl in CUR. rewrite <- current_function_strip in CUR.
 forget (strip_skip k) as k0.
 assert (Smallstep.star CCstep ge st1 Events.E0 (CC.State f Sbreak (strip_skip' k1') ve te m)).
      eapply Smallstep.star_trans; try apply H1; auto.
      2: instantiate (1:=Events.E0); auto.
      clear.
      induction k1'; try destruct s; try solve [constructor 1].
         simpl. econstructor 2; eauto. constructor. auto.
 forget (strip_skip' k1') as k0'. clear k1' H1.
 assert (X:exists k1',
             Smallstep.plus CCstep ge (CC.State f Sbreak k0' ve te m) Events.E0
                       (CC.State f Sskip k1' ve te m)
               /\ match_cont (strip_skip (break_cont k0)) (strip_skip' k1')).
       clear - H H2.
       revert H; induction H2; intros; try solve [inv H].
            rewrite break_cont_skip in *. simpl in H.
               destruct (IHmatch_cont H) as [k1' [? ?]]; clear IHmatch_cont. simpl.
               exists k1'; split; auto.
               eapply Smallstep.star_plus_trans; try eassumption. 2: instantiate (1:=Events.E0); auto.
               econstructor 2. constructor. 2: instantiate (1:=Events.E0); auto.
              apply break_strip.

            simpl in *. exists k'; split. econstructor.
                 eapply CC.step_break_loop1. constructor 1. auto.
                 auto.

            simpl in *. exists k'; split.
                  econstructor. eapply CC.step_skip_break_switch. auto.
                  constructor 1; auto.
                  auto.
                  auto.

 destruct X as [k1' [? ?]].
 destruct (IHcl_step (CC_core_State f Sskip k1' ve te))
                      as [st2 [? ?]]; clear IHcl_step.
       constructor; auto.
       clear - H CUR.
       revert CUR; induction k0; intros. inv CUR.
       destruct a; simpl in *; auto. inv H. inv H.
 exists st2; split; auto.
 eapply star_plus_trans; try apply H5.
      eapply star_trans; try apply H0.
      apply Smallstep.plus_star; apply H1.
      auto.

 rewrite strip_skip'_not in H5 by auto.
 inv H5. clear n.
 admit.
 Focus 1.  inv H1. simpl strip_skip in H6.
 inv H6.
 change (CC.Kseq (Sifthenelse a s1 s2) k'0 = strip_skip' (CC.Kseq s k')) in H4.
 assert (Smallstep.star CCstep ge (CC.State f s k' ve te m) nil (CC.State f (Sifthenelse a s1 s2) k'0 ve te m)).
     clear - H4.
     revert H4; induction k'; intros; try solve [ destruct s; inv H4; constructor 1].
     destruct (dec_skip s). subst s.
     destruct (dec_skip s0). subst s0. simpl in *.
     eapply Smallstep.star_trans; try apply IHk'; eauto. apply Smallstep.star_one. constructor. auto.
      change (strip_skip' (CC.Kseq Sskip (CC.Kseq s0 k'))) with
               (strip_skip' (CC.Kseq s0 k')) in H4.
      rewrite strip_skip'_not in H4 by auto.
      inv H4. apply Smallstep.star_one. constructor. rewrite strip_skip'_not in * by auto.
      inv H4. constructor 1.
 exists (CC_core_State f (if b then s1 else s2) k'0 ve te); split; auto.
 eapply star_plus_trans; try apply H1.
 apply Smallstep.plus_one. econstructor; eauto. auto. constructor; auto.
 apply match_cont_strip; auto.

 Focus 1.  inv H0. inv H4.
 change (CC.Kseq (Sloop s1 s2) k'0 = strip_skip' (CC.Kseq s k')) in H2.
 generalize (exec_skips' ge f _ _ _ _ ve te m (@eq_sym _ _ _ H2)); intro.
 exists ( (CC_core_State f s1 (CC.Kloop1 s1 s2 k'0) ve te)); split.
 eapply star_plus_trans; try apply H.
 apply Smallstep.plus_one. eapply CC.step_loop; eauto.
 constructor; auto. apply match_cont_strip; constructor; auto.

 Focus 1.   inv H0. inv H4.
 destruct s0; inv H3.
 generalize (strip_skip'_loop2 ge f ve te m _ _ _ _ H1); intro.
 exists (CC_core_State f s (CC.Kloop1 s a3 k'0) ve te); split.
eapply star_plus_trans; try apply H.
               econstructor.
                            eapply CC.step_skip_loop2; eauto.
                            apply Smallstep.star_one. eapply CC.step_loop; eauto.
                            auto.
constructor; auto. apply match_cont_strip. constructor. auto.

 Focus 1.  inv H3.
  remember (strip_skip' (CC.Kseq s k'0)) as k3. simpl in CUR, H8.
 inv H8.
 generalize (exec_skips' ge f0 _ _ _ _ ve te m (@eq_sym _ _ _ H4)); intro H99.
 assert (f0=f).
   simpl in CUR; clear - CUR H.
   revert H CUR; induction k; intros. inv H. simpl in *. destruct a; auto. inv CUR; auto. inv H; auto.
 subst f.
 generalize (match_cont_call_strip k k'1); intro.
 spec H3; [congruence |]. spec H3; [auto |].
 generalize H3; rewrite H; intro.
 inv H5.
elimtype False; clear - H10.
         revert H10; induction k'1; simpl; intros; congruence.
destruct optexp; [destruct H1 as [v [? ?]] | ]; (destruct optid; destruct H2 as [H2 H2'];
               try solve [contradiction H2; auto]; subst te'' ).
                eexists (CC_core_State f Sskip k'2 ve' (PTree.set i v' te')).
                split.
                     apply (star_plus_trans _ _ _ _ H99).                      eapply plus_trans with (s2:=CC.Returnstate v' (CC.call_cont k'1) m').
                                         eapply Smallstep.plus_one. simpl. econstructor; eauto.
                                         eapply Smallstep.plus_one. simpl. rewrite <- H13.
                                         eapply CC.step_returnstate.
                    constructor; auto.
                eexists (CC_core_State f Sskip k'2 ve' te').
                split.
                     eapply (star_plus_trans _ _ _ _ H99).                           eapply plus_trans with (s2:=CC.Returnstate v' (CC.call_cont k'1) m').
                                         eapply Smallstep.plus_one. simpl. econstructor; eauto.
                                         eapply Smallstep.plus_one. simpl. rewrite <- H13. eapply CC.step_returnstate.
                    constructor; auto.
                eexists (CC_core_State f Sskip k'2 ve' te').
                split.
                     eapply (star_plus_trans _ _ _ _ H99).                           eapply plus_trans with (s2:=CC.Returnstate Vundef (CC.call_cont k'1) m').
                                         eapply Smallstep.plus_one. simpl. econstructor; eauto.
                                         eapply Smallstep.plus_one. simpl. rewrite <- H13. eapply CC.step_returnstate.
                    constructor; auto.

 destruct optid. destruct H2. congruence.
 destruct H2; subst te''.
 simpl in H. inv H. simpl in CUR. symmetry in CUR; inv CUR.
 destruct s; inv H4.
 assert (Smallstep.star CCstep ge (CC.State f Sskip k'0 ve te m) nil
                         (CC.State f Sskip (CC.Kcall None f1 ve' te' k'1) ve te m)).
     clear H1; rename H3 into H1.
     clear - H1.
     revert H1; induction k'0; intros; try solve [inv H1].
           destruct (dec_skip s). subst s. simpl in H1.
               eapply star_trans; try apply IHk'0; auto. apply Smallstep.star_one. constructor; auto.
          rewrite strip_skip'_not in H1 by auto. rewrite <- H1. constructor 1.
          simpl in H1. inv H1. constructor 1.
 (econstructor; split; [eapply star_plus_trans; [ apply H | eapply Smallstep.plus_two ] | ]).
     eapply CC.step_skip_call; simpl; eauto.
     assert (X: CCstep ge (CC.Returnstate Vundef (CC.Kcall None f1 ve' te' k'1) m')
                                      Events.E0
                                     (CC_core_to_CC_state (CC_core_State f1 Sskip k'1 ve' te') m')).
            econstructor; eauto.
       apply X.
    auto.
    econstructor; eauto.

 Focus 1.  inv H0. simpl strip_skip in H5.
 remember (CC.Kseq s k') as k0'.
 inv H5.
 evar (c2': CC_core).
 exists c2'; split.
     Focus 2. constructor; eauto. apply match_cont_strip. simpl.
                    instantiate (1:= CC.Kswitch k'0). constructor. auto.
     generalize (exec_skips' ge f _ _ _ _ ve te m (@eq_sym _ _ _ H3)); intro H99.
        eapply star_plus_trans; try apply H99.
        unfold c2'. apply Smallstep.plus_one. simpl. constructor; auto.

 Focus 1.  inv H0. remember (CC.Kseq s0 k') as k0'. inv H5.
 destruct (IHcl_step (CC_core_State f s k'0 ve te)) as [st2 [? ?]]; clear IHcl_step.
 constructor; auto. apply match_cont_strip. auto.
 exists st2; split; auto.
   eapply star_plus_trans; try eassumption.
   generalize (exec_skips' ge f _ _ _ _ ve te m (@eq_sym _ _ _ H3)); intro H99.
     eapply star_trans; try apply H99.
     apply Smallstep.star_one. constructor.

 Focus 1.  inv H0. remember (CC.Kseq s k'0) as k0'. inv H5.
  generalize (match_cont_call_strip k k'1); intro.
 spec H0.
 clear - CUR. apply (call_cont_nonnil _ _ CUR).
 specialize (H0 H1).
  rewrite <- strip_call' in H0.
 change (Kseq (Sreturn None) :: call_cont k) with (strip_skip (Kseq (Sreturn None) :: call_cont k)) in H0.
 destruct (match_find_label _ _ _ _ _ H0 H) as [s2 [k2' [? ?]]].
 exists (CC_core_State f s2 k2' ve te); split.
    simpl in CUR0. inversion2 CUR CUR0.
     generalize (exec_skips' ge f _ _ _ _ ve te m (@eq_sym _ _ _ H3)); intro H99.
     eapply star_plus_trans; try apply H99.
         apply Smallstep.plus_one. constructor; auto.
         constructor; auto.
   clear - CUR H. forget (fn_body f) as s.
       rewrite <- current_function_call_cont in CUR.
       change (current_function (Kseq (Sreturn None) :: call_cont k) = Some f) in CUR.
        forget (Kseq (Sreturn None) :: call_cont k) as k0. clear - CUR H.
        eapply current_function_find_label; eauto.
 apply match_cont_strip1. auto.
Qed.

Definition CC_at_external (c: CC_core) : option (external_function * signature * list val) :=
  match c with
  | CC_core_State _ _ _ _ _ => None
  | CC_core_Callstate fd args k =>
    match fd with
      Internal _ => None
      | External ef tps tp =>
          match tp with
          | Tvoid => Some (ef, mksignature (typlist_of_typelist tps) None, args)
          | _ => Some (ef, mksignature (typlist_of_typelist tps) (Some (typ_of_type tp)), args)
          end
    end
  | CC_core_Returnstate _ _ => None
 end.
Parameter mkAfterExtCore: external_function -> typelist -> type -> val -> list val -> CC.cont -> option CC_core.

Definition CC_after_external (rv: option val) (c: CC_core) : option CC_core :=
  match rv, c with
   | Some v, CC_core_Callstate fd vargs k =>
                     match fd with
                         Internal _ => None
                       | External ef tps tp => mkAfterExtCore ef tps tp v vargs k
                     end

  | _, _ => None
  end.

Parameter main_function:function. Parameter myStatement:statement.
Definition CC_initial_core (ge: genv) (v: val) (args: list val) : option CC_core :=
  let tl := typed_params 2%positive (length args)
   in Some (CC_core_State main_function myStatement
                           (CC.Kseq (Scall None
                                  (Etempvar 1%positive (Tfunction (type_of_params tl) Tvoid))
                                  (map (fun x => Etempvar (fst x) (snd x)) tl))
                              (CC.Kseq (Sloop Sskip Sskip) CC.Kstop))
                          empty_env (temp_bindings 1%positive (v::args))).

Definition CC_step (ge: Genv.t fundef type) (q:CC_core) (m:mem) (q': CC_core) (m': mem) : Prop :=
  match q with
      CC_core_Callstate (External _ _ _ ) _ _ => False
   | _ => CCstep ge (CC_core_to_CC_state q m) (Events.E0)(CC_core_to_CC_state q' m')
  end.

Lemma CC_corestep_not_at_external: forall (ge : Genv.t fundef type) (m : mem) (q : CC_core) (m' : mem)
  (q' : CC_core), CC_step ge q m q' m' -> CC_at_external q = None.
  Proof. intros.
     destruct q; simpl in *; trivial.
       destruct f; trivial. contradiction.
  Qed.

Definition CC_safely_halted (q:CC_core) : option val := None.
Lemma CC_corestep_not_halted :
       forall ge m q m' q', CC_step ge q m q' m' -> CC_safely_halted q = None.
  Proof. intros; trivial. Qed.

 Lemma CC_at_external_halted_excl :
       forall q, CC_at_external q = None \/ CC_safely_halted q = None.
   Proof. intros. right; trivial. Qed.

Definition CC_core_sem : CoreSemantics (Genv.t fundef type) CC_core mem (list (ident * globdef fundef type)).
 apply (Build_CoreSemantics _ _ _ _ cl_init_mem
                CC_initial_core CC_at_external CC_after_external CC_safely_halted CC_step).
       apply CC_corestep_not_at_external.
       apply CC_corestep_not_halted.
       apply CC_at_external_halted_excl.
       admit.
  Defined.

Lemma CC_step_to_CCstep: forall ge q m q' m',
   CC_step ge q m q' m' -> CCstep ge (CC_core_to_CC_state q m) nil (CC_core_to_CC_state q' m').
  Proof. intros.
       destruct q; simpl in *. apply H.
          destruct f; try contradiction. apply H.
        apply H.
  Qed.

Definition isExternalCallState (c:CC.state) :=
  match c with CC.Callstate (External _ _ _ ) _ _ _ => True
                      | _ => False
  end.

Lemma CCstep_to_CC_step_1: forall ge c m c' m',
              CCstep ge (CC_core_to_CC_state c m) Events.E0 (CC_core_to_CC_state c' m') ->
              CC_at_external c = None -> CC_step ge c m c' m'.
   Proof. intros.
      destruct c; try apply H.
      destruct f; try apply H.
      destruct t0; try solve [inv H0].
   Qed.

  Lemma CC_atExternal_isExternal: forall s,
         (exists z, CC_at_external (fst (CC_state_to_CC_core s)) = Some z) = isExternalCallState s.
  Proof. intros. apply prop_ext.
     destruct s; simpl.
        split; intros; try contradiction. destruct H. inv H.
        destruct fd; simpl; intros.
        split; try contradiction.
        intros [z H1]. congruence.
        destruct t0; split; auto; intros; try solve[eexists; eauto].
        split; try solve[intros;elimtype False; auto|intros [? ?]; congruence].
  Qed.

Lemma step_to_CC_step: forall ge s s' (H:CCstep ge s Events.E0 s') (Hs: ~ isExternalCallState s),
       exists c, exists m, exists c', exists m',
                  s = CC_core_to_CC_state c m /\ s' = CC_core_to_CC_state c' m' /\
                  CC_step ge c m c' m'.
  Proof. intros.
       destruct (CC_core_CC_state_4 s) as [c [m Hcm]]; subst.
       destruct (CC_core_CC_state_4 s') as [c' [m' Hcm']]; subst.
       eexists. exists m. eexists. exists m'. split. reflexivity. split. reflexivity.
        apply CCstep_to_CC_step_1. apply H.
        remember (CC_at_external c) as b.
          destruct b; trivial; apply eq_sym in Heqb.
            exfalso. apply Hs. clear Hs.
            rewrite <- CC_atExternal_isExternal. exists p.
                 rewrite (CC_core_CC_state_3 _ c m); auto.
  Qed.

Lemma CC_step_to_step: forall ge c m c' m', CC_step ge c m c' m' ->
   CCstep ge (CC_core_to_CC_state c m) Events.E0 (CC_core_to_CC_state c' m').
  Proof. intros.
      destruct c; try apply H.
      destruct f; try contradiction. apply H.
  Qed.

Lemma CC_step_fun: forall ge m q m1 q1 m2 q2,
    CC_step ge q m q1 m1 ->
    CC_step ge q m q2 m2 ->
    (q1,m1)=(q2,m2).
Proof.
intros. apply CC_step_to_step in H. apply CC_step_to_step in H0.
  assert (Z:= cc_step_fun _ _ _ _ H H0).
  destruct q1; destruct q2; inv Z; trivial.
Qed.

Lemma exec_skips_CC:
 forall {s0 k s k'}
   (H1: match_cont (Kseq s0 :: k) (strip_skip' (CC.Kseq s k')))
   ge f ve te m,
   match s0 with Sskip => False | Scontinue => False | Sloop _ _ => False
            | Sifthenelse _ _ _ => False | Sreturn _ => False
            | _ => True end ->
   exists k2, strip_skip' (CC.Kseq s k') = CC.Kseq s0 k2 /\
     corestep_star CC_core_sem ge (CC_core_State f s k' ve te) m
              (CC_core_State f s0 k2 ve te) m.
Proof.
 intros.

 remember (CC.Kseq s k') as k0.
 revert k s k' H1 Heqk0; induction k0; intros; inv Heqk0.
 assert ({s1=Sskip}+{s1<>Sskip}) by (destruct s1; try (left; congruence); right; congruence).
 destruct H0.
subst s1.
      destruct k'; try solve [inv H1].
specialize (IHk0 _ s k' H1 (eq_refl _)).
                   destruct IHk0 as [k2 [? ?]].
                   exists k2. split; simpl; auto.
                   clear - H2. destruct H2 as [n Hn]. exists (S n). simpl.
                     eexists. eexists. split. Focus 2. apply Hn.
                                                          constructor.
inv H1; contradiction.
simpl in H1. inv H1. contradiction.
   replace (strip_skip' (CC.Kseq s1 k')) with (CC.Kseq s1 k') in *
       by (destruct s1; try congruence; auto).
  clear - H H1.
   inv H1. exists k'; split; auto. exists O. reflexivity.
Qed.

Lemma exec_skips'_CC:
  forall ge f s k' s0 k0' ve te m,
        strip_skip' (CC.Kseq s k') = CC.Kseq s0 k0' ->
        corestep_star CC_core_sem ge (CC_core_State f s k' ve te) m
                                   (CC_core_State f s0 k0' ve te) m.
Proof.
 intros.
 destruct (dec_skip s). subst. simpl in *.
 induction k'; try solve [inv H].
 destruct (dec_skip s). subst. simpl in *.
  eapply corestep_star_trans.
             Focus 2. apply IHk'. apply H.
       apply corestep_star_one. simpl. econstructor.
 rewrite strip_skip'_not in * by auto.
 inv H. apply corestep_star_one. simpl. econstructor.
 rewrite strip_skip'_not in H by auto. inv H. exists O. simpl. reflexivity.
Qed.

Lemma strip_skip'_loop1_CC:
  forall ge f ve te m a3 s k1 k, CC.Kloop1 s a3 k1 = strip_skip' k ->
  corestep_star CC_core_sem ge (CC_core_State f Sskip k ve te) m
                                                         (CC_core_State f Sskip (CC.Kloop1 s a3 k1) ve te) m.
Proof.
 induction k; intros; try solve [inv H].
 destruct (dec_skip s0). subst. simpl in H.
     eapply corestep_star_trans; try apply (IHk H).
       apply corestep_star_one. simpl. constructor.
 rewrite strip_skip'_not in * by auto.
 rewrite <- H. apply corestep_star_zero.
 simpl in H. inv H. apply corestep_star_zero.
Qed.

Lemma strip_skip'_call_CC:
  forall ge f ve te m lid f' ve' te' k1 k, CC.Kcall lid f' ve' te' k1 = strip_skip' k ->
  corestep_star CC_core_sem ge (CC_core_State f Sskip k ve te) m
                                                          (CC_core_State f Sskip (CC.Kcall lid f' ve' te' k1) ve te) m.
Proof.
 induction k; intros; try solve [inv H].
 destruct (dec_skip s). subst. simpl in H.
     eapply corestep_star_trans; try apply (IHk H).
       apply corestep_star_one. simpl. constructor.
 rewrite strip_skip'_not in * by auto.
 rewrite <- H. apply corestep_star_zero.
 simpl in H. inv H. apply corestep_star_zero.
Qed.

Lemma step_continue_strip_CC:
  forall ge f k ve te m,
           corestep_star CC_core_sem ge (CC_core_State f Scontinue k ve te) m
               (CC_core_State f Scontinue (strip_skip' k) ve te) m.
Proof.
intros.
induction k; simpl; try apply corestep_star_zero.
destruct (dec_skip s).
   subst.
   eapply corestep_star_trans.
         apply corestep_star_one.
            assert (ZZ: corestep CC_core_sem ge (CC_core_State f Scontinue (CC.Kseq Sskip k) ve te) m (CC_core_State f Scontinue k ve te) m).
                    simpl. apply (CC.step_continue_seq ge function_entry2 f Sskip k ve te m).
            apply ZZ.
         assumption.
destruct s; try congruence; apply corestep_star_zero.
Qed.

Lemma step_continue_seq_CC: forall ge f s k e le m,
       corestep CC_core_sem ge (CC_core_State f Scontinue (CC.Kseq s k) e le) m
                                                      (CC_core_State f Scontinue k e le) m.
  Proof. intros.
    assert (Z:CCstep ge (CC.State f Scontinue (CC.Kseq s k) e le m) Events.E0 (CC.State f Scontinue k e le m) ).
           apply CC.step_continue_seq.
    apply step_to_CC_step in Z.
                     destruct Z as [cc [mm [cc' [mm' [Heq1 [Heq2 Hstep]]]]]].
                         apply CC_core_CC_state_3 in Heq1. apply CC_core_CC_state_3 in Heq2. simpl in *.
                     inv Heq1. inv Heq2. apply Hstep.
                     auto.
  Qed.

Lemma step_continue_switch_CC: forall ge f k e le m,
              corestep CC_core_sem ge (CC_core_State f Scontinue (CC.Kswitch k) e le) m
                                                             (CC_core_State f Scontinue k e le) m.
  Proof. intros.
    assert (Z:CCstep ge (CC.State f Scontinue (CC.Kswitch k) e le m) Events.E0 (CC.State f Scontinue k e le m) ).
           apply CC.step_continue_switch.
    apply step_to_CC_step in Z.
                     destruct Z as [cc [mm [cc' [mm' [Heq1 [Heq2 Hstep]]]]]].
                         apply CC_core_CC_state_3 in Heq1. apply CC_core_CC_state_3 in Heq2. simpl in *.
                     inv Heq1. inv Heq2. apply Hstep.
                     auto.
  Qed.

Lemma break_strip_CC: forall ge f ve te m k,
       corestep_star CC_core_sem ge (CC_core_State f Sbreak k ve te) m
                               (CC_core_State f Sbreak (strip_skip' k) ve te) m.
 Proof. induction k; try solve [apply corestep_star_zero].
    destruct (dec_skip s).
subst. simpl.
         eapply corestep_star_trans; try eassumption. eapply corestep_star_one. constructor.
  rewrite strip_skip'_not; auto. apply corestep_star_zero.
Qed.

Lemma strip_skip'_loop2_CC:
  forall ge f ve te m a3 s k1 k, CC.Kloop2 s a3 k1 = strip_skip' k ->
  corestep_star CC_core_sem ge (CC_core_State f Sskip k ve te) m
                     (CC_core_State f Sskip (CC.Kloop2 s a3 k1) ve te) m.
Proof. intros.
 induction k; intros; try solve [inv H].
 destruct (dec_skip s0).
subst. eapply corestep_star_trans; try apply IHk; auto. apply corestep_star_one. constructor.
rewrite strip_skip'_not in * by auto.
         rewrite <- H. apply corestep_star_zero.

 simpl in H. inv H. apply corestep_star_zero.
Qed.

Lemma Clightnew_Clight_sim_eq_noOrder:
forall p (c1 : corestate) (m : mem) (c1' : corestate) (m' : mem),
corestep cl_core_sem (Genv.globalenv p) c1 m c1' m' ->
forall (c2 : CC_core),
 match_states c1 c2 ->
exists c2' : CC_core,
    corestep_plus CC_core_sem (Genv.globalenv p) c2 m c2' m' /\
    match_states c1' c2'.
Proof.
intros.
forget (Genv.globalenv p) as ge. clear p.
simpl in H.
revert c2 H0. induction H; intros.

Focus 1. inv H4.
simpl strip_skip in H9.
destruct (exec_skips_CC H9 ge f ve te m) as [k2 [? ?]]; auto.
exists (CC_core_State f Sskip k2 ve te); split.
       eapply corestep_star_plus_trans. eassumption.
              eapply corestep_plus_one. econstructor; eauto.
constructor; auto.
rewrite H4 in H9. inv H9; auto.

Focus 1. inv H0.
destruct (exec_skips_CC H5 ge f ve te m) as [k2 [? ?]]; auto.
exists (CC_core_State f Sskip k2 ve (PTree.set id v te)); split.
  eapply corestep_star_plus_trans. eassumption. apply corestep_plus_one. econstructor; eauto.
  rewrite H0 in H5. inv H5; constructor; auto.

Focus 1. inv H7.
 destruct (exec_skips_CC H12 ge f0 ve te m) as [k2 [? ?]]; auto.
 rewrite H7 in *. inv H12. simpl in CUR.
  exists (CC_core_State f (fn_body f) (CC.Kcall optid f0 ve te k2) ve' le').
  split.
eapply corestep_star_plus_trans. apply H8.
               apply corestep_plus_two with (c':=CC_core_Callstate (Internal f) vargs (CC.Kcall optid f0 ve te k2))(m':=m).
                     simpl. econstructor; eauto.
              econstructor; eauto.
simpl. apply list_norepet_app in H4; destruct H4 as [? [? ?]].
             econstructor; eauto. econstructor; eauto.
             apply match_cont_strip. simpl. constructor; auto.

Focus 1. inv H3.
 destruct (exec_skips_CC H8 ge f ve te m) as [k2 [? ?]]; auto.
 rewrite H3 in *. inv H8. simpl in CUR.
  exists (CC_core_Callstate (External ef tyargs tyres) vargs (CC.Kcall optid f ve te k2)).
  split.
eapply corestep_star_plus_trans. eassumption. eapply corestep_plus_one. econstructor; eauto.
econstructor; eauto.

Focus 1.  inv H0.
 destruct (exec_skips_CC H5 ge f ve te m) as [k2 [? ?]]; auto.
 rewrite H0 in *. inv H5.
 destruct (IHcl_step (CC_core_State f s1 (CC.Kseq s2 k2) ve te))
                as [st2 [? ?]]; clear IHcl_step.
 repeat constructor; auto.
 apply match_cont_strip. apply match_cont_strip. auto.
 exists st2; split; auto.
 eapply corestep_star_plus_trans; [ eassumption | ]. simpl.
 apply corestep_plus_trans with (c2:=CC_core_State f s1 (CC.Kseq s2 k2) ve te)(m2:=m).
              apply corestep_plus_one. simpl. econstructor. eassumption.

 Focus 1.  inv H0.
 simpl strip_skip in H5.
 remember (strip_skip k) as k0.
 destruct k0.
 elimtype False; clear - H Heqk0.
 revert H; induction k; intros. inv H.
 forget (a::k) as k'; clear - Heqk0 H.
 remember (State ve te k') as s.
 revert ve te k' Heqs Heqk0; induction H; intros; inv Heqs; simpl in *; try congruence.
 eapply IHcl_step. reflexivity. auto.
 remember (strip_skip' (CC.Kseq s k')) as k0'.
 destruct k0'; inv H5;
  try solve [rewrite <- strip_step in H; rewrite <- Heqk0 in H; inv H].
 assert (s0<>Sskip).
 clear- Heqk0; intro; subst.
 revert Heqk0; induction k; simpl; intros. inv Heqk0. destruct a; try solve [inv Heqk0]; auto. destruct s; inv Heqk0; auto.
 destruct (IHcl_step (CC_core_State f s k' ve te))
                 as [st2 [? ?]]; clear IHcl_step.
 constructor; auto. rewrite <- Heqk0. rewrite <- Heqk0'.
 constructor 2; auto.
 exists st2; split; auto.

  destruct (IHcl_step (CC_core_State f Sskip (CC.Kloop1 s0 s1 k0') ve te))
                      as [st2 [? ?]]; clear IHcl_step.
 constructor; auto. simpl. rewrite <- Heqk0. constructor. auto.
  exists st2; split; auto.
  apply corestep_plus_split in H0. destruct H0 as [cc [mm [Hstep Hstar]]].
      eapply corestep_plus_star_trans; try apply Hstar.
          clear - Hstep Heqk0'.
             destruct s; inv Heqk0'.
             eapply corestep_star_plus_trans.
                    apply (strip_skip'_loop1_CC _ _ _ _ _ _ _ _ _ H0).
                    eapply corestep_plus_one. apply Hstep.

 destruct (IHcl_step (CC_core_State f Sskip (CC.Kloop2 s0 s1 k0') ve te))
                      as [st2 [? ?]]; clear IHcl_step.
 destruct (dec_skip s). subst.
 econstructor; eauto. rewrite <- Heqk0. constructor. auto.
 rewrite strip_skip'_not in Heqk0' by auto. inv Heqk0'.
  exists st2; split; auto.
  destruct s; inv Heqk0'.
  eapply corestep_star_plus_trans; try apply H0.
  clear - H4; revert H4; induction k'; intros; inv H4.
  destruct (dec_skip s). subst.
  specialize (IHk' H0).
       eapply corestep_star_trans; try apply IHk'. apply corestep_star_one. constructor.
 replace (CC.Kloop2 s0 s1 k0') with (CC.Kseq s k') by (destruct s; auto; congruence).
    apply corestep_star_zero.
 apply corestep_star_zero.

 destruct s; inv Heqk0'.
 destruct (IHcl_step (CC_core_State f Sskip (CC.Kcall o f0 e t k0') ve te))
                      as [st2 [? ?]]; clear IHcl_step.
 constructor; auto. rewrite <- Heqk0. constructor; auto.
  exists st2; split; auto.
  apply corestep_plus_split in H0. destruct H0 as [cc [mm [Hstep Hstar]]].
      eapply corestep_plus_star_trans; try apply Hstar.
          clear - Hstep H2.
             eapply corestep_star_plus_trans.
                    eapply (strip_skip'_call_CC _ _ _ _ _ _ _ _ _ _ _ H2); try apply Hstep.
                    eapply corestep_plus_one. apply Hstep.

 Focus 1.  inv H0.
 simpl strip_skip in H5.
 inv H5.
 Focus 1.  change (CC.Kseq Scontinue k'0 = strip_skip' (CC.Kseq s k')) in H3.
 symmetry in H3.
 rewrite continue_cont_skip in *.
 simpl in CUR.
 rewrite <- current_function_strip in CUR.
 forget (strip_skip k) as k0. clear k. rename k0 into k.

 generalize (continue_cont_is k); case_eq (continue_cont k); intros; try contradiction.
 rewrite H0 in H; inv H.
 destruct c; try contradiction. destruct l; try contradiction. destruct c; try contradiction.
 subst s0.

 assert (X1: corestep_star CC_core_sem ge (CC_core_State f s k' ve te) m
                             (CC_core_State f Scontinue k'0 ve te) m).
     clear - H3.
     destruct (dec_skip s).
subst. simpl in H3.
           eapply exec_skips'_CC; auto.
           rewrite strip_skip'_not in H3 by auto. inv H3. simpl. apply corestep_star_zero.
 assert (X2: corestep_star CC_core_sem ge (CC_core_State f Scontinue k'0 ve te) m
                                       (CC_core_State f Scontinue (strip_skip' k'0) ve te) m).
      clear.
      induction k'0; try solve [apply corestep_star_zero].
      destruct (dec_skip s).
subst. simpl in *.
                            eapply corestep_star_trans; try apply IHk'0. clear IHk'0.
                            apply corestep_star_one. constructor.
           rewrite strip_skip'_not; auto. apply corestep_star_zero.
 generalize (corestep_star_trans _ _ _ _ _ _ _ _ X1 X2); clear X1 X2; intro.
 clear H3.
 forget (strip_skip' k'0) as k0'; clear k'0.
 assert (precontinue_cont k = Kloop1 s1 s2 :: l).
 revert H0; clear; induction k; simpl; try congruence. destruct a; try congruence; auto.
 assert (exists k1',
               corestep_star CC_core_sem ge (CC_core_State f Scontinue k0' ve te) m
                    (CC_core_State f Scontinue k1' ve te) m /\
               match_cont (Kseq Scontinue :: Kloop1 s1 s2 :: l) k1').
     clear - H1 H0.
     revert H0; induction H1; simpl; intros; try congruence.
        destruct IHmatch_cont as [k1' [? ?]].
           rewrite <- continue_cont_skip; auto.
        econstructor. split; [ | eassumption].
           eapply corestep_star_trans; try apply H.
             clear.
             eapply corestep_star_trans.
                 eapply corestep_star_one. apply step_continue_seq_CC.
                 apply step_continue_strip_CC.
      inv H0. econstructor; split. apply corestep_star_zero. constructor. auto.
      destruct IHmatch_cont as [k1' [? ?]].
          rewrite <- continue_cont_skip; auto.
          econstructor. split; [ | eassumption].
             eapply corestep_star_trans; try apply H.
              eapply corestep_star_trans.
                 eapply corestep_star_one. apply step_continue_switch_CC.
                 apply step_continue_strip_CC.
 destruct H4 as [k1' [StepStar Mtch]].
 generalize (corestep_star_trans _ _ _ _ _ _ _ _ H2 StepStar); clear H2 StepStar; intro H2.
 rewrite H0 in *.
 assert (CUR': current_function l = Some f).
   clear - CUR H0. revert CUR H0; induction k; simpl; intros. inv CUR.
   destruct a; try discriminate; auto. inv H0. auto.
 clear H1 CUR k H0 H3.
 inv Mtch.
     inv H4. simpl in *.
    destruct (IHcl_step (CC_core_State f s2 (CC.Kloop2 s1 s2 k'0) ve te))
                      as [st2 [? ?]]; clear IHcl_step.
    constructor; auto. apply match_cont_strip. constructor. auto.
    exists st2; split; auto.
    eapply corestep_star_plus_trans; [apply H2 | ].
    eapply corestep_star_plus_trans; [ | apply H0].
    eapply corestep_star_one. constructor. auto.

Focus 1.
   change (CC.Kloop1 s0 e3 k'0 = strip_skip' (CC.Kseq s k')) in H1.
 destruct (dec_skip s); [ | destruct s; try congruence; inv H1].
 subst s.
 simpl in H.
 simpl in H1.
 simpl in *.
 assert (X1: corestep_star CC_core_sem ge (CC_core_State f Sskip k' ve te) m
                   (CC_core_State f Sskip (CC.Kloop1 s0 e3 k'0) ve te) m).
     rewrite H1; clear.
     induction k'; intros; try solve [apply corestep_star_zero].
     destruct (dec_skip s).
subst. simpl in *. eapply corestep_star_trans; try apply IHk'.
                                        apply corestep_star_one. simpl. econstructor.
rewrite strip_skip'_not; auto. apply corestep_star_zero.
 forget (CC_core_State f Sskip k' ve te) as st1.
 clear k' H1.
 assert (X2: corestep_star CC_core_sem ge st1
                  m (CC_core_State f e3 (CC.Kloop2 s0 e3 k'0) ve te) m).
     eapply corestep_star_trans; try apply X1.
     eapply corestep_star_one. constructor. auto.
 clear X1.
 destruct (IHcl_step (CC_core_State f e3 (CC.Kloop2 s0 e3 k'0) ve te))
                      as [st2 [? ?]]; clear IHcl_step.
 constructor; auto. apply match_cont_strip; constructor; auto.
 exists st2; split; auto.
 eapply corestep_star_plus_trans; eauto.

 Focus 1.
 inv H0. simpl strip_skip in H5.
 destruct (dec_skip s).
      subst. simpl strip_skip' in *.
      assert (exists k1', strip_skip' k' = CC.Kseq Sbreak k1').
           revert H5; clear. remember (strip_skip' k') as k0'.
           revert k' Heqk0'; induction k0'; intros; try solve [inv H5].
           inv H5. eauto.
      destruct H0 as [k1' H0].
      assert (X: corestep_star CC_core_sem ge (CC_core_State f Sskip k' ve te) m
                           (CC_core_State f Sbreak k1' ve te) m).
          revert k1' H0; clear; induction k'; intros; try solve [inv H0].
          destruct (dec_skip s).
subst. simpl in *. specialize (IHk' _ H0).
                  eapply corestep_star_trans; try apply IHk'. apply corestep_star_one. constructor.
rewrite strip_skip'_not in H0 by auto. inv H0.
                          apply corestep_star_one. constructor.
      simpl.
      forget (CC_core_State f Sskip k' ve te) as st1.
      rewrite H0 in *.
      clear k' H0.
      inv H5.
      rewrite <- break_cont_skip in *.
      simpl in CUR. rewrite <- current_function_strip in CUR.
      forget (strip_skip k) as k0.
      assert (Y: corestep_star CC_core_sem ge st1 m (CC_core_State f Sbreak (strip_skip' k1') ve te) m).
          eapply corestep_star_trans; try apply X; auto.
          clear.
          induction k1'; try destruct s; try solve [apply corestep_star_zero].
          simpl. eapply corestep_star_trans; eauto. apply corestep_star_one. constructor.
      forget (strip_skip' k1') as k0'. clear k1' X.

      assert (X: exists k1',
             corestep_plus CC_core_sem ge (CC_core_State f Sbreak k0' ve te) m
                       (CC_core_State f Sskip k1' ve te) m
             /\ match_cont (strip_skip (break_cont k0)) (strip_skip' k1')).
          clear - H H1.
          revert H; induction H1; intros; try solve [inv H].
              rewrite break_cont_skip in *. simpl in H.
              destruct (IHmatch_cont H) as [k1' [? ?]]; clear IHmatch_cont. simpl.
              exists k1'; split; auto.
              eapply corestep_star_plus_trans; try eassumption.
                   eapply corestep_star_trans with (c2:=CC_core_State f Sbreak k' ve te)(m2:=m).
                        apply corestep_star_one. simpl. constructor.
                        apply break_strip_CC.
simpl in *. exists k'; split.
               apply corestep_plus_one. simpl. eapply CC.step_break_loop1.
                auto.
simpl in *. exists k'; split.
                eapply corestep_plus_one. simpl. eapply CC.step_skip_break_switch. auto.
                assumption.
       destruct X as [k1' [? ?]].
       destruct (IHcl_step (CC_core_State f Sskip k1' ve te))
                      as [st2 [? ?]]; clear IHcl_step.
         constructor; auto.
            clear - H CUR. revert CUR; induction k0; intros. inv CUR.
            destruct a; simpl in *; auto. inv H. inv H.
       exists st2; split; auto.
       eapply corestep_star_plus_trans; try apply Y.
       eapply corestep_plus_trans. apply H0. apply H3.
     rewrite strip_skip'_not in H5 by auto.
     inv H5. clear n.
     admit.
 Focus 1.  inv H1. simpl strip_skip in H6.
 inv H6.
 change (CC.Kseq (Sifthenelse a s1 s2) k'0 = strip_skip' (CC.Kseq s k')) in H4.
 assert (X: corestep_star CC_core_sem ge (CC_core_State f s k' ve te) m (CC_core_State f (Sifthenelse a s1 s2) k'0 ve te) m).
     clear - H4.
     revert H4; induction k'; intros; try solve [ destruct s; inv H4; apply corestep_star_zero].
     destruct (dec_skip s).
subst s.
          destruct (dec_skip s0).
subst s0. simpl in *.
               eapply corestep_star_trans; try apply IHk'; eauto. apply corestep_star_one. constructor.
change (strip_skip' (CC.Kseq Sskip (CC.Kseq s0 k'))) with
               (strip_skip' (CC.Kseq s0 k')) in H4.
               rewrite strip_skip'_not in H4 by auto.
               inv H4. apply corestep_star_one. constructor.
rewrite strip_skip'_not in * by auto.
          inv H4. apply corestep_star_zero.
 exists (CC_core_State f (if b then s1 else s2) k'0 ve te); split; auto.
   eapply corestep_star_plus_trans; try apply X.
      apply corestep_plus_one. econstructor; eauto.
 constructor; auto. apply match_cont_strip; auto.

 Focus 1.  inv H0. inv H4.
 change (CC.Kseq (Sloop s1 s2) k'0 = strip_skip' (CC.Kseq s k')) in H2.
  generalize (exec_skips'_CC ge f _ _ _ _ ve te m (@eq_sym _ _ _ H2)); intro.
 exists ( (CC_core_State f s1 (CC.Kloop1 s1 s2 k'0) ve te)); split.
 eapply corestep_star_plus_trans; try apply H.
  apply corestep_plus_one. simpl. eapply CC.step_loop; eauto.
constructor; auto. apply match_cont_strip; constructor; auto.

 Focus 1.   inv H0. inv H4.
 destruct s0; inv H3.
 generalize (strip_skip'_loop2_CC ge f ve te m _ _ _ _ H1); intro.
 exists (CC_core_State f s (CC.Kloop1 s a3 k'0) ve te); split.
 eapply corestep_star_plus_trans; try apply H.
 eapply corestep_plus_star_trans with (c2:=CC_core_State f (Sloop s a3) k'0 ve te)(m2:=m).
 apply corestep_plus_one. simpl. eapply CC.step_skip_loop2; eauto.
 apply corestep_star_one. simpl. eapply CC.step_loop; eauto.
  constructor; auto. apply match_cont_strip. constructor. auto.

 Focus 1.  inv H3.
  remember (strip_skip' (CC.Kseq s k'0)) as k3. simpl in CUR, H8.
 inv H8.
 generalize (exec_skips'_CC ge f0 _ _ _ _ ve te m (@eq_sym _ _ _ H4)); intro H99.
 assert (f0=f).
   simpl in CUR; clear - CUR H.
   revert H CUR; induction k; intros. inv H. simpl in *. destruct a; auto. inv CUR; auto. inv H; auto.
 subst f.
 generalize (match_cont_call_strip k k'1); intro.
 spec H3; [congruence |]. spec H3; [auto |].
 generalize H3; rewrite H; intro.
 inv H5.
elimtype False; clear - H10.
         revert H10; induction k'1; simpl; intros; congruence.
destruct optexp; [destruct H1 as [v [? ?]] | ]; (destruct optid; destruct H2 as [H2 H2'];
               try solve [contradiction H2; auto]; subst te'' );
               try (eapply corestep_star_trans; split; [eapply corestep_star_plus_trans; [ apply H99 | eapply corestep_plus_two ] | ]).
                eexists (CC_core_State f Sskip k'2 ve' (PTree.set i v' te')).
                split.
                     eapply (corestep_star_plus_trans _ _ _ _ _ _ _ _ H99).                           eapply corestep_plus_trans with (c2:=CC_core_Returnstate v' (CC.call_cont k'1))(m2:=m').
                                         eapply corestep_plus_one. simpl. econstructor; eauto.
                                         eapply corestep_plus_one. simpl. rewrite <- H13. eapply CC.step_returnstate.
                    constructor; auto.
                eexists (CC_core_State f Sskip k'2 ve' te').
                split.
                     eapply (corestep_star_plus_trans _ _ _ _ _ _ _ _ H99).                           eapply corestep_plus_trans with (c2:=CC_core_Returnstate v' (CC.call_cont k'1))(m2:=m').
                                         eapply corestep_plus_one. simpl. econstructor; eauto.
                                         eapply corestep_plus_one. simpl. rewrite <- H13. eapply CC.step_returnstate.
                    constructor; auto.
                eexists (CC_core_State f Sskip k'2 ve' te').
                split.
                     eapply (corestep_star_plus_trans _ _ _ _ _ _ _ _ H99).                           eapply corestep_plus_trans with (c2:=CC_core_Returnstate Vundef (CC.call_cont k'1))(m2:=m').
                                         eapply corestep_plus_one. simpl. econstructor; eauto.
                                         eapply corestep_plus_one. simpl. rewrite <- H13. eapply CC.step_returnstate.
                    constructor; auto.

 destruct optid. destruct H2. congruence.
 destruct H2; subst te''.
 simpl in H. inv H. simpl in CUR. symmetry in CUR; inv CUR.
 destruct s; inv H4.
 assert (corestep_star CC_core_sem ge (CC_core_State f Sskip k'0 ve te) m
                         (CC_core_State f Sskip (CC.Kcall None f1 ve' te' k'1) ve te) m).
     clear H1; rename H3 into H1.
     clear - H1.
     revert H1; induction k'0; intros; try solve [inv H1].
           destruct (dec_skip s).
subst s. simpl in H1.
               eapply corestep_star_trans; try apply IHk'0; auto. apply corestep_star_one. constructor; auto.
              rewrite strip_skip'_not in H1 by auto. rewrite <- H1. apply corestep_star_zero.
          simpl in H1. inv H1. apply corestep_star_zero.
 eexists (CC_core_State f1 Sskip k'1 ve' te').
     split. eapply corestep_star_plus_trans. apply H. clear H.
              eapply corestep_plus_trans with (c2:=CC_core_Returnstate Vundef (CC.Kcall None f1 ve' te' k'1))(m2:=m').
                  eapply corestep_plus_one. simpl. eapply CC.step_skip_call; simpl; eauto.
                  eapply corestep_plus_one. simpl. econstructor; eauto.
     econstructor; eauto.

 Focus 1.  inv H0. simpl strip_skip in H5.
 remember (CC.Kseq s k') as k0'.
 inv H5.
 evar (c2': CC_core).
 exists c2'; split.
     Focus 2. constructor; eauto. apply match_cont_strip. simpl.
                    instantiate (1:= CC.Kswitch k'0). constructor. auto.
     generalize (exec_skips'_CC ge f _ _ _ _ ve te m (@eq_sym _ _ _ H3)); intro H99.
        eapply corestep_star_plus_trans; try apply H99.
        unfold c2'. apply corestep_plus_one. simpl. constructor; auto.

 Focus 1.  inv H0. remember (CC.Kseq s0 k') as k0'. inv H5.
 destruct (IHcl_step (CC_core_State f s k'0 ve te)) as [st2 [? ?]]; clear IHcl_step.
 constructor; auto. apply match_cont_strip. auto.
 exists st2; split; auto.
   eapply corestep_star_plus_trans; try eassumption.
   generalize (exec_skips'_CC ge f _ _ _ _ ve te m (@eq_sym _ _ _ H3)); intro H99.
     eapply corestep_star_trans; try apply H99.
     apply corestep_star_one. constructor.

 Focus 1.  inv H0. remember (CC.Kseq s k'0) as k0'. inv H5.
  generalize (match_cont_call_strip k k'1); intro.
 spec H0.
 clear - CUR. apply (call_cont_nonnil _ _ CUR).
 specialize (H0 H1).
  rewrite <- strip_call' in H0.
 change (Kseq (Sreturn None) :: call_cont k) with (strip_skip (Kseq (Sreturn None) :: call_cont k)) in H0.
 destruct (match_find_label _ _ _ _ _ H0 H) as [s2 [k2' [? ?]]].
 exists (CC_core_State f s2 k2' ve te); split.
    simpl in CUR0. inversion2 CUR CUR0.
     generalize (exec_skips'_CC ge f _ _ _ _ ve te m (@eq_sym _ _ _ H3)); intro H99.
     eapply corestep_star_plus_trans; try apply H99.
         apply corestep_plus_one. constructor; auto.
         constructor; auto.
   clear - CUR H. forget (fn_body f) as s.
       rewrite <- current_function_call_cont in CUR.
       change (current_function (Kseq (Sreturn None) :: call_cont k) = Some f) in CUR.
        forget (Kseq (Sreturn None) :: call_cont k) as k0. clear - CUR H.
        eapply current_function_find_label; eauto.
 apply match_cont_strip1. auto.
Qed.

Definition MS (_:corestate)(c: corestate) (C: CC_core): Prop := match_states c C.

Lemma Clightnew_Clight_sim_eq: forall p ExternIdents entrypoints
               (ext_ok : CompilerCorrectness.entryPts_ok p p ExternIdents entrypoints)
,
              Forward_simulation_eq.Forward_simulation_equals _ _ _ cl_core_sem CC_core_sem (Genv.globalenv p) (Genv.globalenv p) entrypoints.
Proof.
  intros.
  pose (bogus_measure := (fun x: corestate => O)).
  eapply eq_simulation_plus with (match_cores:=MS); try apply bogus_measure; unfold MS.
      intros. unfold cl_core_sem, CC_core_sem; simpl.
      unfold cl_initial_core, CC_initial_core; simpl.
     eexists. eexists. split. reflexivity. split. reflexivity.
       assert (v1=v2). unfold CompilerCorrectness.entryPts_ok in ext_ok. admit.        subst.
       econstructor. simpl. admit.
       simpl. assert (myStatement = Sskip). admit.
          rewrite H1. econstructor. simpl. constructor. simpl. constructor.
      intros. unfold cl_core_sem in H0. simpl in H0. unfold cl_safely_halted in H0. inv H0.
     intros. inv H. simpl in *. inv H2. simpl in *. inv H0.
          split. unfold CC_at_external. destruct tyres;auto.
          admit.          intros. inv H; simpl in *.
          admit. admit.
  Qed.

Require Import sepcomp.forward_simulations.

Theorem Clightnew_Clight_sim: forall p ExternIdents entrypoints
         (ext_ok: CompilerCorrectness.entryPts_ok p p ExternIdents entrypoints)
        (IniHyp: forall x, Genv.init_mem p = Some x <-> initial_mem CC_core_sem (Genv.globalenv p) x p.(prog_defs)),
        CompilerCorrectness.core_correctness
             (fun F C V Sem P => (forall x, Genv.init_mem P = Some x <-> initial_mem Sem (Genv.globalenv P) x P.(prog_defs)))
              ExternIdents _ _ _ _ _ _ cl_core_sem CC_core_sem p p.
Proof.
intros.
econstructor.
  simpl. intros. exists m1; auto.
  apply ext_ok.
  eapply Clightnew_Clight_sim_eq; eauto.
  trivial.
  unfold CompilerCorrectness.GenvHyp; auto.
  apply IniHyp.
  apply IniHyp.
Qed.