From c48b9097201dc9a1e326acdbce491fe16cab01e6 Mon Sep 17 00:00:00 2001 From: xleroy Date: Tue, 28 Aug 2007 12:57:58 +0000 Subject: Fusion de la branche restr-cminor. En Clight, C#minor et Cminor, les expressions sont maintenant pures et les appels de fonctions sont des statements. Ajout de semantiques coinductives pour la divergence en Clight, C#minor, Cminor. Preuve de preservation semantique pour les programmes qui divergent. git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@409 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e --- cfrontend/Cshmgenproof3.v | 1357 ++++++++++++++++++++++++++++----------------- 1 file changed, 840 insertions(+), 517 deletions(-) (limited to 'cfrontend/Cshmgenproof3.v') diff --git a/cfrontend/Cshmgenproof3.v b/cfrontend/Cshmgenproof3.v index 10f48f61..54f9b772 100644 --- a/cfrontend/Cshmgenproof3.v +++ b/cfrontend/Cshmgenproof3.v @@ -10,6 +10,7 @@ Require Import Values. Require Import Events. Require Import Mem. Require Import Globalenvs. +Require Import Smallstep. Require Import Csyntax. Require Import Csem. Require Import Ctyping. @@ -307,13 +308,13 @@ Qed. (** Correctness of the code generated by [var_get]. *) Lemma var_get_correct: - forall e m id ty loc ofs v tyenv code te le, - Csem.eval_lvalue ge e m (Expr (Csyntax.Evar id) ty) E0 m loc ofs -> + forall e m id ty loc ofs v tyenv code te, + Csem.eval_lvalue ge e m (Expr (Csyntax.Evar id) ty) loc ofs -> load_value_of_type ty m loc ofs = Some v -> wt_expr tyenv (Expr (Csyntax.Evar id) ty) -> var_get id ty = OK code -> match_env tyenv e te -> - eval_expr tprog le te m code E0 m v. + eval_expr tprog te m code v. Proof. intros. inversion H1; subst; clear H1. unfold load_value_of_type in H0. @@ -356,14 +357,14 @@ Qed. (** Correctness of the code generated by [var_set]. *) Lemma var_set_correct: - forall e m id ty m1 loc ofs t1 m2 v t2 m3 tyenv code te rhs, - Csem.eval_lvalue ge e m (Expr (Csyntax.Evar id) ty) t1 m1 loc ofs -> - store_value_of_type ty m2 loc ofs v = Some m3 -> + forall e m id ty loc ofs v m' tyenv code te rhs, + 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 nil te m1 rhs t2 m2 v -> - exec_stmt tprog te m code (t1 ** t2) m3 Out_normal. + eval_expr tprog te m rhs v -> + exec_stmt tprog te m code E0 m' Out_normal. Proof. intros. inversion H1; subst; clear H1. unfold store_value_of_type in H0. @@ -372,16 +373,16 @@ Proof. (* access mode By_value *) intros chunk ACC. rewrite ACC in H0. rewrite ACC in H2. inversion H2; clear H2; subst. - inversion H; subst; clear H; rewrite E0_left. + 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 eval_Sassign. eauto. - eapply eval_var_ref_local. eauto. assumption. + eapply exec_Sassign. eauto. + econstructor. eapply eval_var_ref_local. eauto. assumption. (* global variable *) exploit me_global; eauto. intros [A B]. - eapply eval_Sassign. eauto. - eapply eval_var_ref_global. auto. + eapply exec_Sassign. eauto. + econstructor. eapply eval_var_ref_global. auto. fold tge. rewrite symbols_preserved. eauto. eauto. assumption. (* access mode By_reference *) @@ -390,158 +391,145 @@ Proof. intros. rewrite H1 in H0; discriminate. Qed. -(** * Proof of semantic simulation *) +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 -> + 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 *) + 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. +Qed. + +(** * Proof of semantic preservation *) + +(** ** Semantic preservation for expressions *) -(** The proof of semantic preservation for this compiler pass relies - on simulation diagrams of the following form: +(** The proof of semantic preservation for the translation of expressions + relies on simulation diagrams of the following form: << - e, m1, a ------------------- te, m1, ta + e, m, a ------------------- te, m, ta | | t| |t | | v v - e, m2, v ------------------- te, m2, v + e, m, v ------------------- te, m, v >> - Left: evaluation of expression [a] in Clight. + Left: evaluation of r-value expression [a] in Clight. Right: evaluation of its translation [ta] in Csharpminor. Top (precondition): matching between environments [e], [te], plus well-typedness of expression [a]. - Bottom (postcondition): the result values [v] and final memory states [m2] + Bottom (postcondition): the result values [v] are identical in both evaluations. We state these diagrams as the following properties, parameterized by the Clight evaluation. *) -Definition eval_expr_prop - (e: Csem.env) (m1: mem) (a: Csyntax.expr) (t: trace) (m2: mem) (v: val) : Prop := - forall tyenv ta te tle +Section EXPR. + +Variable e: Csem.env. +Variable m: mem. +Variable te: Csharpminor.env. +Variable tyenv: typenv. +Hypothesis MENV: match_env tyenv e te. + +Definition eval_expr_prop (a: Csyntax.expr) (v: val) : Prop := + forall ta (WT: wt_expr tyenv a) - (TR: transl_expr a = OK ta) - (MENV: match_env tyenv e te), - Csharpminor.eval_expr tprog tle te m1 ta t m2 v. + (TR: transl_expr a = OK ta), + Csharpminor.eval_expr tprog te m ta v. -Definition eval_lvalue_prop - (e: Csem.env) (m1: mem) (a: Csyntax.expr) (t: trace) - (m2: mem) (b: block) (ofs: int) : Prop := - forall tyenv ta te tle +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) - (MENV: match_env tyenv e te), - Csharpminor.eval_expr tprog tle te m1 ta t m2 (Vptr b ofs). + (TR: transl_lvalue a = OK ta), + Csharpminor.eval_expr tprog te m ta (Vptr b ofs). -Definition eval_exprlist_prop - (e: Csem.env) (m1: mem) (al: Csyntax.exprlist) (t: trace) - (m2: mem) (vl: list val) : Prop := - forall tyenv tal te tle +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) - (MENV: match_env tyenv e te), - Csharpminor.eval_exprlist tprog tle te m1 tal t m2 vl. - -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. + (TR: transl_exprlist al = OK tal), + Csharpminor.eval_exprlist tprog te m tal vl. -(** The proof of semantic preservation is by induction on the Clight - evaluation derivation. Since this proof is large, we break it - into one lemma for each Clight evaluation rule. *) +(* Check (eval_expr_ind2 ge e m eval_expr_prop eval_lvalue_prop).*) Lemma transl_Econst_int_correct: - (forall (e : Csem.env) (m : mem) (i : int) (ty : type), - eval_expr_prop e m (Expr (Econst_int i) ty) E0 m (Vint i)). + forall (i : int) (ty : type), + eval_expr_prop (Expr (Econst_int i) ty) (Vint i). Proof. intros; red; intros. monadInv TR. apply make_intconst_correct. Qed. Lemma transl_Econst_float_correct: - (forall (e : Csem.env) (m : mem) (f0 : float) (ty : type), - eval_expr_prop e m (Expr (Econst_float f0) ty) E0 m (Vfloat f0)). + forall (f0 : float) (ty : type), + eval_expr_prop (Expr (Econst_float f0) ty) (Vfloat f0). Proof. intros; red; intros. monadInv TR. apply make_floatconst_correct. Qed. Lemma transl_Elvalue_correct: - (forall (e : Csem.env) (m : mem) (a : expr_descr) (ty : type) - (t : trace) (m1 : mem) (loc : block) (ofs : int) (v : val), - eval_lvalue ge e m (Expr a ty) t m1 loc ofs -> - eval_lvalue_prop e m (Expr a ty) t m1 loc ofs -> - load_value_of_type ty m1 loc ofs = Some v -> - eval_expr_prop e m (Expr a ty) t m1 v). + forall (a : expr_descr) (ty : type) (loc : block) (ofs : int) + (v : val), + eval_lvalue ge e m (Expr a ty) loc ofs -> + eval_lvalue_prop (Expr a ty) loc ofs -> + load_value_of_type ty m loc ofs = Some v -> + eval_expr_prop (Expr a ty) v. Proof. intros; red; intros. exploit transl_expr_lvalue; eauto. intros [[id [EQ VARGET]] | [tb [TRLVAL MKLOAD]]]. (* Case a is a variable *) - subst a. - assert (t = E0 /\ m1 = m). inversion H; auto. - destruct H2; subst t m1. - eapply var_get_correct; eauto. + subst a. eapply var_get_correct; eauto. (* Case a is another lvalue *) eapply make_load_correct; eauto. Qed. Lemma transl_Eaddrof_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t : trace) - (m1 : mem) (loc : block) (ofs : int) (ty : type), - eval_lvalue ge e m a t m1 loc ofs -> - eval_lvalue_prop e m a t m1 loc ofs -> - eval_expr_prop e m (Expr (Csyntax.Eaddrof a) ty) t m1 (Vptr loc ofs)). + forall (a : Csyntax.expr) (ty : type) (loc : block) (ofs : int), + eval_lvalue ge e m a loc ofs -> + eval_lvalue_prop a loc ofs -> + eval_expr_prop (Expr (Csyntax.Eaddrof a) ty) (Vptr loc ofs). Proof. intros; red; intros. inversion WT; clear WT; subst. simpl in TR. eauto. Qed. Lemma transl_Esizeof_correct: - (forall (e : Csem.env) (m : mem) (ty' ty : type), - eval_expr_prop e m (Expr (Esizeof ty') ty) E0 m - (Vint (Int.repr (Csyntax.sizeof ty')))). + forall ty' ty : type, + eval_expr_prop (Expr (Esizeof ty') ty) + (Vint (Int.repr (Csyntax.sizeof ty'))). Proof. intros; red; intros. monadInv TR. apply make_intconst_correct. Qed. Lemma transl_Eunop_correct: - (forall (e : Csem.env) (m : mem) (op : Csyntax.unary_operation) - (a : Csyntax.expr) (ty : type) (t : trace) (m1 : mem) (v1 v : val), - Csem.eval_expr ge e m a t m1 v1 -> - eval_expr_prop e m a t m1 v1 -> - sem_unary_operation op v1 (typeof a) = Some v -> - eval_expr_prop e m (Expr (Csyntax.Eunop op a) ty) t m1 v). + forall (op : Csyntax.unary_operation) (a : Csyntax.expr) (ty : type) + (v1 v : val), + Csem.eval_expr ge e m a v1 -> + eval_expr_prop a v1 -> + sem_unary_operation op v1 (typeof a) = Some v -> + eval_expr_prop (Expr (Csyntax.Eunop op a) ty) v. Proof. intros; red; intros. inversion WT; clear WT; subst. @@ -550,15 +538,14 @@ Proof. Qed. Lemma transl_Ebinop_correct: - (forall (e : Csem.env) (m : mem) (op : Csyntax.binary_operation) - (a1 a2 : Csyntax.expr) (ty : type) (t1 : trace) (m1 : mem) - (v1 : val) (t2 : trace) (m2 : mem) (v2 v : val), - Csem.eval_expr ge e m a1 t1 m1 v1 -> - eval_expr_prop e m a1 t1 m1 v1 -> - Csem.eval_expr ge e m1 a2 t2 m2 v2 -> - eval_expr_prop e m1 a2 t2 m2 v2 -> - sem_binary_operation op v1 (typeof a1) v2 (typeof a2) m2 = Some v -> - eval_expr_prop e m (Expr (Csyntax.Ebinop op a1 a2) ty) (t1 ** t2) m2 v). + forall (op : Csyntax.binary_operation) (a1 a2 : Csyntax.expr) + (ty : type) (v1 v2 v : val), + Csem.eval_expr ge e m a1 v1 -> + eval_expr_prop a1 v1 -> + Csem.eval_expr ge e m a2 v2 -> + eval_expr_prop a2 v2 -> + sem_binary_operation op v1 (typeof a1) v2 (typeof a2) m = Some v -> + eval_expr_prop (Expr (Csyntax.Ebinop op a1 a2) ty) v. Proof. intros; red; intros. inversion WT; clear WT; subst. @@ -567,137 +554,93 @@ Proof. Qed. Lemma transl_Eorbool_1_correct: - (forall (e : Csem.env) (m : mem) (a1 a2 : Csyntax.expr) (t : trace) - (m1 : mem) (v1 : val) (ty : type), - Csem.eval_expr ge e m a1 t m1 v1 -> - eval_expr_prop e m a1 t m1 v1 -> - is_true v1 (typeof a1) -> - eval_expr_prop e m (Expr (Eorbool a1 a2) ty) t m1 Vtrue). + forall (a1 a2 : Csyntax.expr) (ty : type) (v1 : val), + Csem.eval_expr ge e m a1 v1 -> + eval_expr_prop a1 v1 -> + is_true v1 (typeof a1) -> + eval_expr_prop (Expr (Eorbool a1 a2) ty) Vtrue. Proof. intros; red; intros. inversion WT; clear WT; subst. monadInv TR. unfold make_orbool. exploit make_boolean_correct_true; eauto. intros [vb [EVAL ISTRUE]]. - eapply eval_Econdition_true; eauto. - unfold Vtrue; apply make_intconst_correct. traceEq. + eapply eval_Econdition; eauto. apply Val.bool_of_true_val; eauto. + simpl. unfold Vtrue; apply make_intconst_correct. Qed. Lemma transl_Eorbool_2_correct: - (forall (e : Csem.env) (m : mem) (a1 a2 : Csyntax.expr) (ty : type) - (t1 : trace) (m1 : mem) (v1 : val) (t2 : trace) (m2 : mem) - (v2 v : val), - Csem.eval_expr ge e m a1 t1 m1 v1 -> - eval_expr_prop e m a1 t1 m1 v1 -> - is_false v1 (typeof a1) -> - Csem.eval_expr ge e m1 a2 t2 m2 v2 -> - eval_expr_prop e m1 a2 t2 m2 v2 -> - bool_of_val v2 (typeof a2) v -> - eval_expr_prop e m (Expr (Eorbool a1 a2) ty) (t1 ** t2) m2 v). + forall (a1 a2 : Csyntax.expr) (ty : type) (v1 v2 v : val), + Csem.eval_expr ge e m a1 v1 -> + eval_expr_prop a1 v1 -> + is_false v1 (typeof a1) -> + Csem.eval_expr ge e m a2 v2 -> + eval_expr_prop a2 v2 -> + bool_of_val v2 (typeof a2) v -> + eval_expr_prop (Expr (Eorbool a1 a2) ty) v. Proof. intros; red; intros. inversion WT; clear WT; subst. monadInv TR. unfold make_orbool. exploit make_boolean_correct_false. eapply H0; eauto. eauto. intros [vb [EVAL ISFALSE]]. - eapply eval_Econdition_false; eauto. - inversion H4; subst. + eapply eval_Econdition; eauto. apply Val.bool_of_false_val; eauto. + simpl. inversion H4; subst. exploit make_boolean_correct_true. eapply H3; eauto. eauto. intros [vc [EVAL' ISTRUE']]. - eapply eval_Econdition_true; eauto. - unfold Vtrue; apply make_intconst_correct. traceEq. + eapply eval_Econdition; eauto. apply Val.bool_of_true_val; eauto. + unfold Vtrue; apply make_intconst_correct. exploit make_boolean_correct_false. eapply H3; eauto. eauto. intros [vc [EVAL' ISFALSE']]. - eapply eval_Econdition_false; eauto. - unfold Vfalse; apply make_intconst_correct. traceEq. + eapply eval_Econdition; eauto. apply Val.bool_of_false_val; eauto. + unfold Vfalse; apply make_intconst_correct. Qed. Lemma transl_Eandbool_1_correct: - (forall (e : Csem.env) (m : mem) (a1 a2 : Csyntax.expr) (t : trace) - (m1 : mem) (v1 : val) (ty : type), - Csem.eval_expr ge e m a1 t m1 v1 -> - eval_expr_prop e m a1 t m1 v1 -> - is_false v1 (typeof a1) -> - eval_expr_prop e m (Expr (Eandbool a1 a2) ty) t m1 Vfalse). + forall (a1 a2 : Csyntax.expr) (ty : type) (v1 : val), + Csem.eval_expr ge e m a1 v1 -> + eval_expr_prop a1 v1 -> + is_false v1 (typeof a1) -> + eval_expr_prop (Expr (Eandbool a1 a2) ty) Vfalse. Proof. intros; red; intros. inversion WT; clear WT; subst. monadInv TR. unfold make_andbool. exploit make_boolean_correct_false; eauto. intros [vb [EVAL ISFALSE]]. - eapply eval_Econdition_false; eauto. - unfold Vfalse; apply make_intconst_correct. traceEq. + eapply eval_Econdition; eauto. apply Val.bool_of_false_val; eauto. + unfold Vfalse; apply make_intconst_correct. Qed. Lemma transl_Eandbool_2_correct: - (forall (e : Csem.env) (m : mem) (a1 a2 : Csyntax.expr) (ty : type) - (t1 : trace) (m1 : mem) (v1 : val) (t2 : trace) (m2 : mem) - (v2 v : val), - Csem.eval_expr ge e m a1 t1 m1 v1 -> - eval_expr_prop e m a1 t1 m1 v1 -> - is_true v1 (typeof a1) -> - Csem.eval_expr ge e m1 a2 t2 m2 v2 -> - eval_expr_prop e m1 a2 t2 m2 v2 -> - bool_of_val v2 (typeof a2) v -> - eval_expr_prop e m (Expr (Eandbool a1 a2) ty) (t1 ** t2) m2 v). + forall (a1 a2 : Csyntax.expr) (ty : type) (v1 v2 v : val), + Csem.eval_expr ge e m a1 v1 -> + eval_expr_prop a1 v1 -> + is_true v1 (typeof a1) -> + Csem.eval_expr ge e m a2 v2 -> + eval_expr_prop a2 v2 -> + bool_of_val v2 (typeof a2) v -> + eval_expr_prop (Expr (Eandbool a1 a2) ty) v. Proof. intros; red; intros. inversion WT; clear WT; subst. monadInv TR. unfold make_andbool. exploit make_boolean_correct_true. eapply H0; eauto. eauto. intros [vb [EVAL ISTRUE]]. - eapply eval_Econdition_true; eauto. - inversion H4; subst. + eapply eval_Econdition; eauto. apply Val.bool_of_true_val; eauto. + simpl. inversion H4; subst. exploit make_boolean_correct_true. eapply H3; eauto. eauto. intros [vc [EVAL' ISTRUE']]. - eapply eval_Econdition_true; eauto. - unfold Vtrue; apply make_intconst_correct. traceEq. + eapply eval_Econdition; eauto. apply Val.bool_of_true_val; eauto. + unfold Vtrue; apply make_intconst_correct. exploit make_boolean_correct_false. eapply H3; eauto. eauto. intros [vc [EVAL' ISFALSE']]. - eapply eval_Econdition_false; eauto. - unfold Vfalse; apply make_intconst_correct. traceEq. + eapply eval_Econdition; eauto. apply Val.bool_of_false_val; eauto. + unfold Vfalse; apply make_intconst_correct. Qed. Lemma transl_Ecast_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (ty : type) - (t : trace) (m1 : mem) (v1 v : val), - Csem.eval_expr ge e m a t m1 v1 -> - eval_expr_prop e m a t m1 v1 -> - cast v1 (typeof a) ty v -> - eval_expr_prop e m (Expr (Ecast ty a) ty) t m1 v). + forall (a : Csyntax.expr) (ty : type) (v1 v : val), + Csem.eval_expr ge e m a v1 -> + eval_expr_prop a v1 -> + cast v1 (typeof a) ty v -> eval_expr_prop (Expr (Ecast ty a) ty) v. Proof. intros; red; intros. inversion WT; clear WT; subst. monadInv TR. eapply make_cast_correct; eauto. Qed. -Lemma transl_Ecall_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) - (bl : Csyntax.exprlist) (ty : type) (m3 : mem) (vres : val) - (t1 : trace) (m1 : mem) (vf : val) (t2 : trace) (m2 : mem) - (vargs : list val) (f : Csyntax.fundef) (t3 : trace), - Csem.eval_expr ge e m a t1 m1 vf -> - eval_expr_prop e m a t1 m1 vf -> - Csem.eval_exprlist ge e m1 bl t2 m2 vargs -> - eval_exprlist_prop e m1 bl t2 m2 vargs -> - Genv.find_funct ge vf = Some f -> - type_of_fundef f = typeof a -> - Csem.eval_funcall ge m2 f vargs t3 m3 vres -> - eval_funcall_prop m2 f vargs t3 m3 vres -> - eval_expr_prop e m (Expr (Csyntax.Ecall a bl) ty) (t1 ** t2 ** t3) m3 - vres). -Proof. - intros; red; intros. - inversion WT; clear WT; subst. - simpl in TR. - caseEq (classify_fun (typeof a)). - 2: intros; rewrite H7 in TR; discriminate. - intros targs tres EQ. rewrite EQ in TR. - monadInv TR. - rewrite <- H4 in EQ. - exploit functions_translated; eauto. intros [tf [FIND TRL]]. - econstructor. - eapply H0; eauto. - eapply H2; eauto. - eexact FIND. - eapply transl_fundef_sig1; eauto. - eapply H6; eauto. - eapply functions_well_typed; eauto. - auto. -Qed. - Lemma transl_Evar_local_correct: - (forall (e : Csem.env) (m : mem) (id : positive) (l : block) - (ty : type), - e ! id = Some l -> - eval_lvalue_prop e m (Expr (Csyntax.Evar id) ty) E0 m l Int.zero). + forall (id : ident) (l : block) (ty : type), + e ! id = Some l -> + 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]]. @@ -705,11 +648,10 @@ Proof. Qed. Lemma transl_Evar_global_correct: - (forall (e : PTree.t block) (m : mem) (id : positive) (l : block) - (ty : type), - e ! id = None -> - Genv.find_symbol ge id = Some l -> - eval_lvalue_prop e m (Expr (Csyntax.Evar id) ty) E0 m l Int.zero). + forall (id : ident) (l : block) (ty : type), + e ! id = None -> + Genv.find_symbol ge id = Some l -> + eval_lvalue_prop (Expr (Csyntax.Evar id) ty) l Int.zero. Proof. intros; red; intros. inversion WT; clear WT; subst. monadInv TR. exploit (me_global _ _ _ MENV); eauto. intros [A B]. @@ -718,83 +660,183 @@ Proof. Qed. Lemma transl_Ederef_correct: - (forall (e : Csem.env) (m m1 : mem) (a : Csyntax.expr) (t : trace) - (ofs : int) (ty : type) (l : block), - Csem.eval_expr ge e m a t m1 (Vptr l ofs) -> - eval_expr_prop e m a t m1 (Vptr l ofs) -> - eval_lvalue_prop e m (Expr (Ederef a) ty) t m1 l ofs). + forall (a : Csyntax.expr) (ty : type) (l : block) (ofs : int), + Csem.eval_expr ge e m a (Vptr l ofs) -> + eval_expr_prop a (Vptr l ofs) -> + eval_lvalue_prop (Expr (Ederef a) ty) l ofs. Proof. intros; red; intros. inversion WT; clear WT; subst. simpl in TR. eauto. Qed. Lemma transl_Eindex_correct: - (forall (e : Csem.env) (m : mem) (a1 : Csyntax.expr) (t1 : trace) - (m1 : mem) (v1 : val) (a2 : Csyntax.expr) (t2 : trace) (m2 : mem) - (v2 : val) (l : block) (ofs : int) (ty : type), - Csem.eval_expr ge e m a1 t1 m1 v1 -> - eval_expr_prop e m a1 t1 m1 v1 -> - Csem.eval_expr ge e m1 a2 t2 m2 v2 -> - eval_expr_prop e m1 a2 t2 m2 v2 -> - sem_add v1 (typeof a1) v2 (typeof a2) = Some (Vptr l ofs) -> - eval_lvalue_prop e m (Expr (Eindex a1 a2) ty) (t1 ** t2) m2 l ofs). + forall (a1 a2 : Csyntax.expr) (ty : type) (v1 v2 : val) (l : block) + (ofs : int), + Csem.eval_expr ge e m a1 v1 -> + eval_expr_prop a1 v1 -> + Csem.eval_expr ge e m a2 v2 -> + eval_expr_prop a2 v2 -> + sem_add v1 (typeof a1) v2 (typeof a2) = Some (Vptr l ofs) -> + eval_lvalue_prop (Expr (Eindex a1 a2) ty) l ofs. Proof. intros; red; intros. inversion WT; clear WT; subst. simpl in TR. monadInv TR. eapply (make_add_correct tprog); eauto. Qed. Lemma transl_Efield_struct_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t : trace) - (m1 : mem) (l : block) (ofs : int) (id: ident) (fList : fieldlist) (i : ident) - (ty : type) (delta : Z), - eval_lvalue ge e m a t m1 l ofs -> - eval_lvalue_prop e m a t m1 l ofs -> - typeof a = Tstruct id fList -> - field_offset i fList = OK delta -> - eval_lvalue_prop e m (Expr (Efield a i) ty) t m1 l - (Int.add ofs (Int.repr delta))). + forall (a : Csyntax.expr) (i : ident) (ty : type) (l : block) + (ofs : int) (id : ident) (fList : fieldlist) (delta : Z), + eval_lvalue ge e m a l ofs -> + eval_lvalue_prop a l ofs -> + typeof a = Tstruct id fList -> + field_offset i fList = OK delta -> + eval_lvalue_prop (Expr (Efield a i) ty) l (Int.add ofs (Int.repr delta)). Proof. intros; red; intros. inversion WT; clear WT; subst. simpl in TR. rewrite H1 in TR. monadInv TR. - econstructor; eauto. + eapply eval_Ebinop; eauto. apply make_intconst_correct. - simpl. congruence. traceEq. + simpl. congruence. Qed. Lemma transl_Efield_union_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t : trace) - (m1 : mem) (l : block) (ofs : int) (id: ident) (fList : fieldlist) (i : ident) - (ty : type), - eval_lvalue ge e m a t m1 l ofs -> - eval_lvalue_prop e m a t m1 l ofs -> - typeof a = Tunion id fList -> - eval_lvalue_prop e m (Expr (Efield a i) ty) t m1 l ofs). + forall (a : Csyntax.expr) (i : ident) (ty : type) (l : block) + (ofs : int) (id : ident) (fList : fieldlist), + eval_lvalue ge e m a l ofs -> + eval_lvalue_prop a l ofs -> + typeof a = Tunion id fList -> + eval_lvalue_prop (Expr (Efield a i) ty) l ofs. Proof. intros; red; intros. inversion WT; clear WT; subst. simpl in TR. rewrite H1 in TR. eauto. Qed. -Lemma transl_Enil_correct: - (forall (e : Csem.env) (m : mem), - eval_exprlist_prop e m Csyntax.Enil E0 m nil). -Proof. - intros; red; intros. monadInv TR. constructor. -Qed. +Lemma transl_expr_correct: + forall a v, + Csem.eval_expr ge e m a v -> + eval_expr_prop a v. +Proof + (eval_expr_ind2 ge e m eval_expr_prop eval_lvalue_prop + transl_Econst_int_correct + transl_Econst_float_correct + transl_Elvalue_correct + transl_Eaddrof_correct + transl_Esizeof_correct + transl_Eunop_correct + transl_Ebinop_correct + transl_Eorbool_1_correct + transl_Eorbool_2_correct + transl_Eandbool_1_correct + transl_Eandbool_2_correct + transl_Ecast_correct + transl_Evar_local_correct + transl_Evar_global_correct + transl_Ederef_correct + transl_Eindex_correct + transl_Efield_struct_correct + transl_Efield_union_correct). -Lemma transl_Econs_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) - (bl : Csyntax.exprlist) (t1 : trace) (m1 : mem) (v : val) - (t2 : trace) (m2 : mem) (vl : list val), - Csem.eval_expr ge e m a t1 m1 v -> - eval_expr_prop e m a t1 m1 v -> - Csem.eval_exprlist ge e m1 bl t2 m2 vl -> - eval_exprlist_prop e m1 bl t2 m2 vl -> - eval_exprlist_prop e m (Csyntax.Econs a bl) (t1 ** t2) m2 (v :: vl)). +Lemma transl_lvalue_correct: + forall a blk ofs, + Csem.eval_lvalue ge e m a blk ofs -> + eval_lvalue_prop a blk ofs. +Proof + (eval_lvalue_ind2 ge e m eval_expr_prop eval_lvalue_prop + transl_Econst_int_correct + transl_Econst_float_correct + transl_Elvalue_correct + transl_Eaddrof_correct + transl_Esizeof_correct + transl_Eunop_correct + transl_Ebinop_correct + transl_Eorbool_1_correct + transl_Eorbool_2_correct + transl_Eandbool_1_correct + transl_Eandbool_2_correct + transl_Ecast_correct + transl_Evar_local_correct + transl_Evar_global_correct + transl_Ederef_correct + transl_Eindex_correct + transl_Efield_struct_correct + transl_Efield_union_correct). + +Lemma transl_exprlist_correct: + forall al vl, + Csem.eval_exprlist ge e m al vl -> + eval_exprlist_prop al vl. Proof. - intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR. - econstructor; eauto. + induction 1; red; intros; monadInv TR; inv WT. + constructor. + constructor. eapply (transl_expr_correct _ _ H); eauto. eauto. 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. + +(* +Set 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). @@ -802,28 +844,13 @@ Proof. intros; red; intros. monadInv TR. simpl. constructor. Qed. -Lemma transl_Sexpr_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t : trace) - (m1 : mem) (v : val), - Csem.eval_expr ge e m a t m1 v -> - eval_expr_prop e m a t m1 v -> - exec_stmt_prop e m (Csyntax.Sexpr a) t m1 Csem.Out_normal). -Proof. - intros; red; intros; simpl. inversion WT; clear WT; subst. - monadInv TR. econstructor; eauto. -Qed. - Lemma transl_Sassign_correct: - (forall (e : Csem.env) (m : mem) (a1 a2 : Csyntax.expr) (t1 : trace) - (m1 : mem) (loc : block) (ofs : int) (t2 : trace) (m2 : mem) - (v2 : val) (m3 : mem), - eval_lvalue ge e m a1 t1 m1 loc ofs -> - eval_lvalue_prop e m a1 t1 m1 loc ofs -> - Csem.eval_expr ge e m1 a2 t2 m2 v2 -> - eval_expr_prop e m1 a2 t2 m2 v2 -> - store_value_of_type (typeof a1) m2 loc ofs v2 = Some m3 -> - exec_stmt_prop e m (Csyntax.Sassign a1 a2) (t1 ** t2) m3 - Csem.Out_normal). + 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. @@ -832,12 +859,70 @@ Proof. (* a = variable id *) intros id ISVAR. rewrite ISVAR in TR. generalize (is_variable_correct _ _ ISVAR). intro EQ. - rewrite EQ in H; rewrite EQ in H0; rewrite EQ in H6. + rewrite EQ in H; rewrite EQ in H4. monadInv TR. - eapply var_set_correct; eauto. + 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: @@ -867,35 +952,39 @@ Proof. Qed. Lemma transl_Sifthenelse_true_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) - (s1 s2 : statement) (t1 : trace) (m1 : mem) (v1 : val) (t2 : trace) - (m2 : mem) (out : Csem.outcome), - Csem.eval_expr ge e m a t1 m1 v1 -> - eval_expr_prop e m a t1 m1 v1 -> + (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 m1 s1 t2 m2 out -> - exec_stmt_prop e m1 s1 t2 m2 out -> - exec_stmt_prop e m (Csyntax.Sifthenelse a s1 s2) (t1 ** t2) m2 out). + 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 H0; eauto. eauto. intros [vb [EVAL ISTRUE]]. - eapply exec_Sifthenelse_true; eauto. + 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) (t1 : trace) (m1 : mem) (v1 : val) (t2 : trace) - (m2 : mem) (out : Csem.outcome), - Csem.eval_expr ge e m a t1 m1 v1 -> - eval_expr_prop e m a t1 m1 v1 -> + (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 m1 s2 t2 m2 out -> - exec_stmt_prop e m1 s2 t2 m2 out -> - exec_stmt_prop e m (Csyntax.Sifthenelse a s1 s2) (t1 ** t2) m2 out). + 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 H0; eauto. eauto. intros [vb [EVAL ISFALSE]]. - eapply exec_Sifthenelse_false; eauto. + 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: @@ -907,15 +996,13 @@ Proof. Qed. Lemma transl_Sreturn_some_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t : trace) - (m1 : mem) (v : val), - Csem.eval_expr ge e m a t m1 v -> - eval_expr_prop e m a t m1 v -> - exec_stmt_prop e m (Csyntax.Sreturn (Some a)) t m1 - (Csem.Out_return (Some v))). + (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. inversion WT; clear WT; subst. simpl in TR; monadInv TR. - simpl. eapply exec_Sreturn_some; eauto. + 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: @@ -935,47 +1022,51 @@ Proof. Qed. Lemma exit_if_false_true: - forall a ts e m1 t m2 v tyenv te, + forall a ts e m v tyenv te, exit_if_false a = OK ts -> - eval_expr_prop e m1 a t m2 v -> + Csem.eval_expr ge e m a v -> + is_true v (typeof a) -> match_env tyenv e te -> wt_expr tyenv a -> - is_true v (typeof a) -> - exec_stmt tprog te m1 ts t m2 Out_normal. + exec_stmt tprog te m ts E0 m Out_normal. Proof. - intros. monadInv H. - exploit make_boolean_correct_true. eapply H0; eauto. eauto. + intros. monadInv H. + exploit make_boolean_correct_true. + eapply (transl_expr_correct _ _ _ _ H2 _ _ H0); eauto. + eauto. intros [vb [EVAL ISTRUE]]. - eapply exec_Sifthenelse_true with (v1 := vb); eauto. - constructor. traceEq. + eapply exec_Sifthenelse with (v := vb); eauto. + apply Val.bool_of_true_val; eauto. + constructor. Qed. Lemma exit_if_false_false: - forall a ts e m1 t m2 v tyenv te, + forall a ts e m v tyenv te, exit_if_false a = OK ts -> - eval_expr_prop e m1 a t m2 v -> + Csem.eval_expr ge e m a v -> + is_false v (typeof a) -> match_env tyenv e te -> wt_expr tyenv a -> - is_false v (typeof a) -> - exec_stmt tprog te m1 ts t m2 (Out_exit 0). + exec_stmt tprog te m ts E0 m (Out_exit 0). Proof. - intros. monadInv H. - exploit make_boolean_correct_false. eapply H0; eauto. eauto. + intros. monadInv H. + exploit make_boolean_correct_false. + eapply (transl_expr_correct _ _ _ _ H2 _ _ H0); eauto. + eauto. intros [vb [EVAL ISFALSE]]. - eapply exec_Sifthenelse_false with (v1 := vb); eauto. - constructor. traceEq. + eapply exec_Sifthenelse with (v := vb); eauto. + apply Val.bool_of_false_val; eauto. + simpl. constructor. Qed. Lemma transl_Swhile_false_correct: - (forall (e : Csem.env) (m : mem) (s : statement) (a : Csyntax.expr) - (t : trace) (v : val) (m1 : mem), - Csem.eval_expr ge e m a t m1 v -> - eval_expr_prop e m a t m1 v -> + (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) t m1 Csem.Out_normal). + exec_stmt_prop e m (Swhile a s) E0 m Csem.Out_normal). Proof. - intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR. - simpl. + 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. @@ -999,48 +1090,45 @@ Proof. Qed. Lemma transl_Swhile_stop_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t1 : trace) - (m1 : mem) (v : val) (s : statement) (m2 : mem) (t2 : trace) - (out2 out : Csem.outcome), - Csem.eval_expr ge e m a t1 m1 v -> - eval_expr_prop e m a t1 m1 v -> + (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 m1 s t2 m2 out2 -> - exec_stmt_prop e m1 s t2 m2 out2 -> - out_break_or_return out2 out -> - exec_stmt_prop e m (Swhile a s) (t1 ** t2) m2 out). + 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. inversion WT; clear WT; subst. simpl in TR; monadInv TR. - rewrite (transl_out_break_or_return _ _ nbrk ncnt H4). + 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. - auto. inversion H4; simpl; congruence. + apply exec_Sblock. eauto. traceEq. + inversion H3; simpl; congruence. Qed. Lemma transl_Swhile_loop_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t1 : trace) - (m1 : mem) (v : val) (s : statement) (out2 out : Csem.outcome) - (t2 : trace) (m2 : mem) (t3 : trace) (m3 : mem), - Csem.eval_expr ge e m a t1 m1 v -> - eval_expr_prop e m a t1 m1 v -> + (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 m1 s t2 m2 out2 -> - exec_stmt_prop e m1 s t2 m2 out2 -> - out_normal_or_continue out2 -> - Csem.exec_stmt ge e m2 (Swhile a s) t3 m3 out -> - exec_stmt_prop e m2 (Swhile a s) t3 m3 out -> - exec_stmt_prop e m (Swhile a s) (t1 ** t2 ** t3) m3 out). + 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 H6; eauto. intro NEXTITER. - inversion WT; clear WT; subst. simpl in TR; monadInv TR. + 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 _ H4). + rewrite (transl_out_normal_or_continue _ H3). apply exec_Sblock. eauto. reflexivity. eassumption. traceEq. @@ -1048,23 +1136,21 @@ Qed. Lemma transl_Sdowhile_false_correct: (forall (e : Csem.env) (m : mem) (s : statement) (a : Csyntax.expr) - (t1 : trace) (m1 : mem) (out1 : Csem.outcome) (v : val) - (t2 : trace) (m2 : mem), - Csem.exec_stmt ge e m s t1 m1 out1 -> - exec_stmt_prop e m s t1 m1 out1 -> + (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 t2 m2 v -> - eval_expr_prop e m1 a t2 m2 v -> + Csem.eval_expr ge e m1 a v -> is_false v (typeof a) -> - exec_stmt_prop e m (Sdowhile a s) (t1 ** t2) m2 Csem.Out_normal). + exec_stmt_prop e m (Sdowhile a s) t m1 Csem.Out_normal). Proof. - intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR. + 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. auto. congruence. + eapply exit_if_false_false; eauto. traceEq. congruence. Qed. Lemma transl_Sdowhile_stop_correct: @@ -1075,7 +1161,7 @@ Lemma transl_Sdowhile_stop_correct: out_break_or_return out1 out -> exec_stmt_prop e m (Sdowhile a s) t m1 out). Proof. - intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR. + intros; red; intros. inv WT. monadInv TR. simpl. assert (outcome_block (transl_outcome 1 0 out1) <> Out_normal). inversion H1; simpl; congruence. @@ -1087,22 +1173,19 @@ Qed. Lemma transl_Sdowhile_loop_correct: (forall (e : Csem.env) (m : mem) (s : statement) (a : Csyntax.expr) - (m1 m2 m3 : mem) (t1 t2 t3 : trace) (out out1 : Csem.outcome) - (v : val), + (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 t2 m2 v -> - eval_expr_prop e m1 a t2 m2 v -> + Csem.eval_expr ge e m1 a v -> is_true v (typeof a) -> - Csem.exec_stmt ge e m2 (Sdowhile a s) t3 m3 out -> - exec_stmt_prop e m2 (Sdowhile a s) t3 m3 out -> - exec_stmt_prop e m (Sdowhile a s) (t1 ** t2 ** t3) m3 out). + 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 H6; eauto. intro NEXTITER. - inversion WT; clear WT; subst. simpl in TR; monadInv TR. - inversion NEXTITER; subst. + 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). @@ -1115,6 +1198,7 @@ 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 -> @@ -1122,101 +1206,88 @@ Lemma transl_Sfor_start_correct: exec_stmt_prop e m (Sfor a1 a2 a3 s) (t1 ** t2) m2 out). Proof. intros; red; intros. - exploit transl_stmt_Sfor_start; eauto. - intros [ts1 [ts2 [A [B C]]]]. - clear TR; subst ts. - inversion WT; subst. + 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 H0; eauto. simpl. intro EXEC1. - exploit H2; eauto. intro EXEC2. - assert (EXEC3: exec_stmt tprog te m1 ts2 t2 m2 (transl_outcome nbrk ncnt out)). - inversion EXEC2; subst. - inversion H5; subst. rewrite E0_left; auto. - inversion H11; subst. congruence. - eapply exec_Sseq_continue; eauto. + exploit H1; eauto. simpl. intro EXEC1. + exploit H3; eauto. intro EXEC2. + eapply exec_Sseq_continue; eauto. Qed. Lemma transl_Sfor_false_correct: (forall (e : Csem.env) (m : mem) (s : statement) (a2 : Csyntax.expr) - (a3 : statement) (t : trace) (v : val) (m1 : mem), - Csem.eval_expr ge e m a2 t m1 v -> - eval_expr_prop e m a2 t m1 v -> + (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) t m1 Csem.Out_normal). + exec_stmt_prop e m (Sfor Csyntax.Sskip a2 a3 s) E0 m Csem.Out_normal). Proof. - intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR. + intros; red; intros. inv WT. + rewrite transl_stmt_Sfor_not_start in TR; monadInv TR. simpl. - eapply exec_Sseq_continue. apply exec_Sskip. 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. traceEq. + congruence. congruence. Qed. Lemma transl_Sfor_stop_correct: (forall (e : Csem.env) (m : mem) (s : statement) (a2 : Csyntax.expr) - (a3 : statement) (v : val) (m1 m2 : mem) (t1 t2 : trace) - (out2 out : Csem.outcome), - Csem.eval_expr ge e m a2 t1 m1 v -> - eval_expr_prop e m a2 t1 m1 v -> + (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 m1 s t2 m2 out2 -> - exec_stmt_prop e m1 s t2 m2 out2 -> - out_break_or_return out2 out -> - exec_stmt_prop e m (Sfor Csyntax.Sskip a2 a3 s) (t1 ** t2) m2 out). + 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. inversion WT; clear WT; subst. simpl in TR; monadInv TR. - simpl. - assert (outcome_block (transl_outcome 1 0 out2) <> Out_normal). - inversion H4; simpl; congruence. - rewrite (transl_out_break_or_return _ _ nbrk ncnt H4). - eapply exec_Sseq_continue. apply exec_Sskip. + 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. traceEq. + auto. reflexivity. auto. Qed. Lemma transl_Sfor_loop_correct: (forall (e : Csem.env) (m : mem) (s : statement) (a2 : Csyntax.expr) - (a3 : statement) (v : val) (m1 m2 m3 m4 : mem) - (t1 t2 t3 t4 : trace) (out2 out : Csem.outcome), - Csem.eval_expr ge e m a2 t1 m1 v -> - eval_expr_prop e m a2 t1 m1 v -> + (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 m1 s t2 m2 out2 -> - exec_stmt_prop e m1 s t2 m2 out2 -> - out_normal_or_continue out2 -> - Csem.exec_stmt ge e m2 a3 t3 m3 Csem.Out_normal -> - exec_stmt_prop e m2 a3 t3 m3 Csem.Out_normal -> - Csem.exec_stmt ge e m3 (Sfor Csyntax.Sskip a2 a3 s) t4 m4 out -> - exec_stmt_prop e m3 (Sfor Csyntax.Sskip a2 a3 s) t4 m4 out -> - exec_stmt_prop e m (Sfor Csyntax.Sskip a2 a3 s) - (t1 ** t2 ** t3 ** t4) m4 out). + 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). Proof. intros; red; intros. - exploit H8; eauto. intro NEXTITER. - inversion WT; clear WT; subst. simpl in TR; monadInv TR. + exploit H7; eauto. intro NEXTITER. + inv WT. + rewrite transl_stmt_Sfor_not_start in TR; monadInv TR. inversion NEXTITER; subst. - inversion H11; subst. - inversion H18; subst. - eapply exec_Sseq_continue. apply exec_Sskip. 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 _ H4). + rewrite (transl_out_normal_or_continue _ H3). apply exec_Sblock. eauto. - red in H6; simpl in H6; eauto. + red in H5; simpl in H5; eauto. reflexivity. reflexivity. eassumption. - reflexivity. traceEq. - inversion H17. congruence. + traceEq. Qed. Lemma transl_lblstmts_switch: - forall e m0 t1 m1 n nbrk ncnt tyenv te t2 m2 out sl body ts, - exec_stmt tprog te m0 body t1 m1 + 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) @@ -1224,8 +1295,8 @@ Lemma transl_lblstmts_switch: sl (Sblock body) = OK ts -> wt_lblstmts tyenv sl -> match_env tyenv e te -> - exec_lblstmts_prop e m1 (select_switch n sl) t2 m2 out -> - Csharpminor.exec_stmt tprog te m0 ts (t1 ** t2) m2 + 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)). Proof. induction sl; intros. @@ -1251,24 +1322,20 @@ Proof. Qed. Lemma transl_Sswitch_correct: - (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t1 : trace) - (m1 : mem) (n : int) (sl : labeled_statements) (t2 : trace) - (m2 : mem) (out : Csem.outcome), - Csem.eval_expr ge e m a t1 m1 (Vint n) -> - eval_expr_prop e m a t1 m1 (Vint n) -> - exec_lblstmts ge e m1 (select_switch n sl) t2 m2 out -> - exec_lblstmts_prop e m1 (select_switch n sl) t2 m2 out -> - exec_stmt_prop e m (Csyntax.Sswitch a sl) (t1 ** t2) m2 - (outcome_switch out)). + (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. - inversion WT; clear WT; subst. - simpl in TR. monadInv TR. + 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. - eapply transl_lblstmts_switch; eauto. - constructor. eapply H0; eauto. + change t with (E0 ** t). eapply transl_lblstmts_switch; eauto. + constructor. eapply (transl_expr_correct _ _ _ _ MENV _ _ H); eauto. Qed. Lemma transl_LSdefault_correct: @@ -1278,9 +1345,7 @@ Lemma transl_LSdefault_correct: exec_stmt_prop e m s t m1 out -> exec_lblstmts_prop e m (LSdefault s) t m1 out). Proof. - intros; red; intros. - inversion WT; subst. - simpl in TR. monadInv TR. + 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. @@ -1299,11 +1364,9 @@ Lemma transl_LScase_fallthrough_correct: 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. - inversion WT; subst. - monadInv TR. + intros; red; intros. inv WT. monadInv TR. assert (exec_stmt tprog te m0 (Sblock (Sseq body x)) - (t0 ** t1) m1 Out_normal). + (t0 ** t1) m1 Out_normal). change Out_normal with (outcome_block (transl_outcome (S (lblstmts_length ls)) (S (S (lblstmts_length ls + ncnt))) @@ -1316,7 +1379,7 @@ Proof. Qed. Lemma transl_LScase_stop_correct: - (forall (e : Csem.env) (m : mem) (n : int) (s : statement) + (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 -> @@ -1324,9 +1387,7 @@ Lemma transl_LScase_stop_correct: out <> Csem.Out_normal -> exec_lblstmts_prop e m (LScase n s ls) t m1 out). Proof. - intros; red; intros. - inversion WT; subst. - monadInv TR. + intros; red; intros. inv WT. monadInv TR. exploit H0; eauto. intro EXEC. destruct out; simpl; simpl in EXEC. (* out = Out_break *) @@ -1378,8 +1439,7 @@ Lemma transl_funcall_internal_correct: Proof. intros; red; intros. (* Exploitation of typing hypothesis *) - inversion WT; clear WT; subst. - inversion H6; clear H6; subst. + inv WT. inv H6. (* Exploitation of translation hypothesis *) monadInv TR. monadInv EQ. @@ -1419,38 +1479,55 @@ Theorem transl_funcall_correct: Csem.eval_funcall ge m f l t m0 v -> eval_funcall_prop m f l t m0 v. Proof - (Csem.eval_funcall_ind6 ge - eval_expr_prop - eval_lvalue_prop - eval_exprlist_prop + (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_Econst_int_correct - transl_Econst_float_correct - transl_Elvalue_correct - transl_Eaddrof_correct - transl_Esizeof_correct - transl_Eunop_correct - transl_Ebinop_correct - transl_Eorbool_1_correct - transl_Eorbool_2_correct - transl_Eandbool_1_correct - transl_Eandbool_2_correct - transl_Ecast_correct - transl_Ecall_correct - transl_Evar_local_correct - transl_Evar_global_correct - transl_Ederef_correct - transl_Eindex_correct - transl_Efield_struct_correct - transl_Efield_union_correct - transl_Enil_correct - transl_Econs_correct transl_Sskip_correct - transl_Sexpr_correct transl_Sassign_correct + transl_Scall_None_correct + transl_Scall_Some_correct transl_Ssequence_1_correct transl_Ssequence_2_correct transl_Sifthenelse_true_correct @@ -1476,41 +1553,287 @@ Proof 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. +Proof. + cofix FUNCALL. + assert (STMT: + 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). + cofix STMT. + assert(LBLSTMT: + 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)). + + cofix LBLSTMT; 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 STMT; 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 STMT; 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 LBLSTMT 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 LBLSTMT 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 STMT; eauto. auto. + (* 2.2.2 we diverge later *) + simpl. apply execinf_sleep. + replace (t0 *** t2 *** t3) with ((t0 ** t2) *** t3). + eapply LBLSTMT 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 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 FUNCALL; eauto. + eapply functions_well_typed; eauto. + (* Sseq 1 *) + apply execinf_Sseq_1. eapply STMT; 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 STMT; 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 STMT; 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 STMT; eauto. + (* Swhile, body *) + apply execinf_Sblock. apply execinf_Sloop_body. + eapply execinf_Sseq_2. eapply exit_if_false_true; eauto. + apply execinf_Sblock. eapply STMT; 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 STMT 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 STMT; 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 STMT 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 STMT; 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 STMT; 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 STMT; 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 STMT; 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 STMT; 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 LBLSTMT; eauto. + left. split. apply exec_Sblock. constructor. + eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto. + auto. + + (* 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 STMT; eauto. +Qed. + End CORRECTNESS. (** Semantic preservation for whole programs. *) Theorem transl_program_correct: - forall prog tprog t r, + forall prog tprog beh, transl_program prog = OK tprog -> Ctyping.wt_program prog -> - Csem.exec_program prog t r -> - Csharpminor.exec_program tprog t r. + Csem.exec_program prog beh -> + Csharpminor.exec_program tprog beh. Proof. - intros until r. intros TRANSL WT [b [f [m1 [FINDS [FINDF EVAL]]]]]. - inversion WT; subst. - + 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 H; clear H; intros targs TYP. + elim H1; clear H1; intros targs TYP. assert (targs = Tnil). - inversion EVAL; subst; simpl in TYP. - inversion H0; subst. injection TYP. rewrite <- H6. simpl; auto. - inversion TYP; subst targs0 tres. inversion H. simpl in H0. - inversion H0. destruct targs; simpl in H8; congruence. + 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]]. - exists b; exists tf; exists m1. - split. - rewrite (symbols_preserved _ _ TRANSL). - rewrite (transform_partial_program2_main transl_fundef transl_globvar prog TRANSL). auto. - split. auto. - split. - generalize (transl_fundef_sig2 _ _ _ _ TRANSLFD TYP). simpl; auto. - rewrite (@Genv.init_mem_transf_partial2 _ _ _ _ transl_fundef transl_globvar prog tprog TRANSL). - generalize (transl_funcall_correct _ _ WT TRANSL _ _ _ _ _ _ EVAL). - intro. eapply H. + 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. Qed. -- cgit