diff options
author | xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e> | 2009-08-03 15:32:27 +0000 |
---|---|---|
committer | xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e> | 2009-08-03 15:32:27 +0000 |
commit | 213bf38509f4f92545d4c5749c25a55b9a9dda36 (patch) | |
tree | a40df8011ab5fabb0de362befc53e7af164c70ae /cfrontend/Cshmgenproof3.v | |
parent | 88b98f00facde51bff705a3fb6c32a73937428cb (diff) | |
download | compcert-213bf38509f4f92545d4c5749c25a55b9a9dda36.tar.gz compcert-213bf38509f4f92545d4c5749c25a55b9a9dda36.zip |
Transition semantics for Clight and Csharpminor
git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@1119 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e
Diffstat (limited to 'cfrontend/Cshmgenproof3.v')
-rw-r--r-- | cfrontend/Cshmgenproof3.v | 1921 |
1 files changed, 869 insertions, 1052 deletions
diff --git a/cfrontend/Cshmgenproof3.v b/cfrontend/Cshmgenproof3.v index af6dc90a..92a09562 100644 --- a/cfrontend/Cshmgenproof3.v +++ b/cfrontend/Cshmgenproof3.v @@ -41,6 +41,8 @@ Hypothesis TRANSL: transl_program prog = OK tprog. Let ge := Genv.globalenv prog. Let tge := Genv.globalenv tprog. +Let tgvare : gvarenv := global_var_env tprog. +Let tgve := (tge, tgvare). Lemma symbols_preserved: forall s, Genv.find_symbol tge s = Genv.find_symbol ge s. @@ -80,6 +82,17 @@ Proof. assumption. Qed. +Lemma sig_translated: + forall fd tfd targs tres, + classify_fun (type_of_fundef fd) = fun_case_f targs tres -> + transl_fundef fd = OK tfd -> + funsig tfd = signature_of_type targs tres. +Proof. + intros. destruct fd; monadInv H0; inv H. + monadInv EQ. simpl. auto. + simpl. auto. +Qed. + (** * Matching between environments *) (** In this section, we define a matching relation between @@ -95,9 +108,15 @@ Definition match_var_kind (ty: type) (vk: var_kind) : Prop := Record match_env (tyenv: typenv) (e: Csem.env) (te: Csharpminor.env) : Prop := mk_match_env { me_local: - forall id b ty, - e!id = Some b -> tyenv!id = Some ty -> - exists vk, match_var_kind ty vk /\ te!id = Some (b, vk); + forall id b, + e!id = Some b -> + exists vk, exists ty, + tyenv!id = Some ty + /\ match_var_kind ty vk + /\ te!id = Some (b, vk); + me_local_inv: + forall id b vk, + te!id = Some (b, vk) -> e!id = Some b; me_global: forall id ty, e!id = None -> tyenv!id = Some ty -> @@ -105,6 +124,66 @@ Record match_env (tyenv: typenv) (e: Csem.env) (te: Csharpminor.env) : Prop := (forall chunk, access_mode ty = By_value chunk -> (global_var_env tprog)!id = Some (Vscalar chunk)) }. + +Lemma match_env_same_blocks: + forall tyenv e te, + match_env tyenv e te -> + forall b, In b (Csem.blocks_of_env e) <-> In b (blocks_of_env te). +Proof. + intros. inv H. + unfold Csem.blocks_of_env, blocks_of_env. + set (f := (fun id_b_lv : positive * (block * var_kind) => + let (_, y) := id_b_lv in let (b0, _) := y in b0)). + split; intros. + exploit list_in_map_inv; eauto. intros [[id b'] [A B]]. + simpl in A; subst b'. + exploit (me_local0 id b). apply PTree.elements_complete; auto. + intros [vk [ty [C [D E]]]]. + change b with (f (id, (b, vk))). + apply List.in_map. apply PTree.elements_correct. auto. + exploit list_in_map_inv; eauto. intros [[id [b' vk]] [A B]]. + simpl in A; subst b'. + exploit (me_local_inv0 id b vk). apply PTree.elements_complete; auto. + intro. + change b with (snd (id, b)). + apply List.in_map. apply PTree.elements_correct. auto. +Qed. + +Remark free_list_charact: + forall l m, + free_list m l = + mkmem (fun b => if In_dec eq_block b l then empty_block 0 0 else m.(blocks) b) + m.(nextblock) + m.(nextblock_pos). +Proof. + induction l; intros; simpl. + destruct m; simpl. decEq. apply extensionality. auto. + rewrite IHl. unfold free; simpl. decEq. apply extensionality; intro b. + unfold update. destruct (eq_block a b). + subst b. apply zeq_true. + rewrite zeq_false; auto. + destruct (In_dec eq_block b l); auto. +Qed. + +Lemma mem_free_list_same: + forall m l1 l2, + (forall b, In b l1 <-> In b l2) -> + free_list m l1 = free_list m l2. +Proof. + intros. repeat rewrite free_list_charact. decEq. apply extensionality; intro b. + destruct (In_dec eq_block b l1); destruct (In_dec eq_block b l2); auto. + rewrite H in i. contradiction. + rewrite <- H in i. contradiction. +Qed. + +Lemma match_env_free_blocks: + forall tyenv e te m, + match_env tyenv e te -> + Mem.free_list m (Csem.blocks_of_env e) = Mem.free_list m (blocks_of_env te). +Proof. + intros. apply mem_free_list_same. intros; eapply match_env_same_blocks; eauto. +Qed. + Definition match_globalenv (tyenv: typenv) (gv: gvarenv): Prop := forall id ty chunk, tyenv!id = Some ty -> access_mode ty = By_value chunk -> @@ -117,7 +196,8 @@ Lemma match_globalenv_match_env_empty: Proof. intros. unfold Csem.empty_env, Csharpminor.empty_env. constructor. - intros until ty. repeat rewrite PTree.gempty. congruence. + intros until b. repeat rewrite PTree.gempty. congruence. + intros until vk. rewrite PTree.gempty. congruence. intros. split. apply PTree.gempty. intros. red in H. eauto. @@ -136,13 +216,13 @@ Qed. local variables and initialization of the parameters. *) Lemma match_env_alloc_variables: - forall e1 m1 vars e2 m2 lb, - Csem.alloc_variables e1 m1 vars e2 m2 lb -> + forall e1 m1 vars e2 m2, + Csem.alloc_variables e1 m1 vars e2 m2 -> forall tyenv te1 tvars, match_env tyenv e1 te1 -> transl_vars vars = OK tvars -> exists te2, - Csharpminor.alloc_variables te1 m1 tvars te2 m2 lb + Csharpminor.alloc_variables te1 m1 tvars te2 m2 /\ match_env (Ctyping.add_vars tyenv vars) e2 te2. Proof. induction 1; intros. @@ -156,10 +236,14 @@ Proof. assert (match_env (add_var tyenv (id, ty)) (PTree.set id b1 e) te2). inversion H1. unfold te2, add_var. constructor. (* me_local *) - intros until ty0. repeat rewrite PTree.gsspec. simpl. destruct (peq id0 id); intros. - subst id0. exists vk; split. - apply match_var_kind_of_type. congruence. congruence. + intros until b. simpl. repeat rewrite PTree.gsspec. + destruct (peq id0 id); intros. + inv H3. exists vk; exists ty; intuition. + apply match_var_kind_of_type. congruence. auto. + (* me_local_inv *) + intros until vk0. repeat rewrite PTree.gsspec. + destruct (peq id0 id); intros. congruence. eauto. (* me_global *) intros until ty0. repeat rewrite PTree.gsspec. simpl. destruct (peq id0 id); intros. discriminate. @@ -167,7 +251,7 @@ Proof. destruct (IHalloc_variables _ _ _ H3 TVARS) as [te3 [ALLOC MENV]]. exists te3; split. econstructor; eauto. - rewrite (sizeof_var_kind_of_type _ _ VK). auto. + rewrite (sizeof_var_kind_of_type _ _ VK). eauto. auto. Qed. @@ -192,8 +276,9 @@ Proof. unfold store_value_of_type in H0. rewrite H4 in H0. apply bind_parameters_cons with b m1. assert (tyenv!id = Some ty). apply H2. apply in_eq. - destruct (me_local _ _ _ H3 _ _ _ H H5) as [vk [A B]]. - red in A; rewrite H4 in A. congruence. + destruct (me_local _ _ _ H3 _ _ H) as [vk [ty' [A [B C]]]]. + assert (ty' = ty) by congruence. subst ty'. + red in B; rewrite H4 in B. congruence. assumption. apply IHbind_parameters with tyenv; auto. intros. apply H2. apply in_cons; auto. @@ -326,7 +411,7 @@ Lemma var_get_correct: wt_expr tyenv (Expr (Csyntax.Evar id) ty) -> var_get id ty = OK code -> match_env tyenv e te -> - eval_expr tprog te m code v. + eval_expr tgve te m code v. Proof. intros. inversion H1; subst; clear H1. unfold load_value_of_type in H0. @@ -337,8 +422,9 @@ Proof. inversion H2; clear H2; subst. inversion H; subst; clear H. (* local variable *) - exploit me_local; eauto. intros [vk [A B]]. - red in A; rewrite ACC in A. + exploit me_local; eauto. intros [vk [ty' [A [B C]]]]. + assert (ty' = ty) by congruence. subst ty'. + red in B; rewrite ACC in B. subst vk. eapply eval_Evar. eapply eval_var_ref_local. eauto. assumption. @@ -354,7 +440,7 @@ Proof. inversion H2; clear H2; subst. inversion H; subst; clear H. (* local variable *) - exploit me_local; eauto. intros [vk [A B]]. + exploit me_local; eauto. intros [vk [ty' [A [B C]]]]. eapply eval_Eaddrof. eapply eval_var_addr_local. eauto. (* global variable *) @@ -369,14 +455,14 @@ Qed. (** Correctness of the code generated by [var_set]. *) Lemma var_set_correct: - forall e m id ty loc ofs v m' tyenv code te rhs, + forall e m id ty loc ofs v m' tyenv code te rhs f k, Csem.eval_lvalue ge e m (Expr (Csyntax.Evar id) ty) loc ofs -> store_value_of_type ty m loc ofs v = Some m' -> wt_expr tyenv (Expr (Csyntax.Evar id) ty) -> var_set id ty rhs = OK code -> match_env tyenv e te -> - eval_expr tprog te m rhs v -> - exec_stmt tprog te m code E0 m' Out_normal. + eval_expr tgve te m rhs v -> + step tgve (State f code k te m) E0 (State f Sskip k te m'). Proof. intros. inversion H1; subst; clear H1. unfold store_value_of_type in H0. @@ -387,15 +473,16 @@ Proof. inversion H2; clear H2; subst. inversion H; subst; clear H. (* local variable *) - exploit me_local; eauto. intros [vk [A B]]. - red in A; rewrite ACC in A; subst vk. - eapply exec_Sassign. eauto. + exploit me_local; eauto. intros [vk [ty' [A [B C]]]]. + assert (ty' = ty) by congruence. subst ty'. + red in B; rewrite ACC in B; subst vk. + eapply step_assign. eauto. econstructor. eapply eval_var_ref_local. eauto. assumption. (* global variable *) exploit me_global; eauto. intros [A B]. - eapply exec_Sassign. eauto. - econstructor. eapply eval_var_ref_global. auto. - fold tge. rewrite symbols_preserved. eauto. + eapply step_assign. eauto. + econstructor. eapply eval_var_ref_global. auto. + change (fst tgve) with tge. rewrite symbols_preserved. eauto. eauto. assumption. (* access mode By_reference *) intros ACC. rewrite ACC in H0. discriminate. @@ -403,35 +490,59 @@ Proof. intros. rewrite H1 in H0; discriminate. Qed. -Lemma call_dest_set_correct: - forall e m0 lhs loc ofs m1 v m2 tyenv optid te, - Csem.eval_lvalue ge e m0 lhs loc ofs -> - store_value_of_type (typeof lhs) m1 loc ofs v = Some m2 -> +Lemma call_dest_correct: + forall e m lhs loc ofs tyenv optid te, + Csem.eval_lvalue ge e m lhs loc ofs -> wt_expr tyenv lhs -> transl_lhs_call (Some lhs) = OK optid -> match_env tyenv e te -> - exec_opt_assign tprog te m1 optid v m2. -Proof. - intros. generalize H2. simpl. caseEq (is_variable lhs). 2: congruence. - intros. inv H5. - exploit is_variable_correct; eauto. intro. - rewrite H5 in H. rewrite H5 in H1. inversion H1. subst i ty. - constructor. - generalize H0. unfold store_value_of_type. - caseEq (access_mode (typeof lhs)); intros; try discriminate. - (* access mode By_value *) - inversion H. - (* local variable *) + exists id, + optid = Some id + /\ tyenv!id = Some (typeof lhs) + /\ ofs = Int.zero + /\ match access_mode (typeof lhs) with + | By_value chunk => eval_var_ref tgve te id loc chunk + | _ => True + end. +Proof. + intros. generalize H1. simpl. caseEq (is_variable lhs); try congruence. + intros id ISV EQ. inv EQ. + exploit is_variable_correct; eauto. intro EQ. + rewrite EQ in H0. inversion H0. subst id0 ty. + exists id. split; auto. split. rewrite EQ in H0. inversion H0. auto. + rewrite EQ in H. inversion H. +(* local variable *) + split. auto. subst id0 ty l ofs. exploit me_local; eauto. - intros [vk [A B]]. red in A. rewrite H6 in A. subst vk. - econstructor. eapply eval_var_ref_local; eauto. assumption. - (* global variable *) - subst id0 ty l ofs. exploit me_global; eauto. - intros [A B]. - econstructor. eapply eval_var_ref_global; eauto. - rewrite symbols_preserved. eauto. assumption. + intros [vk [ty [A [B C]]]]. + assert (ty = typeof lhs) by congruence. rewrite <- H3. + generalize B; unfold match_var_kind. destruct (access_mode ty); auto. + intros. subst vk. apply eval_var_ref_local; auto. +(* global variable *) + split. auto. + subst id0 ty l ofs. exploit me_global; eauto. intros [A B]. + case_eq (access_mode (typeof lhs)); intros; auto. + apply eval_var_ref_global; auto. + simpl. rewrite <- H9. apply symbols_preserved. +Qed. + +Lemma set_call_dest_correct: + forall ty m loc v m' tyenv e te id, + store_value_of_type ty m loc Int.zero v = Some m' -> + match access_mode ty with + | By_value chunk => eval_var_ref tgve te id loc chunk + | _ => True + end -> + match_env tyenv e te -> + tyenv!id = Some ty -> + exec_opt_assign tgve te m (Some id) v m'. +Proof. + intros. generalize H. unfold store_value_of_type. case_eq (access_mode ty); intros; try congruence. + rewrite H3 in H0. + constructor. econstructor. eauto. auto. Qed. + (** * Proof of semantic preservation *) (** ** Semantic preservation for expressions *) @@ -441,7 +552,7 @@ Qed. << e, m, a ------------------- te, m, ta | | - t| |t + | | | | v v e, m, v ------------------- te, m, v @@ -468,19 +579,19 @@ Definition eval_expr_prop (a: Csyntax.expr) (v: val) : Prop := forall ta (WT: wt_expr tyenv a) (TR: transl_expr a = OK ta), - Csharpminor.eval_expr tprog te m ta v. + Csharpminor.eval_expr tgve te m ta v. Definition eval_lvalue_prop (a: Csyntax.expr) (b: block) (ofs: int) : Prop := forall ta (WT: wt_expr tyenv a) (TR: transl_lvalue a = OK ta), - Csharpminor.eval_expr tprog te m ta (Vptr b ofs). + Csharpminor.eval_expr tgve te m ta (Vptr b ofs). Definition eval_exprlist_prop (al: list Csyntax.expr) (vl: list val) : Prop := forall tal (WT: wt_exprlist tyenv al) (TR: transl_exprlist al = OK tal), - Csharpminor.eval_exprlist tprog te m tal vl. + Csharpminor.eval_exprlist tgve te m tal vl. (* Check (eval_expr_ind2 ge e m eval_expr_prop eval_lvalue_prop). *) @@ -687,7 +798,8 @@ Lemma transl_Evar_local_correct: eval_lvalue_prop (Expr (Csyntax.Evar id) ty) l Int.zero. Proof. intros; red; intros. inversion WT; clear WT; subst. monadInv TR. - exploit (me_local _ _ _ MENV); eauto. intros [vk [A B]]. + exploit (me_local _ _ _ MENV); eauto. + intros [vk [ty' [A [B C]]]]. econstructor. eapply eval_var_addr_local. eauto. Qed. @@ -805,1068 +917,773 @@ Qed. End EXPR. -(** ** Semantic preservation for statements *) - -(** The simulation diagrams for terminating statements and function - calls are of the following form: - relies on simulation diagrams of the following form: -<< - e, m1, s ------------------- te, m1, ts - | | - t| |t - | | - v v - e, m2, out ----------------- te, m2, tout ->> - Left: execution of statement [s] in Clight. - Right: execution of its translation [ts] in Csharpminor. - Top (precondition): matching between environments [e], [te], - plus well-typedness of statement [s]. - Bottom (postcondition): the outcomes [out] and [tout] are - related per the following function [transl_outcome]. -*) - -Definition transl_outcome (nbrk ncnt: nat) (out: Csem.outcome): Csharpminor.outcome := - match out with - | Csem.Out_normal => Csharpminor.Out_normal - | Csem.Out_break => Csharpminor.Out_exit nbrk - | Csem.Out_continue => Csharpminor.Out_exit ncnt - | Csem.Out_return vopt => Csharpminor.Out_return vopt - end. - -Definition exec_stmt_prop - (e: Csem.env) (m1: mem) (s: Csyntax.statement) (t: trace) - (m2: mem) (out: Csem.outcome) : Prop := - forall tyenv nbrk ncnt ts te - (WT: wt_stmt tyenv s) - (TR: transl_statement nbrk ncnt s = OK ts) - (MENV: match_env tyenv e te), - Csharpminor.exec_stmt tprog te m1 ts t m2 (transl_outcome nbrk ncnt out). - -Definition exec_lblstmts_prop - (e: Csem.env) (m1: mem) (s: Csyntax.labeled_statements) - (t: trace) (m2: mem) (out: Csem.outcome) : Prop := - forall tyenv nbrk ncnt body ts te m0 t0 - (WT: wt_lblstmts tyenv s) - (TR: transl_lblstmts (lblstmts_length s) - (1 + lblstmts_length s + ncnt) - s body = OK ts) - (MENV: match_env tyenv e te) - (BODY: Csharpminor.exec_stmt tprog te m0 body t0 m1 Out_normal), - Csharpminor.exec_stmt tprog te m0 ts (t0 ** t) m2 - (transl_outcome nbrk ncnt (outcome_switch out)). - -Definition eval_funcall_prop - (m1: mem) (f: Csyntax.fundef) (params: list val) - (t: trace) (m2: mem) (res: val) : Prop := - forall tf - (WT: wt_fundef (global_typenv prog) f) - (TR: transl_fundef f = OK tf), - Csharpminor.eval_funcall tprog m1 tf params t m2 res. - -(* -Type Printing Depth 100. -Check (Csem.eval_funcall_ind3 ge exec_stmt_prop exec_lblstmts_prop eval_funcall_prop). -*) - -Lemma transl_Sskip_correct: - (forall (e : Csem.env) (m : mem), - exec_stmt_prop e m Csyntax.Sskip E0 m Csem.Out_normal). -Proof. - intros; red; intros. monadInv TR. simpl. constructor. -Qed. - -Lemma transl_Sassign_correct: - forall (e : Csem.env) (m : mem) (a1 a2 : Csyntax.expr) (loc : block) - (ofs : int) (v2 : val) (m' : mem), - eval_lvalue ge e m a1 loc ofs -> - Csem.eval_expr ge e m a2 v2 -> - store_value_of_type (typeof a1) m loc ofs v2 = Some m' -> - exec_stmt_prop e m (Csyntax.Sassign a1 a2) E0 m' Csem.Out_normal. -Proof. - intros; red; intros. - inversion WT; subst; clear WT. - simpl in TR. - caseEq (is_variable a1). - (* a = variable id *) - intros id ISVAR. rewrite ISVAR in TR. - generalize (is_variable_correct _ _ ISVAR). intro EQ. - rewrite EQ in H; rewrite EQ in H4. - monadInv TR. - eapply var_set_correct; eauto. - eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto. - (* a is not a variable *) - intro ISVAR; rewrite ISVAR in TR. monadInv TR. - eapply make_store_correct; eauto. - eapply (transl_lvalue_correct _ _ _ _ MENV _ _ _ H); eauto. - eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto. -Qed. - -Lemma transl_Scall_None_correct: - forall (e : Csem.env) (m : mem) (a : Csyntax.expr) - (al : list Csyntax.expr) (vf : val) (vargs : list val) - (f : Csyntax.fundef) (t : trace) (m' : mem) (vres : val), - Csem.eval_expr ge e m a vf -> - Csem.eval_exprlist ge e m al vargs -> - Genv.find_funct ge vf = Some f -> - type_of_fundef f = typeof a -> - Csem.eval_funcall ge m f vargs t m' vres -> - eval_funcall_prop m f vargs t m' vres -> - exec_stmt_prop e m (Csyntax.Scall None a al) t m' Csem.Out_normal. -Proof. - intros; red; intros; simpl. - inv WT. simpl in TR. - caseEq (classify_fun (typeof a)); intros; rewrite H5 in TR; monadInv TR. - exploit functions_translated; eauto. intros [tf [TFIND TFD]]. - econstructor. - eapply (transl_expr_correct _ _ _ _ MENV _ _ H); eauto. - eapply (transl_exprlist_correct _ _ _ _ MENV _ _ H0); eauto. - eauto. - eapply transl_fundef_sig1; eauto. rewrite H2; auto. - eapply H4; eauto. - eapply functions_well_typed; eauto. - constructor. -Qed. - -Lemma transl_Scall_Some_correct: - forall (e : Csem.env) (m : mem) (lhs a : Csyntax.expr) - (al : list Csyntax.expr) (loc : block) (ofs : int) (vf : val) - (vargs : list val) (f : Csyntax.fundef) (t : trace) (m' : mem) - (vres : val) (m'' : mem), - eval_lvalue ge e m lhs loc ofs -> - Csem.eval_expr ge e m a vf -> - Csem.eval_exprlist ge e m al vargs -> - Genv.find_funct ge vf = Some f -> - type_of_fundef f = typeof a -> - Csem.eval_funcall ge m f vargs t m' vres -> - eval_funcall_prop m f vargs t m' vres -> - store_value_of_type (typeof lhs) m' loc ofs vres = Some m'' -> - exec_stmt_prop e m (Csyntax.Scall (Some lhs) a al) t m'' Csem.Out_normal. -Proof. - intros; red; intros; simpl. - inv WT. inv H10. unfold transl_statement in TR. - caseEq (classify_fun (typeof a)); intros; rewrite H7 in TR; monadInv TR. - exploit functions_translated; eauto. intros [tf [TFIND TFD]]. - econstructor. - eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto. - eapply (transl_exprlist_correct _ _ _ _ MENV _ _ H1); eauto. - eauto. - eapply transl_fundef_sig1; eauto. rewrite H3; auto. - eapply H5; eauto. - eapply functions_well_typed; eauto. - eapply call_dest_set_correct; eauto. -Qed. - -Lemma transl_Ssequence_1_correct: - (forall (e : Csem.env) (m : mem) (s1 s2 : statement) (t1 : trace) - (m1 : mem) (t2 : trace) (m2 : mem) (out : Csem.outcome), - Csem.exec_stmt ge e m s1 t1 m1 Csem.Out_normal -> - exec_stmt_prop e m s1 t1 m1 Csem.Out_normal -> - Csem.exec_stmt ge e m1 s2 t2 m2 out -> - exec_stmt_prop e m1 s2 t2 m2 out -> - exec_stmt_prop e m (Ssequence s1 s2) (t1 ** t2) m2 out). -Proof. - intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR. - red in H0; simpl in H0. eapply exec_Sseq_continue; eauto. -Qed. - -Lemma transl_Ssequence_2_correct: - (forall (e : Csem.env) (m : mem) (s1 s2 : statement) (t1 : trace) - (m1 : mem) (out : Csem.outcome), - Csem.exec_stmt ge e m s1 t1 m1 out -> - exec_stmt_prop e m s1 t1 m1 out -> - out <> Csem.Out_normal -> - exec_stmt_prop e m (Ssequence s1 s2) t1 m1 out). -Proof. - intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR. - eapply exec_Sseq_stop; eauto. - destruct out; simpl; congruence. -Qed. - -Lemma transl_Sifthenelse_true_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) - (s1 s2 : statement) (v1 : val) (t : trace) (m' : mem) - (out : Csem.outcome), - Csem.eval_expr ge e m a v1 -> - is_true v1 (typeof a) -> - Csem.exec_stmt ge e m s1 t m' out -> - exec_stmt_prop e m s1 t m' out -> - exec_stmt_prop e m (Csyntax.Sifthenelse a s1 s2) t m' out). -Proof. - intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR. - exploit make_boolean_correct_true. - eapply (transl_expr_correct _ _ _ _ MENV _ _ H); eauto. - eauto. - intros [vb [EVAL ISTRUE]]. - eapply exec_Sifthenelse; eauto. apply Val.bool_of_true_val; eauto. simpl; eauto. -Qed. - -Lemma transl_Sifthenelse_false_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) - (s1 s2 : statement) (v1 : val) (t : trace) (m' : mem) - (out : Csem.outcome), - Csem.eval_expr ge e m a v1 -> - is_false v1 (typeof a) -> - Csem.exec_stmt ge e m s2 t m' out -> - exec_stmt_prop e m s2 t m' out -> - exec_stmt_prop e m (Csyntax.Sifthenelse a s1 s2) t m' out). -Proof. - intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR. - exploit make_boolean_correct_false. - eapply (transl_expr_correct _ _ _ _ MENV _ _ H); eauto. - eauto. - intros [vb [EVAL ISFALSE]]. - eapply exec_Sifthenelse; eauto. apply Val.bool_of_false_val; eauto. simpl; eauto. -Qed. - -Lemma transl_Sreturn_none_correct: - (forall (e : Csem.env) (m : mem), - exec_stmt_prop e m (Csyntax.Sreturn None) E0 m (Csem.Out_return None)). -Proof. - intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR. - simpl. apply exec_Sreturn_none. -Qed. - -Lemma transl_Sreturn_some_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (v : val), - Csem.eval_expr ge e m a v -> - exec_stmt_prop e m (Csyntax.Sreturn (Some a)) E0 m (Csem.Out_return (Some v))). -Proof. - intros; red; intros. inv WT. inv H1. monadInv TR. - simpl. eapply exec_Sreturn_some; eauto. - eapply (transl_expr_correct _ _ _ _ MENV _ _ H); eauto. -Qed. - -Lemma transl_Sbreak_correct: - (forall (e : Csem.env) (m : mem), - exec_stmt_prop e m Sbreak E0 m Out_break). -Proof. - intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR. - simpl. apply exec_Sexit. -Qed. - -Lemma transl_Scontinue_correct: - (forall (e : Csem.env) (m : mem), - exec_stmt_prop e m Scontinue E0 m Out_continue). -Proof. - intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR. - simpl. apply exec_Sexit. -Qed. - Lemma exit_if_false_true: - forall a ts e m v tyenv te, + forall a ts e m v tyenv te f tk, exit_if_false a = OK ts -> Csem.eval_expr ge e m a v -> is_true v (typeof a) -> match_env tyenv e te -> wt_expr tyenv a -> - exec_stmt tprog te m ts E0 m Out_normal. + step tgve (State f ts tk te m) E0 (State f Sskip tk te m). Proof. intros. monadInv H. exploit make_boolean_correct_true. eapply (transl_expr_correct _ _ _ _ H2 _ _ H0); eauto. eauto. intros [vb [EVAL ISTRUE]]. - eapply exec_Sifthenelse with (v := vb); eauto. + change Sskip with (if true then Sskip else Sexit 0). + eapply step_ifthenelse; eauto. apply Val.bool_of_true_val; eauto. - constructor. Qed. Lemma exit_if_false_false: - forall a ts e m v tyenv te, + forall a ts e m v tyenv te f tk, exit_if_false a = OK ts -> Csem.eval_expr ge e m a v -> is_false v (typeof a) -> match_env tyenv e te -> wt_expr tyenv a -> - exec_stmt tprog te m ts E0 m (Out_exit 0). + step tgve (State f ts tk te m) E0 (State f (Sexit 0) tk te m). Proof. intros. monadInv H. exploit make_boolean_correct_false. eapply (transl_expr_correct _ _ _ _ H2 _ _ H0); eauto. eauto. intros [vb [EVAL ISFALSE]]. - eapply exec_Sifthenelse with (v := vb); eauto. + change (Sexit 0) with (if false then Sskip else Sexit 0). + eapply step_ifthenelse; eauto. apply Val.bool_of_false_val; eauto. - simpl. constructor. Qed. -Lemma transl_Swhile_false_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (s : statement) - (v : val), - Csem.eval_expr ge e m a v -> - is_false v (typeof a) -> - exec_stmt_prop e m (Swhile a s) E0 m Csem.Out_normal). -Proof. - intros; red; intros; simpl. inv WT. monadInv TR. - change Out_normal with (outcome_block (Out_exit 0)). - apply exec_Sblock. apply exec_Sloop_stop. apply exec_Sseq_stop. - eapply exit_if_false_false; eauto. congruence. congruence. -Qed. +(** ** Semantic preservation for statements *) -Lemma transl_out_break_or_return: - forall out1 out2 nbrk ncnt, - out_break_or_return out1 out2 -> - transl_outcome nbrk ncnt out2 = - outcome_block (outcome_block (transl_outcome 1 0 out1)). -Proof. - intros. inversion H; subst; reflexivity. -Qed. +(** The simulation diagram for the translation of statements and functions + is a "plus" diagram of the form +<< + I + S1 ------- R1 + | | + t | + | t + v v + S2 ------- R2 + I I +>> -Lemma transl_out_normal_or_continue: - forall out, - out_normal_or_continue out -> - Out_normal = outcome_block (transl_outcome 1 0 out). -Proof. - intros; inversion H; reflexivity. -Qed. +The invariant [I] is the [match_states] predicate that we now define. +*) -Lemma transl_Swhile_stop_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (v : val) - (s : statement) (t : trace) (m' : mem) (out' out : Csem.outcome), - Csem.eval_expr ge e m a v -> - is_true v (typeof a) -> - Csem.exec_stmt ge e m s t m' out' -> - exec_stmt_prop e m s t m' out' -> - out_break_or_return out' out -> - exec_stmt_prop e m (Swhile a s) t m' out). -Proof. - intros; red; intros. inv WT. monadInv TR. - rewrite (transl_out_break_or_return _ _ nbrk ncnt H3). - apply exec_Sblock. apply exec_Sloop_stop. - eapply exec_Sseq_continue. - eapply exit_if_false_true; eauto. - apply exec_Sblock. eauto. traceEq. - inversion H3; simpl; congruence. -Qed. +Definition typenv_fun (f: Csyntax.function) := + add_vars (global_typenv prog) (f.(Csyntax.fn_params) ++ f.(Csyntax.fn_vars)). -Lemma transl_Swhile_loop_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (s : statement) - (v : val) (t1 : trace) (m1 : mem) (out1 : Csem.outcome) - (t2 : trace) (m2 : mem) (out : Csem.outcome), - Csem.eval_expr ge e m a v -> - is_true v (typeof a) -> - Csem.exec_stmt ge e m s t1 m1 out1 -> - exec_stmt_prop e m s t1 m1 out1 -> - out_normal_or_continue out1 -> - Csem.exec_stmt ge e m1 (Swhile a s) t2 m2 out -> - exec_stmt_prop e m1 (Swhile a s) t2 m2 out -> - exec_stmt_prop e m (Swhile a s) (t1 ** t2) m2 out). -Proof. - intros; red; intros. - exploit H5; eauto. intro NEXTITER. - inv WT. monadInv TR. - inversion NEXTITER; subst. - apply exec_Sblock. - eapply exec_Sloop_loop. eapply exec_Sseq_continue. - eapply exit_if_false_true; eauto. - rewrite (transl_out_normal_or_continue _ H3). - apply exec_Sblock. eauto. - reflexivity. eassumption. - traceEq. -Qed. +Inductive match_transl: stmt -> cont -> stmt -> cont -> Prop := + | match_transl_0: forall ts tk, + match_transl ts tk ts tk + | match_transl_1: forall ts tk, + match_transl (Sblock ts) tk ts (Kblock tk). -Lemma transl_Sdowhile_false_correct: - (forall (e : Csem.env) (m : mem) (s : statement) (a : Csyntax.expr) - (t : trace) (m1 : mem) (out1 : Csem.outcome) (v : val), - Csem.exec_stmt ge e m s t m1 out1 -> - exec_stmt_prop e m s t m1 out1 -> - out_normal_or_continue out1 -> - Csem.eval_expr ge e m1 a v -> - is_false v (typeof a) -> - exec_stmt_prop e m (Sdowhile a s) t m1 Csem.Out_normal). +Lemma match_transl_step: + forall ts tk ts' tk' f te m, + match_transl (Sblock ts) tk ts' tk' -> + star step tgve (State f ts' tk' te m) E0 (State f ts (Kblock tk) te m). Proof. - intros; red; intros. inv WT. monadInv TR. - simpl. - change Out_normal with (outcome_block (Out_exit 0)). - apply exec_Sblock. apply exec_Sloop_stop. eapply exec_Sseq_continue. - rewrite (transl_out_normal_or_continue out1 H1). - apply exec_Sblock. eauto. - eapply exit_if_false_false; eauto. traceEq. congruence. -Qed. + intros. inv H. + apply star_one. constructor. + apply star_refl. +Qed. + +Inductive match_cont: typenv -> nat -> nat -> Csem.cont -> Csharpminor.cont -> Prop := + | match_Kstop: forall tyenv nbrk ncnt, + match_cont tyenv nbrk ncnt Csem.Kstop Kstop + | match_Kseq: forall tyenv nbrk ncnt s k ts tk, + transl_statement nbrk ncnt s = OK ts -> + wt_stmt tyenv s -> + match_cont tyenv nbrk ncnt k tk -> + match_cont tyenv nbrk ncnt + (Csem.Kseq s k) + (Kseq ts tk) + | match_Kwhile: forall tyenv nbrk ncnt a s k ta ts tk, + exit_if_false a = OK ta -> + transl_statement 1%nat 0%nat s = OK ts -> + wt_expr tyenv a -> + wt_stmt tyenv s -> + match_cont tyenv nbrk ncnt k tk -> + match_cont tyenv 1%nat 0%nat + (Csem.Kwhile a s k) + (Kblock (Kseq (Sloop (Sseq ta (Sblock ts))) (Kblock tk))) + | match_Kdowhile: forall tyenv nbrk ncnt a s k ta ts tk, + exit_if_false a = OK ta -> + transl_statement 1%nat 0%nat s = OK ts -> + wt_expr tyenv a -> + wt_stmt tyenv s -> + match_cont tyenv nbrk ncnt k tk -> + match_cont tyenv 1%nat 0%nat + (Csem.Kdowhile a s k) + (Kblock (Kseq ta (Kseq (Sloop (Sseq (Sblock ts) ta)) (Kblock tk)))) + | match_Kfor2: forall tyenv nbrk ncnt a2 a3 s k ta2 ta3 ts tk, + exit_if_false a2 = OK ta2 -> + transl_statement nbrk ncnt a3 = OK ta3 -> + transl_statement 1%nat 0%nat s = OK ts -> + wt_expr tyenv a2 -> wt_stmt tyenv a3 -> wt_stmt tyenv s -> + match_cont tyenv nbrk ncnt k tk -> + match_cont tyenv 1%nat 0%nat + (Csem.Kfor2 a2 a3 s k) + (Kblock (Kseq ta3 (Kseq (Sloop (Sseq ta2 (Sseq (Sblock ts) ta3))) (Kblock tk)))) + | match_Kfor3: forall tyenv nbrk ncnt a2 a3 s k ta2 ta3 ts tk, + exit_if_false a2 = OK ta2 -> + transl_statement nbrk ncnt a3 = OK ta3 -> + transl_statement 1%nat 0%nat s = OK ts -> + wt_expr tyenv a2 -> wt_stmt tyenv a3 -> wt_stmt tyenv s -> + match_cont tyenv nbrk ncnt k tk -> + match_cont tyenv nbrk ncnt + (Csem.Kfor3 a2 a3 s k) + (Kseq (Sloop (Sseq ta2 (Sseq (Sblock ts) ta3))) (Kblock tk)) + | match_Kswitch: forall tyenv nbrk ncnt k tk, + match_cont tyenv nbrk ncnt k tk -> + match_cont tyenv 0%nat (S ncnt) + (Csem.Kswitch k) + (Kblock tk) + | match_Kcall_none: forall tyenv nbrk ncnt nbrk' ncnt' f e k tf te tk, + transl_function f = OK tf -> + wt_stmt (typenv_fun f) f.(Csyntax.fn_body) -> + match_env (typenv_fun f) e te -> + match_cont (typenv_fun f) nbrk' ncnt' k tk -> + match_cont tyenv nbrk ncnt + (Csem.Kcall None f e k) + (Kcall None tf te tk) + | match_Kcall_some: forall tyenv nbrk ncnt nbrk' ncnt' loc ofs ty f e k id tf te tk, + transl_function f = OK tf -> + wt_stmt (typenv_fun f) f.(Csyntax.fn_body) -> + match_env (typenv_fun f) e te -> + ofs = Int.zero -> + (typenv_fun f)!id = Some ty -> + match access_mode ty with + | By_value chunk => eval_var_ref tgve te id loc chunk + | _ => True + end -> + match_cont (typenv_fun f) nbrk' ncnt' k tk -> + match_cont tyenv nbrk ncnt + (Csem.Kcall (Some(loc, ofs, ty)) f e k) + (Kcall (Some id) tf te tk). + +Inductive match_states: Csem.state -> Csharpminor.state -> Prop := + | match_state: + forall f nbrk ncnt s k e m tf ts tk te ts' tk' + (TRF: transl_function f = OK tf) + (TR: transl_statement nbrk ncnt s = OK ts) + (MTR: match_transl ts tk ts' tk') + (WTF: wt_stmt (typenv_fun f) f.(Csyntax.fn_body)) + (WT: wt_stmt (typenv_fun f) s) + (MENV: match_env (typenv_fun f) e te) + (MK: match_cont (typenv_fun f) nbrk ncnt k tk), + match_states (Csem.State f s k e m) + (State tf ts' tk' te m) + | match_callstate: + forall fd args k m tfd tk + (TR: transl_fundef fd = OK tfd) + (WT: wt_fundef (global_typenv prog) fd) + (MK: match_cont (global_typenv prog) 0%nat 0%nat k tk) + (ISCC: Csem.is_call_cont k), + match_states (Csem.Callstate fd args k m) + (Callstate tfd args tk m) + | match_returnstate: + forall res k m tk + (MK: match_cont (global_typenv prog) 0%nat 0%nat k tk), + match_states (Csem.Returnstate res k m) + (Returnstate res tk m). + +Remark match_states_skip: + forall f e te nbrk ncnt k tf tk m, + transl_function f = OK tf -> + wt_stmt (typenv_fun f) f.(Csyntax.fn_body) -> + match_env (typenv_fun f) e te -> + match_cont (typenv_fun f) nbrk ncnt k tk -> + match_states (Csem.State f Csyntax.Sskip k e m) (State tf Sskip tk te m). +Proof. + intros. econstructor; eauto. simpl; reflexivity. constructor. constructor. +Qed. + +(** Commutation between label resolution and compilation *) + +Section FIND_LABEL. +Variable lbl: label. +Variable tyenv: typenv. -Lemma transl_Sdowhile_stop_correct: - (forall (e : Csem.env) (m : mem) (s : statement) (a : Csyntax.expr) - (t : trace) (m1 : mem) (out1 out : Csem.outcome), - Csem.exec_stmt ge e m s t m1 out1 -> - exec_stmt_prop e m s t m1 out1 -> - out_break_or_return out1 out -> - exec_stmt_prop e m (Sdowhile a s) t m1 out). -Proof. - intros; red; intros. inv WT. monadInv TR. - simpl. - assert (outcome_block (transl_outcome 1 0 out1) <> Out_normal). - inversion H1; simpl; congruence. - rewrite (transl_out_break_or_return _ _ nbrk ncnt H1). - apply exec_Sblock. apply exec_Sloop_stop. - apply exec_Sseq_stop. apply exec_Sblock. eauto. - auto. auto. -Qed. +Remark exit_if_false_no_label: + forall a s, exit_if_false a = OK s -> forall k, find_label lbl s k = None. +Proof. + intros. unfold exit_if_false in H. monadInv H. simpl. auto. +Qed. + +Lemma transl_find_label: + forall s nbrk ncnt k ts tk + (WT: wt_stmt tyenv s) + (TR: transl_statement nbrk ncnt s = OK ts) + (MC: match_cont tyenv nbrk ncnt k tk), + match Csem.find_label lbl s k with + | None => find_label lbl ts tk = None + | Some (s', k') => + exists ts', exists tk', exists nbrk', exists ncnt', + find_label lbl ts tk = Some (ts', tk') + /\ transl_statement nbrk' ncnt' s' = OK ts' + /\ match_cont tyenv nbrk' ncnt' k' tk' + /\ wt_stmt tyenv s' + end + +with transl_find_label_ls: + forall ls nbrk ncnt k tls tk + (WT: wt_lblstmts tyenv ls) + (TR: transl_lbl_stmt nbrk ncnt ls = OK tls) + (MC: match_cont tyenv nbrk ncnt k tk), + match Csem.find_label_ls lbl ls k with + | None => find_label_ls lbl tls tk = None + | Some (s', k') => + exists ts', exists tk', exists nbrk', exists ncnt', + find_label_ls lbl tls tk = Some (ts', tk') + /\ transl_statement nbrk' ncnt' s' = OK ts' + /\ match_cont tyenv nbrk' ncnt' k' tk' + /\ wt_stmt tyenv s' + end. -Lemma transl_Sdowhile_loop_correct: - (forall (e : Csem.env) (m : mem) (s : statement) (a : Csyntax.expr) - (m1 m2 : mem) (t1 t2 : trace) (out out1 : Csem.outcome) (v : val), - Csem.exec_stmt ge e m s t1 m1 out1 -> - exec_stmt_prop e m s t1 m1 out1 -> - out_normal_or_continue out1 -> - Csem.eval_expr ge e m1 a v -> - is_true v (typeof a) -> - Csem.exec_stmt ge e m1 (Sdowhile a s) t2 m2 out -> - exec_stmt_prop e m1 (Sdowhile a s) t2 m2 out -> - exec_stmt_prop e m (Sdowhile a s) (t1 ** t2) m2 out). Proof. - intros; red; intros. - exploit H5; eauto. intro NEXTITER. - inv WT. monadInv TR. inversion NEXTITER; subst. - apply exec_Sblock. - eapply exec_Sloop_loop. eapply exec_Sseq_continue. - rewrite (transl_out_normal_or_continue _ H1). - apply exec_Sblock. eauto. - eapply exit_if_false_true; eauto. - reflexivity. eassumption. traceEq. -Qed. + intro s; case s; intros; inv WT; try (monadInv TR); simpl. +(* skip *) + auto. +(* assign *) + simpl in TR. destruct (is_variable e); monadInv TR. + unfold var_set in EQ0. destruct (access_mode (typeof e)); inv EQ0. auto. + unfold make_store in EQ2. destruct (access_mode (typeof e)); inv EQ2. auto. +(* call *) + simpl in TR. destruct (classify_fun (typeof e)); monadInv TR. auto. +(* seq *) + exploit (transl_find_label s0 nbrk ncnt (Csem.Kseq s1 k)); eauto. constructor; eauto. + destruct (Csem.find_label lbl s0 (Csem.Kseq s1 k)) as [[s' k'] | ]. + intros [ts' [tk' [nbrk' [ncnt' [A [B [C D]]]]]]]. + rewrite A. exists ts'; exists tk'; exists nbrk'; exists ncnt'; auto. + intro. rewrite H. eapply transl_find_label; eauto. +(* ifthenelse *) + exploit (transl_find_label s0); eauto. + destruct (Csem.find_label lbl s0 k) as [[s' k'] | ]. + intros [ts' [tk' [nbrk' [ncnt' [A [B [C D]]]]]]]. + rewrite A. exists ts'; exists tk'; exists nbrk'; exists ncnt'; auto. + intro. rewrite H. eapply transl_find_label; eauto. +(* while *) + rewrite (exit_if_false_no_label _ _ EQ). + eapply transl_find_label; eauto. econstructor; eauto. +(* dowhile *) + exploit (transl_find_label s0 1%nat 0%nat (Csem.Kdowhile e s0 k)); eauto. econstructor; eauto. + destruct (Csem.find_label lbl s0 (Kdowhile e s0 k)) as [[s' k'] | ]. + intros [ts' [tk' [nbrk' [ncnt' [A [B [C D]]]]]]]. + rewrite A. exists ts'; exists tk'; exists nbrk'; exists ncnt'; auto. + intro. rewrite H. eapply exit_if_false_no_label; eauto. +(* for *) + simpl in TR. destruct (is_Sskip s0); monadInv TR. + simpl. rewrite (exit_if_false_no_label _ _ EQ). + exploit (transl_find_label s2 1%nat 0%nat (Kfor2 e s1 s2 k)); eauto. econstructor; eauto. + destruct (Csem.find_label lbl s2 (Kfor2 e s1 s2 k)) as [[s' k'] | ]. + intros [ts' [tk' [nbrk' [ncnt' [A [B [C D]]]]]]]. + rewrite A. exists ts'; exists tk'; exists nbrk'; exists ncnt'; auto. + intro. rewrite H. + eapply transl_find_label; eauto. econstructor; eauto. + exploit (transl_find_label s0 nbrk ncnt (Csem.Kseq (Sfor Csyntax.Sskip e s1 s2) k)); eauto. + econstructor; eauto. simpl. rewrite is_Sskip_true. rewrite EQ1; simpl. rewrite EQ0; simpl. rewrite EQ2; simpl. reflexivity. + constructor; auto. constructor. + simpl. rewrite (exit_if_false_no_label _ _ EQ1). + destruct (Csem.find_label lbl s0 (Csem.Kseq (Sfor Csyntax.Sskip e s1 s2) k)) as [[s' k'] | ]. + intros [ts' [tk' [nbrk' [ncnt' [A [B [C D]]]]]]]. + rewrite A. exists ts'; exists tk'; exists nbrk'; exists ncnt'; auto. + intro. rewrite H. + exploit (transl_find_label s2 1%nat 0%nat (Kfor2 e s1 s2 k)); eauto. econstructor; eauto. + destruct (Csem.find_label lbl s2 (Kfor2 e s1 s2 k)) as [[s' k'] | ]. + intros [ts' [tk' [nbrk' [ncnt' [A [B [C D]]]]]]]. + rewrite A. exists ts'; exists tk'; exists nbrk'; exists ncnt'; auto. + intro. rewrite H0. + eapply transl_find_label; eauto. econstructor; eauto. +(* break *) + auto. +(* continue *) + auto. +(* return *) + simpl in TR. destruct o; monadInv TR. auto. auto. +(* switch *) + eapply transl_find_label_ls with (k := Csem.Kswitch k); eauto. econstructor; eauto. +(* label *) + destruct (ident_eq lbl l). + exists x; exists tk; exists nbrk; exists ncnt; auto. + eapply transl_find_label; eauto. +(* goto *) + auto. -Lemma transl_Sfor_start_correct: - (forall (e : Csem.env) (m : mem) (s a1 : statement) - (a2 : Csyntax.expr) (a3 : statement) (out : Csem.outcome) - (m1 m2 : mem) (t1 t2 : trace), - a1 <> Csyntax.Sskip -> - Csem.exec_stmt ge e m a1 t1 m1 Csem.Out_normal -> - exec_stmt_prop e m a1 t1 m1 Csem.Out_normal -> - Csem.exec_stmt ge e m1 (Sfor Csyntax.Sskip a2 a3 s) t2 m2 out -> - exec_stmt_prop e m1 (Sfor Csyntax.Sskip a2 a3 s) t2 m2 out -> - exec_stmt_prop e m (Sfor a1 a2 a3 s) (t1 ** t2) m2 out). -Proof. - intros; red; intros. - destruct (transl_stmt_Sfor_start _ _ _ _ _ _ _ TR H) as [ts1 [ts2 [EQ [TR1 TR2]]]]. - subst ts. - inv WT. - assert (WT': wt_stmt tyenv (Sfor Csyntax.Sskip a2 a3 s)). - constructor; auto. constructor. - exploit H1; eauto. simpl. intro EXEC1. - exploit H3; eauto. intro EXEC2. - eapply exec_Sseq_continue; eauto. + intro ls; case ls; intros; inv WT; monadInv TR; simpl. +(* default *) + eapply transl_find_label; eauto. +(* case *) + exploit (transl_find_label s nbrk ncnt (Csem.Kseq (seq_of_labeled_statement l) k)); eauto. + econstructor; eauto. apply transl_lbl_stmt_2; eauto. + apply wt_seq_of_labeled_statement; auto. + destruct (Csem.find_label lbl s (Csem.Kseq (seq_of_labeled_statement l) k)) as [[s' k'] | ]. + intros [ts' [tk' [nbrk' [ncnt' [A [B [C D]]]]]]]. + rewrite A. exists ts'; exists tk'; exists nbrk'; exists ncnt'; auto. + intro. rewrite H. + eapply transl_find_label_ls; eauto. Qed. -Lemma transl_Sfor_false_correct: - (forall (e : Csem.env) (m : mem) (s : statement) (a2 : Csyntax.expr) - (a3 : statement) (v : val), - Csem.eval_expr ge e m a2 v -> - is_false v (typeof a2) -> - exec_stmt_prop e m (Sfor Csyntax.Sskip a2 a3 s) E0 m Csem.Out_normal). -Proof. - intros; red; intros. inv WT. - rewrite transl_stmt_Sfor_not_start in TR; monadInv TR. - simpl. - change Out_normal with (outcome_block (Out_exit 0)). - apply exec_Sblock. apply exec_Sloop_stop. - apply exec_Sseq_stop. eapply exit_if_false_false; eauto. - congruence. congruence. -Qed. +End FIND_LABEL. -Lemma transl_Sfor_stop_correct: - (forall (e : Csem.env) (m : mem) (s : statement) (a2 : Csyntax.expr) - (a3 : statement) (v : val) (m1 : mem) (t : trace) - (out1 out : Csem.outcome), - Csem.eval_expr ge e m a2 v -> - is_true v (typeof a2) -> - Csem.exec_stmt ge e m s t m1 out1 -> - exec_stmt_prop e m s t m1 out1 -> - out_break_or_return out1 out -> - exec_stmt_prop e m (Sfor Csyntax.Sskip a2 a3 s) t m1 out). -Proof. - intros; red; intros. inv WT. - rewrite transl_stmt_Sfor_not_start in TR; monadInv TR. - assert (outcome_block (transl_outcome 1 0 out1) <> Out_normal). - inversion H3; simpl; congruence. - rewrite (transl_out_break_or_return _ _ nbrk ncnt H3). - apply exec_Sblock. apply exec_Sloop_stop. - eapply exec_Sseq_continue. eapply exit_if_false_true; eauto. - apply exec_Sseq_stop. apply exec_Sblock. eauto. - auto. reflexivity. auto. -Qed. +(** Properties of call continuations *) -Lemma transl_Sfor_loop_correct: - (forall (e : Csem.env) (m : mem) (s : statement) (a2 : Csyntax.expr) - (a3 : statement) (v : val) (m1 m2 m3 : mem) (t1 t2 t3 : trace) - (out1 out : Csem.outcome), - Csem.eval_expr ge e m a2 v -> - is_true v (typeof a2) -> - Csem.exec_stmt ge e m s t1 m1 out1 -> - exec_stmt_prop e m s t1 m1 out1 -> - out_normal_or_continue out1 -> - Csem.exec_stmt ge e m1 a3 t2 m2 Csem.Out_normal -> - exec_stmt_prop e m1 a3 t2 m2 Csem.Out_normal -> - Csem.exec_stmt ge e m2 (Sfor Csyntax.Sskip a2 a3 s) t3 m3 out -> - exec_stmt_prop e m2 (Sfor Csyntax.Sskip a2 a3 s) t3 m3 out -> - exec_stmt_prop e m (Sfor Csyntax.Sskip a2 a3 s) (t1 ** t2 ** t3) m3 out). +Lemma match_cont_call_cont: + forall nbrk' ncnt' tyenv' tyenv nbrk ncnt k tk, + match_cont tyenv nbrk ncnt k tk -> + match_cont tyenv' nbrk' ncnt' (Csem.call_cont k) (call_cont tk). Proof. - intros; red; intros. - exploit H7; eauto. intro NEXTITER. - inv WT. - rewrite transl_stmt_Sfor_not_start in TR; monadInv TR. - inversion NEXTITER; subst. - apply exec_Sblock. - eapply exec_Sloop_loop. eapply exec_Sseq_continue. - eapply exit_if_false_true; eauto. - eapply exec_Sseq_continue. - rewrite (transl_out_normal_or_continue _ H3). - apply exec_Sblock. eauto. - red in H5; simpl in H5; eauto. - reflexivity. reflexivity. eassumption. - traceEq. + induction 1; simpl; auto. + constructor. + econstructor; eauto. + econstructor; eauto. Qed. -Lemma transl_lblstmts_switch: - forall e m0 m1 n nbrk ncnt tyenv te t0 t m2 out sl body ts, - exec_stmt tprog te m0 body t0 m1 - (Out_exit (switch_target n (lblstmts_length sl) (switch_table sl 0))) -> - transl_lblstmts - (lblstmts_length sl) - (S (lblstmts_length sl + ncnt)) - sl (Sblock body) = OK ts -> - wt_lblstmts tyenv sl -> - match_env tyenv e te -> - exec_lblstmts_prop e m1 (select_switch n sl) t m2 out -> - Csharpminor.exec_stmt tprog te m0 ts (t0 ** t) m2 - (transl_outcome nbrk ncnt (outcome_switch out)). +Lemma match_cont_is_call_cont: + forall typenv nbrk ncnt k tk typenv' nbrk' ncnt', + match_cont typenv nbrk ncnt k tk -> + Csem.is_call_cont k -> + match_cont typenv' nbrk' ncnt' k tk /\ is_call_cont tk. Proof. - induction sl; intros. - simpl in H. simpl in H3. - eapply H3; eauto. - change Out_normal with (outcome_block (Out_exit 0)). - apply exec_Sblock. auto. - (* Inductive case *) - simpl in H. simpl in H3. rewrite Int.eq_sym in H3. destruct (Int.eq n i). - (* first case selected *) - eapply H3; eauto. - change Out_normal with (outcome_block (Out_exit 0)). - apply exec_Sblock. auto. - (* next case selected *) - inversion H1; clear H1; subst. - simpl in H0; monadInv H0. - eapply IHsl with (body := Sseq (Sblock body) x); eauto. - apply exec_Sseq_stop. - change (Out_exit (switch_target n (lblstmts_length sl) (switch_table sl 0))) - with (outcome_block (Out_exit (S (switch_target n (lblstmts_length sl) (switch_table sl 0))))). - apply exec_Sblock. - rewrite switch_target_table_shift in H. auto. congruence. + intros. inv H; simpl in H0; try contradiction; simpl; intuition. + constructor. + econstructor; eauto. + econstructor; eauto. Qed. -Lemma transl_Sswitch_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t : trace) - (n : int) (sl : labeled_statements) (m1 : mem) (out : Csem.outcome), - Csem.eval_expr ge e m a (Vint n) -> - exec_lblstmts ge e m (select_switch n sl) t m1 out -> - exec_lblstmts_prop e m (select_switch n sl) t m1 out -> - exec_stmt_prop e m (Csyntax.Sswitch a sl) t m1 (outcome_switch out)). -Proof. - intros; red; intros. - inv WT. monadInv TR. - rewrite length_switch_table in EQ0. - replace (ncnt + lblstmts_length sl + 1)%nat - with (S (lblstmts_length sl + ncnt))%nat in EQ0 by omega. - change t with (E0 ** t). eapply transl_lblstmts_switch; eauto. - constructor. eapply (transl_expr_correct _ _ _ _ MENV _ _ H); eauto. -Qed. +(** The simulation proof *) + +Lemma transl_step: + forall S1 t S2, Csem.step ge S1 t S2 -> + forall T1, match_states S1 T1 -> + exists T2, plus step tgve T1 t T2 /\ match_states S2 T2. +Proof. + induction 1; intros T1 MST; inv MST. + +(* assign *) + simpl in TR. inv WT. + case_eq (is_variable a1); intros. + rewrite H2 in TR. monadInv TR. + exploit is_variable_correct; eauto. intro EQ1. rewrite EQ1 in H. + assert (ts' = ts /\ tk' = tk). + inversion MTR. auto. + subst ts. unfold var_set in EQ0. destruct (access_mode (typeof a1)); congruence. + destruct H3; subst ts' tk'. + econstructor; split. + apply plus_one. eapply var_set_correct; eauto. congruence. + exploit transl_expr_correct; eauto. + eapply match_states_skip; eauto. + + rewrite H2 in TR. monadInv TR. + assert (ts' = ts /\ tk' = tk). + inversion MTR. auto. + subst ts. unfold make_store in EQ2. destruct (access_mode (typeof a1)); congruence. + destruct H3; subst ts' tk'. + econstructor; split. + apply plus_one. eapply make_store_correct; eauto. + exploit transl_lvalue_correct; eauto. + exploit transl_expr_correct; eauto. + eapply match_states_skip; eauto. + +(* call none *) + generalize TR. simpl. case_eq (classify_fun (typeof a)); try congruence. + intros targs tres CF TR'. monadInv TR'. inv MTR. inv WT. + exploit functions_translated; eauto. intros [tfd [FIND TFD]]. + econstructor; split. + apply plus_one. econstructor; eauto. + exploit transl_expr_correct; eauto. + exploit transl_exprlist_correct; eauto. + eapply sig_translated; eauto. congruence. + econstructor; eauto. eapply functions_well_typed; eauto. + econstructor; eauto. simpl. auto. + +(* call some *) + generalize TR. simpl. case_eq (classify_fun (typeof a)); try congruence. + intros targs tres CF TR'. monadInv TR'. inv MTR. inv WT. + exploit functions_translated; eauto. intros [tfd [FIND TFD]]. + inv H7. exploit call_dest_correct; eauto. + intros [id [A [B [C D]]]]. subst x ofs. + econstructor; split. + apply plus_one. econstructor; eauto. + exploit transl_expr_correct; eauto. + exploit transl_exprlist_correct; eauto. + eapply sig_translated; eauto. congruence. + econstructor; eauto. eapply functions_well_typed; eauto. + econstructor; eauto. simpl; auto. + +(* seq *) + monadInv TR. inv WT. inv MTR. + econstructor; split. + apply plus_one. constructor. + econstructor; eauto. constructor. + econstructor; eauto. -Lemma transl_LSdefault_correct: - (forall (e : Csem.env) (m : mem) (s : statement) (t : trace) - (m1 : mem) (out : Csem.outcome), - Csem.exec_stmt ge e m s t m1 out -> - exec_stmt_prop e m s t m1 out -> - exec_lblstmts_prop e m (LSdefault s) t m1 out). -Proof. - intros; red; intros. inv WT. monadInv TR. - replace (transl_outcome nbrk ncnt (outcome_switch out)) - with (outcome_block (transl_outcome 0 (S ncnt) out)). - constructor. - eapply exec_Sseq_continue. eauto. - eapply H0; eauto. traceEq. - destruct out; simpl; auto. -Qed. +(* skip seq *) + monadInv TR. inv MTR. inv MK. + econstructor; split. + apply plus_one. apply step_skip_seq. + econstructor; eauto. constructor. + +(* continue seq *) + monadInv TR. inv MTR. inv MK. + econstructor; split. + apply plus_one. constructor. + econstructor; eauto. simpl. reflexivity. constructor. + +(* break seq *) + monadInv TR. inv MTR. inv MK. + econstructor; split. + apply plus_one. constructor. + econstructor; eauto. simpl. reflexivity. constructor. + +(* ifthenelse true *) + monadInv TR. inv MTR. inv WT. + exploit make_boolean_correct_true; eauto. + exploit transl_expr_correct; eauto. + intros [v [A B]]. + econstructor; split. + apply plus_one. apply step_ifthenelse with (v := v) (b := true). + auto. apply Val.bool_of_true_val. auto. + econstructor; eauto. constructor. + +(* ifthenelse false *) + monadInv TR. inv MTR. inv WT. + exploit make_boolean_correct_false; eauto. + exploit transl_expr_correct; eauto. + intros [v [A B]]. + econstructor; split. + apply plus_one. apply step_ifthenelse with (v := v) (b := false). + auto. apply Val.bool_of_false_val. auto. + econstructor; eauto. constructor. + +(* while false *) + monadInv TR. inv WT. + econstructor; split. + eapply star_plus_trans. eapply match_transl_step; eauto. + eapply plus_left. constructor. + eapply star_left. constructor. + eapply star_left. eapply exit_if_false_false; eauto. + eapply star_left. constructor. + eapply star_left. constructor. + apply star_one. constructor. + reflexivity. reflexivity. reflexivity. reflexivity. reflexivity. traceEq. + eapply match_states_skip; eauto. + +(* while true *) + monadInv TR. inv WT. + econstructor; split. + eapply star_plus_trans. eapply match_transl_step; eauto. + eapply plus_left. constructor. + eapply star_left. constructor. + eapply star_left. eapply exit_if_false_true; eauto. + eapply star_left. constructor. + apply star_one. constructor. + reflexivity. reflexivity. reflexivity. reflexivity. traceEq. + econstructor; eauto. constructor. + econstructor; eauto. -Lemma transl_LScase_fallthrough_correct: - (forall (e : Csem.env) (m : mem) (n : int) (s : statement) - (ls : labeled_statements) (t1 : trace) (m1 : mem) (t2 : trace) - (m2 : mem) (out : Csem.outcome), - Csem.exec_stmt ge e m s t1 m1 Csem.Out_normal -> - exec_stmt_prop e m s t1 m1 Csem.Out_normal -> - exec_lblstmts ge e m1 ls t2 m2 out -> - exec_lblstmts_prop e m1 ls t2 m2 out -> - exec_lblstmts_prop e m (LScase n s ls) (t1 ** t2) m2 out). -Proof. - intros; red; intros. inv WT. monadInv TR. - assert (exec_stmt tprog te m0 (Sblock (Sseq body x)) - (t0 ** t1) m1 Out_normal). - change Out_normal with - (outcome_block (transl_outcome (S (lblstmts_length ls)) - (S (S (lblstmts_length ls + ncnt))) - Csem.Out_normal)). - apply exec_Sblock. eapply exec_Sseq_continue. eexact BODY. - eapply H0; eauto. - auto. - exploit H2. eauto. simpl; eauto. eauto. eauto. simpl. - rewrite Eapp_assoc. eauto. -Qed. +(* skip or continue while *) + assert ((ts' = Sskip \/ ts' = Sexit ncnt) /\ tk' = tk). + destruct H; subst x; monadInv TR; inv MTR; auto. + destruct H0. inv MK. + econstructor; split. + eapply plus_left. + destruct H0; subst ts'; constructor. + apply star_one. constructor. traceEq. + econstructor; eauto. + simpl. rewrite H5; simpl. rewrite H6; simpl. reflexivity. + constructor. constructor; auto. + +(* break while *) + monadInv TR. inv MTR. inv MK. + econstructor; split. + eapply plus_left. constructor. + eapply star_left. constructor. + apply star_one. constructor. + reflexivity. traceEq. + eapply match_states_skip; eauto. + +(* dowhile *) + monadInv TR. inv WT. + econstructor; split. + eapply star_plus_trans. eapply match_transl_step; eauto. + eapply plus_left. constructor. + eapply star_left. constructor. + apply star_one. constructor. + reflexivity. reflexivity. traceEq. + econstructor; eauto. constructor. + econstructor; eauto. -Lemma transl_LScase_stop_correct: - (forall (e : Csem.env) (m : mem) (n : int) (s : statement) - (ls : labeled_statements) (t : trace) (m1 : mem) - (out : Csem.outcome), - Csem.exec_stmt ge e m s t m1 out -> - exec_stmt_prop e m s t m1 out -> - out <> Csem.Out_normal -> - exec_lblstmts_prop e m (LScase n s ls) t m1 out). -Proof. - intros; red; intros. inv WT. monadInv TR. - exploit H0; eauto. intro EXEC. - destruct out; simpl; simpl in EXEC. - (* out = Out_break *) - change Out_normal with (outcome_block (Out_exit 0)). - eapply transl_lblstmts_exit with (body := Sblock (Sseq body x)); eauto. - rewrite plus_0_r. - change (Out_exit (lblstmts_length ls)) - with (outcome_block (Out_exit (S (lblstmts_length ls)))). - constructor. eapply exec_Sseq_continue; eauto. - (* out = Out_continue *) - change (Out_exit ncnt) with (outcome_block (Out_exit (S ncnt))). - eapply transl_lblstmts_exit with (body := Sblock (Sseq body x)); eauto. - replace (Out_exit (lblstmts_length ls + S ncnt)) - with (outcome_block (Out_exit (S (S (lblstmts_length ls + ncnt))))). - constructor. eapply exec_Sseq_continue; eauto. - simpl. decEq. omega. - (* out = Out_normal *) - congruence. - (* out = Out_return *) - eapply transl_lblstmts_return with (body := Sblock (Sseq body x)); eauto. - change (Out_return o) - with (outcome_block (Out_return o)). - constructor. eapply exec_Sseq_continue; eauto. -Qed. +(* skip or continue dowhile false *) + assert ((ts' = Sskip \/ ts' = Sexit ncnt) /\ tk' = tk). + destruct H; subst x; monadInv TR; inv MTR; auto. + destruct H2. inv MK. + econstructor; split. + eapply plus_left. destruct H2; subst ts'; constructor. + eapply star_left. constructor. + eapply star_left. eapply exit_if_false_false; eauto. + eapply star_left. constructor. + apply star_one. constructor. + reflexivity. reflexivity. reflexivity. traceEq. + eapply match_states_skip; eauto. + +(* skip or continue dowhile true *) + assert ((ts' = Sskip \/ ts' = Sexit ncnt) /\ tk' = tk). + destruct H; subst x; monadInv TR; inv MTR; auto. + destruct H2. inv MK. + econstructor; split. + eapply plus_left. destruct H2; subst ts'; constructor. + eapply star_left. constructor. + eapply star_left. eapply exit_if_false_true; eauto. + apply star_one. constructor. + reflexivity. reflexivity. traceEq. + econstructor; eauto. + simpl. rewrite H7; simpl. rewrite H8; simpl. reflexivity. constructor. + constructor; auto. -Remark outcome_result_value_match: - forall out ty v nbrk ncnt, - Csem.outcome_result_value out ty v -> - Csharpminor.outcome_result_value (transl_outcome nbrk ncnt out) (opttyp_of_type ty) v. -Proof. - intros until ncnt. - destruct out; simpl; try contradiction. - destruct ty; simpl; auto. - destruct o. intros [A B]. destruct ty; simpl; congruence. - destruct ty; simpl; auto. -Qed. +(* break dowhile *) + monadInv TR. inv MTR. inv MK. + econstructor; split. + eapply plus_left. constructor. + eapply star_left. constructor. + eapply star_left. constructor. + apply star_one. constructor. + reflexivity. reflexivity. traceEq. + eapply match_states_skip; eauto. + +(* for start *) + simpl in TR. rewrite is_Sskip_false in TR; auto. monadInv TR. inv MTR. inv WT. + econstructor; split. + apply plus_one. constructor. + econstructor; eauto. constructor. + constructor; auto. simpl. rewrite is_Sskip_true. rewrite EQ1; simpl. rewrite EQ0; simpl. rewrite EQ2; auto. + constructor; auto. constructor. + +(* for false *) + simpl in TR. rewrite is_Sskip_true in TR. monadInv TR. inv WT. + econstructor; split. + eapply star_plus_trans. eapply match_transl_step; eauto. + eapply plus_left. constructor. + eapply star_left. constructor. + eapply star_left. eapply exit_if_false_false; eauto. + eapply star_left. constructor. + eapply star_left. constructor. + apply star_one. constructor. + reflexivity. reflexivity. reflexivity. reflexivity. reflexivity. reflexivity. + eapply match_states_skip; eauto. + +(* for true *) + simpl in TR. rewrite is_Sskip_true in TR. monadInv TR. inv WT. + econstructor; split. + eapply star_plus_trans. eapply match_transl_step; eauto. + eapply plus_left. constructor. + eapply star_left. constructor. + eapply star_left. eapply exit_if_false_true; eauto. + eapply star_left. constructor. + eapply star_left. constructor. + apply star_one. constructor. + reflexivity. reflexivity. reflexivity. reflexivity. reflexivity. reflexivity. + econstructor; eauto. constructor. + econstructor; eauto. + +(* skip or continue for2 *) + assert ((ts' = Sskip \/ ts' = Sexit ncnt) /\ tk' = tk). + destruct H; subst x; monadInv TR; inv MTR; auto. + destruct H0. inv MK. + econstructor; split. + eapply plus_left. destruct H0; subst ts'; constructor. + apply star_one. constructor. reflexivity. + econstructor; eauto. constructor. + constructor; auto. + +(* break for2 *) + monadInv TR. inv MTR. inv MK. + econstructor; split. + eapply plus_left. constructor. + eapply star_left. constructor. + eapply star_left. constructor. + apply star_one. constructor. + reflexivity. reflexivity. traceEq. + eapply match_states_skip; eauto. + +(* skip for3 *) + monadInv TR. inv MTR. inv MK. + econstructor; split. + apply plus_one. constructor. + econstructor; eauto. + simpl. rewrite is_Sskip_true. rewrite H3; simpl. rewrite H4; simpl. rewrite H5; simpl. reflexivity. + constructor. constructor; auto. + +(* return none *) + monadInv TR. inv MTR. + econstructor; split. + apply plus_one. constructor. monadInv TRF. simpl. rewrite H. auto. + rewrite (match_env_free_blocks _ _ _ m MENV). econstructor; eauto. + eapply match_cont_call_cont. eauto. + +(* return some *) + monadInv TR. inv MTR. inv WT. inv H2. + econstructor; split. + apply plus_one. constructor. monadInv TRF. simpl. + unfold opttyp_of_type. destruct (fn_return f); congruence. + exploit transl_expr_correct; eauto. + rewrite (match_env_free_blocks _ _ _ m MENV). econstructor; eauto. + eapply match_cont_call_cont. eauto. + +(* skip call *) + monadInv TR. inv MTR. + exploit match_cont_is_call_cont; eauto. intros [A B]. + econstructor; split. + apply plus_one. apply step_skip_call. auto. + monadInv TRF. simpl. rewrite H0. auto. + rewrite (match_env_free_blocks _ _ _ m MENV). constructor. eauto. + +(* switch *) + monadInv TR. inv WT. + exploit transl_expr_correct; eauto. intro EV. + econstructor; split. + eapply star_plus_trans. eapply match_transl_step; eauto. + apply plus_one. econstructor. eauto. traceEq. + econstructor; eauto. + apply transl_lbl_stmt_2. apply transl_lbl_stmt_1. eauto. + constructor. + apply wt_seq_of_labeled_statement. apply wt_select_switch. auto. + econstructor. eauto. + +(* skip or break switch *) + assert ((ts' = Sskip \/ ts' = Sexit nbrk) /\ tk' = tk). + destruct H; subst x; monadInv TR; inv MTR; auto. + destruct H0. inv MK. + econstructor; split. + apply plus_one. destruct H0; subst ts'; constructor. + eapply match_states_skip; eauto. + + +(* continue switch *) + monadInv TR. inv MTR. inv MK. + econstructor; split. + apply plus_one. constructor. + econstructor; eauto. simpl. reflexivity. constructor. + +(* label *) + monadInv TR. inv WT. inv MTR. + econstructor; split. + apply plus_one. constructor. + econstructor; eauto. constructor. + +(* goto *) + monadInv TR. inv MTR. + generalize TRF. unfold transl_function. intro TRF'. monadInv TRF'. + exploit (transl_find_label lbl). eexact WTF. eexact EQ0. eapply match_cont_call_cont. eauto. + rewrite H. + intros [ts' [tk'' [nbrk' [ncnt' [A [B [C D]]]]]]]. + econstructor; split. + apply plus_one. constructor. simpl. eexact A. + econstructor; eauto. constructor. + +(* internal function *) + monadInv TR. inv WT. inv H3. monadInv EQ. + exploit match_cont_is_call_cont; eauto. intros [A B]. + exploit match_env_alloc_variables; eauto. + apply match_globalenv_match_env_empty. apply match_global_typenv. + apply transl_fn_variables. eauto. eauto. + intros [te1 [C D]]. + econstructor; split. + apply plus_one. econstructor. + eapply transl_names_norepet; eauto. + eexact C. eapply bind_parameters_match; eauto. + econstructor; eauto. + unfold transl_function. rewrite EQ0; simpl. rewrite EQ; simpl. rewrite EQ1; auto. + constructor. -Lemma transl_funcall_internal_correct: - (forall (m : mem) (f : Csyntax.function) (vargs : list val) - (t : trace) (e : Csem.env) (m1 : mem) (lb : list block) - (m2 m3 : mem) (out : Csem.outcome) (vres : val), - Csem.alloc_variables Csem.empty_env m - (Csyntax.fn_params f ++ Csyntax.fn_vars f) e m1 lb -> - Csem.bind_parameters e m1 (Csyntax.fn_params f) vargs m2 -> - Csem.exec_stmt ge e m2 (Csyntax.fn_body f) t m3 out -> - exec_stmt_prop e m2 (Csyntax.fn_body f) t m3 out -> - Csem.outcome_result_value out (fn_return f) vres -> - eval_funcall_prop m (Internal f) vargs t (free_list m3 lb) vres). -Proof. - intros; red; intros. - (* Exploitation of typing hypothesis *) - inv WT. inv H6. - (* Exploitation of translation hypothesis *) +(* external function *) monadInv TR. - monadInv EQ. - (* Allocation of variables *) - exploit match_env_alloc_variables; eauto. - apply match_globalenv_match_env_empty. - apply match_global_typenv. - eexact (transl_fn_variables _ _ (signature_of_function f) _ _ x2 EQ0 EQ). - intros [te [ALLOCVARS MATCHENV]]. - (* Execution *) - econstructor; simpl. - (* Norepet *) - eapply transl_names_norepet; eauto. - (* Alloc *) - eexact ALLOCVARS. - (* Bind *) - eapply bind_parameters_match; eauto. - (* Execution of body *) - eapply H2; eauto. - (* Outcome_result_value *) - apply outcome_result_value_match; auto. -Qed. + exploit match_cont_is_call_cont; eauto. intros [A B]. + econstructor; split. + apply plus_one. constructor. eauto. + econstructor; eauto. -Lemma transl_funcall_external_correct: - (forall (m : mem) (id : ident) (targs : typelist) (tres : type) - (vargs : list val) (t : trace) (vres : val), - event_match (external_function id targs tres) vargs t vres -> - eval_funcall_prop m (External id targs tres) vargs t m vres). -Proof. - intros; red; intros. - monadInv TR. constructor. auto. +(* returnstate 0 *) + inv MK. + econstructor; split. + apply plus_one. constructor. constructor. + econstructor; eauto. simpl; reflexivity. constructor. constructor. + +(* returnstate 1 *) + inv MK. + econstructor; split. + apply plus_one. constructor. eapply set_call_dest_correct; eauto. + econstructor; eauto. simpl; reflexivity. constructor. constructor. +Qed. + +Lemma transl_initial_states: + forall S t S', Csem.initial_state prog S -> Csem.step ge S t S' -> + exists R, initial_state tprog R /\ match_states S R. +Proof. + intros. inv H. + exploit function_ptr_translated; eauto. intros [tf [A B]]. + assert (C: Genv.find_symbol tge (prog_main tprog) = Some b). + rewrite symbols_preserved. replace (prog_main tprog) with (prog_main prog). + exact H1. symmetry. unfold transl_program in TRANSL. + eapply transform_partial_program2_main; eauto. + exploit function_ptr_well_typed. eauto. intro WTF. + assert (exists targs, type_of_fundef f = Tfunction targs (Tint I32 Signed)). + eapply wt_program_main. eauto. + eapply Genv.find_funct_ptr_symbol_inversion; eauto. + destruct H as [targs D]. + assert (targs = Tnil). + inv H0. inv H9. simpl in D. unfold type_of_function in D. rewrite <- H4 in D. + simpl in D. congruence. + simpl in D. inv D. inv H8. inv H. + destruct targs; simpl in H5; congruence. + subst targs. + assert (funsig tf = signature_of_type Tnil (Tint I32 Signed)). + eapply sig_translated; eauto. rewrite D; auto. + econstructor; split. + econstructor; eauto. + rewrite (@Genv.init_mem_transf_partial2 _ _ _ _ transl_fundef transl_globvar prog tprog TRANSL). + constructor; auto. constructor. exact I. Qed. -Theorem transl_funcall_correct: - forall (m : mem) (f : Csyntax.fundef) (l : list val) (t : trace) - (m0 : mem) (v : val), - Csem.eval_funcall ge m f l t m0 v -> - eval_funcall_prop m f l t m0 v. -Proof - (Csem.eval_funcall_ind3 ge - exec_stmt_prop - exec_lblstmts_prop - eval_funcall_prop - - transl_Sskip_correct - transl_Sassign_correct - transl_Scall_None_correct - transl_Scall_Some_correct - transl_Ssequence_1_correct - transl_Ssequence_2_correct - transl_Sifthenelse_true_correct - transl_Sifthenelse_false_correct - transl_Sreturn_none_correct - transl_Sreturn_some_correct - transl_Sbreak_correct - transl_Scontinue_correct - transl_Swhile_false_correct - transl_Swhile_stop_correct - transl_Swhile_loop_correct - transl_Sdowhile_false_correct - transl_Sdowhile_stop_correct - transl_Sdowhile_loop_correct - transl_Sfor_start_correct - transl_Sfor_false_correct - transl_Sfor_stop_correct - transl_Sfor_loop_correct - transl_Sswitch_correct - transl_LSdefault_correct - transl_LScase_fallthrough_correct - transl_LScase_stop_correct - transl_funcall_internal_correct - transl_funcall_external_correct). - -Theorem transl_stmt_correct: - forall (e: Csem.env) (m1: mem) (s: Csyntax.statement) (t: trace) - (m2: mem) (out: Csem.outcome), - Csem.exec_stmt ge e m1 s t m2 out -> - exec_stmt_prop e m1 s t m2 out. -Proof - (Csem.exec_stmt_ind3 ge - exec_stmt_prop - exec_lblstmts_prop - eval_funcall_prop - - transl_Sskip_correct - transl_Sassign_correct - transl_Scall_None_correct - transl_Scall_Some_correct - transl_Ssequence_1_correct - transl_Ssequence_2_correct - transl_Sifthenelse_true_correct - transl_Sifthenelse_false_correct - transl_Sreturn_none_correct - transl_Sreturn_some_correct - transl_Sbreak_correct - transl_Scontinue_correct - transl_Swhile_false_correct - transl_Swhile_stop_correct - transl_Swhile_loop_correct - transl_Sdowhile_false_correct - transl_Sdowhile_stop_correct - transl_Sdowhile_loop_correct - transl_Sfor_start_correct - transl_Sfor_false_correct - transl_Sfor_stop_correct - transl_Sfor_loop_correct - transl_Sswitch_correct - transl_LSdefault_correct - transl_LScase_fallthrough_correct - transl_LScase_stop_correct - transl_funcall_internal_correct - transl_funcall_external_correct). - -(** ** Semantic preservation for divergence *) - -Lemma transl_funcall_divergence_correct: - forall m1 f params t tf, - Csem.evalinf_funcall ge m1 f params t -> - wt_fundef (global_typenv prog) f -> - transl_fundef f = OK tf -> - Csharpminor.evalinf_funcall tprog m1 tf params t - -with transl_stmt_divergence_correct: - forall e m1 s t, - Csem.execinf_stmt ge e m1 s t -> - forall tyenv nbrk ncnt ts te - (WT: wt_stmt tyenv s) - (TR: transl_statement nbrk ncnt s = OK ts) - (MENV: match_env tyenv e te), - Csharpminor.execinf_stmt tprog te m1 ts t - -with transl_lblstmt_divergence_correct: - forall s ncnt body ts tyenv e te m0 t0 m1 t1 n, - transl_lblstmts (lblstmts_length s) - (S (lblstmts_length s + ncnt)) - s body = OK ts -> - wt_lblstmts tyenv s -> - match_env tyenv e te -> - (exec_stmt tprog te m0 body t0 m1 - (outcome_block (Out_exit - (switch_target n (lblstmts_length s) (switch_table s 0)))) - /\ execinf_lblstmts ge e m1 (select_switch n s) t1) - \/ (exec_stmt tprog te m0 body t0 m1 Out_normal - /\ execinf_lblstmts ge e m1 s t1) -> - execinf_stmt_N tprog (lblstmts_length s) te m0 ts (t0 *** t1). - +Lemma transl_final_states: + forall S R r, + match_states S R -> Csem.final_state S r -> final_state R r. Proof. - (* Functions *) - intros. inv H. - (* Exploitation of typing hypothesis *) - inv H0. inv H6. - (* Exploitation of translation hypothesis *) - monadInv H1. monadInv EQ. - (* Allocation of variables *) - assert (match_env (global_typenv prog) Csem.empty_env Csharpminor.empty_env). - apply match_globalenv_match_env_empty. apply match_global_typenv. - generalize (transl_fn_variables _ _ (signature_of_function f0) _ _ x2 EQ0 EQ). - intro. - destruct (match_env_alloc_variables _ _ _ _ _ _ H2 _ _ _ H1 H5) - as [te [ALLOCVARS MATCHENV]]. - (* Execution *) - econstructor; simpl. - eapply transl_names_norepet; eauto. - eexact ALLOCVARS. - eapply bind_parameters_match; eauto. - eapply transl_stmt_divergence_correct; eauto. - -(* Statements *) - - intros. inv H; inv WT; try (generalize TR; intro TR'; monadInv TR'). - (* Scall *) - simpl in TR. - caseEq (classify_fun (typeof a)); intros; rewrite H in TR; monadInv TR. - destruct (functions_translated _ _ H2) as [tf [TFIND TFD]]. - eapply execinf_Scall. - eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto. - eapply (transl_exprlist_correct _ _ _ _ MENV _ _ H1); eauto. - eauto. - eapply transl_fundef_sig1; eauto. rewrite H3; auto. - eapply transl_funcall_divergence_correct; eauto. - eapply functions_well_typed; eauto. - (* Sseq 1 *) - apply execinf_Sseq_1. eapply transl_stmt_divergence_correct; eauto. - (* Sseq 2 *) - eapply execinf_Sseq_2. - change Out_normal with (transl_outcome nbrk ncnt Csem.Out_normal). - eapply (transl_stmt_correct _ _ _ _ _ _ H0); eauto. - eapply transl_stmt_divergence_correct; eauto. auto. - (* Sifthenelse, true *) - assert (eval_expr tprog te m1 x v1). - eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto. - destruct (make_boolean_correct_true _ _ _ _ _ _ H H1) as [vb [A B]]. - eapply execinf_Sifthenelse. eauto. apply Val.bool_of_true_val; eauto. - auto. eapply transl_stmt_divergence_correct; eauto. - (* Sifthenelse, false *) - assert (eval_expr tprog te m1 x v1). - eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto. - destruct (make_boolean_correct_false _ _ _ _ _ _ H H1) as [vb [A B]]. - eapply execinf_Sifthenelse. eauto. apply Val.bool_of_false_val; eauto. - auto. eapply transl_stmt_divergence_correct; eauto. - (* Swhile, body *) - apply execinf_Sblock. apply execinf_Sloop_body. - eapply execinf_Sseq_2. eapply exit_if_false_true; eauto. - apply execinf_Sblock. eapply transl_stmt_divergence_correct; eauto. traceEq. - (* Swhile, loop *) - apply execinf_Sblock. eapply execinf_Sloop_block. - eapply exec_Sseq_continue. eapply exit_if_false_true; eauto. - rewrite (transl_out_normal_or_continue out1 H3). - apply exec_Sblock. - eapply (transl_stmt_correct _ _ _ _ _ _ H2); eauto. reflexivity. - eapply transl_stmt_divergence_correct with (nbrk := 1%nat) (ncnt := 0%nat); eauto. - constructor; eauto. - traceEq. - (* Sdowhile, body *) - apply execinf_Sblock. apply execinf_Sloop_body. - apply execinf_Sseq_1. apply execinf_Sblock. - eapply transl_stmt_divergence_correct; eauto. - (* Sdowhile, loop *) - apply execinf_Sblock. eapply execinf_Sloop_block. - eapply exec_Sseq_continue. - rewrite (transl_out_normal_or_continue out1 H1). - apply exec_Sblock. - eapply (transl_stmt_correct _ _ _ _ _ _ H0); eauto. - eapply exit_if_false_true; eauto. reflexivity. - eapply transl_stmt_divergence_correct with (nbrk := 1%nat) (ncnt := 0%nat); eauto. - constructor; auto. - traceEq. - (* Sfor start 1 *) - simpl in TR. destruct (is_Sskip a1). - subst a1. inv H0. - monadInv TR. - apply execinf_Sseq_1. eapply transl_stmt_divergence_correct; eauto. - (* Sfor start 2 *) - destruct (transl_stmt_Sfor_start _ _ _ _ _ _ _ TR H0) as [ts1 [ts2 [EQ [TR1 TR2]]]]. - subst ts. - eapply execinf_Sseq_2. - change Out_normal with (transl_outcome nbrk ncnt Csem.Out_normal). - eapply (transl_stmt_correct _ _ _ _ _ _ H1); eauto. - eapply transl_stmt_divergence_correct; eauto. - constructor; auto. constructor. - auto. - (* Sfor_body *) - rewrite transl_stmt_Sfor_not_start in TR; monadInv TR. - apply execinf_Sblock. apply execinf_Sloop_body. - eapply execinf_Sseq_2. - eapply exit_if_false_true; eauto. - apply execinf_Sseq_1. apply execinf_Sblock. - eapply transl_stmt_divergence_correct; eauto. - traceEq. - (* Sfor next *) - rewrite transl_stmt_Sfor_not_start in TR; monadInv TR. - apply execinf_Sblock. apply execinf_Sloop_body. - eapply execinf_Sseq_2. - eapply exit_if_false_true; eauto. - eapply execinf_Sseq_2. - rewrite (transl_out_normal_or_continue out1 H3). - apply exec_Sblock. - eapply (transl_stmt_correct _ _ _ _ _ _ H2); eauto. - eapply transl_stmt_divergence_correct; eauto. - reflexivity. traceEq. - (* Sfor loop *) - generalize TR. rewrite transl_stmt_Sfor_not_start; intro TR'; monadInv TR'. - apply execinf_Sblock. eapply execinf_Sloop_block. - eapply exec_Sseq_continue. - eapply exit_if_false_true; eauto. - eapply exec_Sseq_continue. - rewrite (transl_out_normal_or_continue out1 H3). - apply exec_Sblock. - eapply (transl_stmt_correct _ _ _ _ _ _ H2); eauto. - change Out_normal with (transl_outcome nbrk ncnt Csem.Out_normal). - eapply (transl_stmt_correct _ _ _ _ _ _ H4); eauto. - reflexivity. reflexivity. - eapply transl_stmt_divergence_correct; eauto. - constructor; auto. - traceEq. - (* Sswitch *) - apply execinf_stutter with (lblstmts_length sl). - rewrite length_switch_table in EQ0. - replace (ncnt + lblstmts_length sl + 1)%nat - with (S (lblstmts_length sl + ncnt))%nat in EQ0 by omega. - change t with (E0 *** t). - eapply transl_lblstmt_divergence_correct; eauto. - left. split. apply exec_Sblock. constructor. - eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto. - auto. - -(* Labeled statements *) - intros. destruct s; simpl in *; monadInv H; inv H0. - (* 1. LSdefault *) - assert (exec_stmt tprog te m0 body t0 m1 Out_normal) by tauto. - assert (execinf_lblstmts ge e m1 (LSdefault s) t1) by tauto. - clear H2. inv H0. - change (Sblock (Sseq body x)) - with ((fun z => Sblock z) (Sseq body x)). - apply execinf_context. - eapply execinf_Sseq_2. eauto. eapply transl_stmt_divergence_correct; eauto. auto. - constructor. - (* 2. LScase *) - elim H2; clear H2. - (* 2.1 searching for the case *) - rewrite (Int.eq_sym i n). - destruct (Int.eq n i). - (* 2.1.1 found it! *) - intros [A B]. inv B. - (* 2.1.1.1 we diverge because of this case *) - destruct (transl_lblstmts_context _ _ _ _ _ EQ0) as [ctx [CTX EQ1]]. - rewrite EQ1. apply execinf_context; auto. - apply execinf_Sblock. eapply execinf_Sseq_2. eauto. - eapply transl_stmt_divergence_correct; eauto. auto. - (* 2.1.1.2 we diverge later, after falling through *) - simpl. apply execinf_sleep. - replace (t0 *** t2 *** t3) with ((t0 ** t2) *** t3). - eapply transl_lblstmt_divergence_correct with (n := n); eauto. right. split. - change Out_normal with (outcome_block Out_normal). - apply exec_Sblock. - eapply exec_Sseq_continue. eauto. - change Out_normal with (transl_outcome (S (lblstmts_length s0)) (S (S (lblstmts_length s0 + ncnt))) Csem.Out_normal). - eapply (transl_stmt_correct _ _ _ _ _ _ H8); eauto. - auto. auto. traceEq. - (* 2.1.2 still searching *) - rewrite switch_target_table_shift. intros [A B]. - apply execinf_sleep. - eapply transl_lblstmt_divergence_correct with (n := n); eauto. left. split. - fold (outcome_block (Out_exit (switch_target n (lblstmts_length s0) (switch_table s0 0)))). - apply exec_Sblock. apply exec_Sseq_stop. eauto. congruence. - auto. - (* 2.2 found the case already, falling through next cases *) - intros [A B]. inv B. - (* 2.2.1 we diverge because of this case *) - destruct (transl_lblstmts_context _ _ _ _ _ EQ0) as [ctx [CTX EQ1]]. - rewrite EQ1. apply execinf_context; auto. - apply execinf_Sblock. eapply execinf_Sseq_2. eauto. - eapply transl_stmt_divergence_correct; eauto. auto. - (* 2.2.2 we diverge later *) - simpl. apply execinf_sleep. - replace (t0 *** t2 *** t3) with ((t0 ** t2) *** t3). - eapply transl_lblstmt_divergence_correct with (n := n); eauto. right. split. - change Out_normal with (outcome_block Out_normal). - apply exec_Sblock. - eapply exec_Sseq_continue. eauto. - change Out_normal with (transl_outcome (S (lblstmts_length s0)) (S (S (lblstmts_length s0 + ncnt))) Csem.Out_normal). - eapply (transl_stmt_correct _ _ _ _ _ _ H8); eauto. - auto. auto. traceEq. + intros. inv H0. inv H. inv MK. constructor. Qed. -End CORRECTNESS. - -(** Semantic preservation for whole programs. *) - Theorem transl_program_correct: - forall prog tprog beh, - transl_program prog = OK tprog -> - Ctyping.wt_program prog -> + forall (beh: program_behavior), Csem.exec_program prog beh -> Csharpminor.exec_program tprog beh. Proof. - intros. inversion H0; subst. inv H1. - (* Termination *) - assert (exists targs, type_of_fundef f = Tfunction targs (Tint I32 Signed)). - apply wt_program_main. - eapply Genv.find_funct_ptr_symbol_inversion; eauto. - elim H1; clear H1; intros targs TYP. - assert (targs = Tnil). - inv H4; simpl in TYP. - inv H5. injection TYP. rewrite <- H10. simpl. auto. - inv TYP. inv H1. - destruct targs; simpl in H4. auto. inv H4. - subst targs. - exploit function_ptr_translated; eauto. intros [tf [TFINDF TRANSLFD]]. - apply program_terminates with b tf m1. - rewrite (symbols_preserved _ _ H). - rewrite (transform_partial_program2_main transl_fundef transl_globvar prog H). auto. - auto. - generalize (transl_fundef_sig2 _ _ _ _ TRANSLFD TYP). simpl; auto. - rewrite (@Genv.init_mem_transf_partial2 _ _ _ _ transl_fundef transl_globvar prog tprog H). - generalize (transl_funcall_correct _ _ H0 H _ _ _ _ _ _ H4). - intro. eapply H1. - eapply function_ptr_well_typed; eauto. - auto. - (* Divergence *) - assert (exists targs, type_of_fundef f = Tfunction targs (Tint I32 Signed)). - apply wt_program_main. - eapply Genv.find_funct_ptr_symbol_inversion; eauto. - elim H1; clear H1; intros targs TYP. - assert (targs = Tnil). - inv H4; simpl in TYP. - inv H5. injection TYP. rewrite <- H9. simpl. auto. - subst targs. - exploit function_ptr_translated; eauto. intros [tf [TFINDF TRANSLFD]]. - apply program_diverges with b tf. - rewrite (symbols_preserved _ _ H). - rewrite (transform_partial_program2_main transl_fundef transl_globvar prog H). auto. - auto. - generalize (transl_fundef_sig2 _ _ _ _ TRANSLFD TYP). simpl; auto. - rewrite (@Genv.init_mem_transf_partial2 _ _ _ _ transl_fundef transl_globvar prog tprog H). - eapply transl_funcall_divergence_correct; eauto. - eapply function_ptr_well_typed; eauto. + set (order := fun (S1 S2: Csem.state) => False). + assert (transl_step': + forall S1 t S2, Csem.step ge S1 t S2 -> + forall T1, match_states S1 T1 -> + exists T2, + (plus step tgve T1 t T2 \/ star step tgve T1 t T2 /\ order S2 S1) + /\ match_states S2 T2). + intros. exploit transl_step; eauto. intros [T2 [A B]]. + exists T2; split. auto. auto. + intros. inv H. + assert (exists t1, exists s1, Csem.step (Genv.globalenv prog) s t1 s1). + inv H1. inv H0; inv H2. exists t1; exists s2; auto. + destruct H as [t1 [s1 ST]]. + exploit transl_initial_states; eauto. intros [R [A B]]. + exploit simulation_star_star; eauto. intros [R' [C D]]. + econstructor; eauto. eapply transl_final_states; eauto. + assert (exists t1, exists s1, Csem.step (Genv.globalenv prog) s t1 s1). + inv H1. exists t; exists s2; auto. + destruct H as [t1 [s1 ST]]. + exploit transl_initial_states; eauto. intros [R [A B]]. + exploit simulation_star_forever; eauto. + unfold order; red. intros. constructor; intros. contradiction. + intro C. + econstructor; eauto. Qed. + +End CORRECTNESS. |