From 17f519651feb4a09aa90c89c949469e8a5ab0e88 Mon Sep 17 00:00:00 2001 From: xleroy Date: Sun, 17 Aug 2014 07:52:12 +0000 Subject: - Support "switch" statements over 64-bit integers (in CompCert C to Cminor, included) - Translation of "switch" to decision trees or jumptables made generic over the sizes of integers and moved to the Cminor->CminorSel pass instead of CminorSel->RTL as before. - CminorSel: add "exitexpr" to support the above. - ValueDomain: more precise analysis of comparisons against an integer literal. E.g. "x >=u 0" is always true. git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@2565 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e --- backend/Selectionproof.v | 459 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 336 insertions(+), 123 deletions(-) (limited to 'backend/Selectionproof.v') diff --git a/backend/Selectionproof.v b/backend/Selectionproof.v index 55977b47..658e6603 100644 --- a/backend/Selectionproof.v +++ b/backend/Selectionproof.v @@ -22,6 +22,7 @@ Require Import Memory. Require Import Events. Require Import Globalenvs. Require Import Smallstep. +Require Import Switch. Require Import Cminor. Require Import Op. Require Import CminorSel. @@ -33,7 +34,8 @@ Require Import SelectOpproof. Require Import SelectDivproof. Require Import SelectLongproof. -Open Local Scope cminorsel_scope. +Local Open Scope cminorsel_scope. +Local Open Scope error_monad_scope. (** * Correctness of the instruction selection functions for expressions *) @@ -41,50 +43,54 @@ Open Local Scope cminorsel_scope. Section PRESERVATION. Variable prog: Cminor.program. +Variable tprog: CminorSel.program. Let ge := Genv.globalenv prog. -Variable hf: helper_functions. -Let tprog := transform_program (sel_fundef hf ge) prog. Let tge := Genv.globalenv tprog. +Variable hf: helper_functions. Hypothesis HELPERS: i64_helpers_correct tge hf. +Hypothesis TRANSFPROG: transform_partial_program (sel_fundef hf ge) prog = OK tprog. Lemma symbols_preserved: forall (s: ident), Genv.find_symbol tge s = Genv.find_symbol ge s. Proof. - intros; unfold ge, tge, tprog. apply Genv.find_symbol_transf. + intros. eapply Genv.find_symbol_transf_partial; eauto. Qed. Lemma function_ptr_translated: forall (b: block) (f: Cminor.fundef), Genv.find_funct_ptr ge b = Some f -> - Genv.find_funct_ptr tge b = Some (sel_fundef hf ge f). + exists tf, Genv.find_funct_ptr tge b = Some tf /\ sel_fundef hf ge f = OK tf. Proof. - intros. - exact (Genv.find_funct_ptr_transf (sel_fundef hf ge) _ _ H). + intros. eapply Genv.find_funct_ptr_transf_partial; eauto. Qed. Lemma functions_translated: forall (v v': val) (f: Cminor.fundef), Genv.find_funct ge v = Some f -> Val.lessdef v v' -> - Genv.find_funct tge v' = Some (sel_fundef hf ge f). + exists tf, Genv.find_funct tge v' = Some tf /\ sel_fundef hf ge f = OK tf. Proof. intros. inv H0. - exact (Genv.find_funct_transf (sel_fundef hf ge) _ _ H). + eapply Genv.find_funct_transf_partial; eauto. simpl in H. discriminate. Qed. Lemma sig_function_translated: - forall f, - funsig (sel_fundef hf ge f) = Cminor.funsig f. + forall f tf, sel_fundef hf ge f = OK tf -> funsig tf = Cminor.funsig f. +Proof. + intros. destruct f; monadInv H; auto. monadInv EQ. auto. +Qed. + +Lemma stackspace_function_translated: + forall f tf, sel_function hf ge f = OK tf -> fn_stackspace tf = Cminor.fn_stackspace f. Proof. - intros. destruct f; reflexivity. + intros. monadInv H. auto. Qed. Lemma varinfo_preserved: forall b, Genv.find_var_info tge b = Genv.find_var_info ge b. Proof. - intros; unfold ge, tge, tprog, sel_program. - apply Genv.find_var_info_transf. + intros; eapply Genv.find_var_info_transf_partial; eauto. Qed. Lemma helper_implements_preserved: @@ -93,7 +99,7 @@ Lemma helper_implements_preserved: helper_implements tge id sg vargs vres. Proof. intros. destruct H as (b & ef & A & B & C & D). - exploit function_ptr_translated; eauto. simpl. intros. + exploit function_ptr_translated; eauto. simpl. intros (tf & P & Q). inv Q. exists b; exists ef. split. rewrite symbols_preserved. auto. split. auto. @@ -306,6 +312,176 @@ Proof. auto. Qed. +(** Translation of [switch] statements *) + +Inductive Rint: Z -> val -> Prop := + | Rint_intro: forall n, Rint (Int.unsigned n) (Vint n). + +Inductive Rlong: Z -> val -> Prop := + | Rlong_intro: forall n, Rlong (Int64.unsigned n) (Vlong n). + +Section SEL_SWITCH. + +Variable make_cmp_eq: expr -> Z -> expr. +Variable make_cmp_ltu: expr -> Z -> expr. +Variable make_sub: expr -> Z -> expr. +Variable make_to_int: expr -> expr. +Variable modulus: Z. +Variable R: Z -> val -> Prop. + +Hypothesis eval_make_cmp_eq: forall sp e m le a v i n, + eval_expr tge sp e m le a v -> R i v -> 0 <= n < modulus -> + eval_expr tge sp e m le (make_cmp_eq a n) (Val.of_bool (zeq i n)). +Hypothesis eval_make_cmp_ltu: forall sp e m le a v i n, + eval_expr tge sp e m le a v -> R i v -> 0 <= n < modulus -> + eval_expr tge sp e m le (make_cmp_ltu a n) (Val.of_bool (zlt i n)). +Hypothesis eval_make_sub: forall sp e m le a v i n, + eval_expr tge sp e m le a v -> R i v -> 0 <= n < modulus -> + exists v', eval_expr tge sp e m le (make_sub a n) v' /\ R ((i - n) mod modulus) v'. +Hypothesis eval_make_to_int: forall sp e m le a v i, + eval_expr tge sp e m le a v -> R i v -> + exists v', eval_expr tge sp e m le (make_to_int a) v' /\ Rint (i mod Int.modulus) v'. + +Lemma sel_switch_correct_rec: + forall sp e m varg i x, + R i varg -> + forall t arg le, + wf_comptree modulus t -> + nth_error le arg = Some varg -> + comptree_match modulus i t = Some x -> + eval_exitexpr tge sp e m le (sel_switch make_cmp_eq make_cmp_ltu make_sub make_to_int arg t) x. +Proof. + intros until x; intros Ri. induction t; simpl; intros until le; intros WF ARG MATCH. +- (* base case *) + inv MATCH. constructor. +- (* eq test *) + inv WF. + assert (eval_expr tge sp e m le (make_cmp_eq (Eletvar arg) key) (Val.of_bool (zeq i key))). + { eapply eval_make_cmp_eq; eauto. constructor; auto. } + eapply eval_XEcondition with (va := zeq i key). + eapply eval_condexpr_of_expr; eauto. destruct (zeq i key); constructor; auto. + destruct (zeq i key); simpl. + + inv MATCH. constructor. + + eapply IHt; eauto. +- (* lt test *) + inv WF. + assert (eval_expr tge sp e m le (make_cmp_ltu (Eletvar arg) key) (Val.of_bool (zlt i key))). + { eapply eval_make_cmp_ltu; eauto. constructor; auto. } + eapply eval_XEcondition with (va := zlt i key). + eapply eval_condexpr_of_expr; eauto. destruct (zlt i key); constructor; auto. + destruct (zlt i key); simpl. + + eapply IHt1; eauto. + + eapply IHt2; eauto. +- (* jump table *) + inv WF. + exploit (eval_make_sub sp e m le). eapply eval_Eletvar. eauto. eauto. + instantiate (1 := ofs). auto. + intros (v' & A & B). + set (i' := (i - ofs) mod modulus) in *. + assert (eval_expr tge sp e m (v' :: le) (make_cmp_ltu (Eletvar O) sz) (Val.of_bool (zlt i' sz))). + { eapply eval_make_cmp_ltu; eauto. constructor; auto. } + econstructor. eauto. + eapply eval_XEcondition with (va := zlt i' sz). + eapply eval_condexpr_of_expr; eauto. destruct (zlt i' sz); constructor; auto. + destruct (zlt i' sz); simpl. + + exploit (eval_make_to_int sp e m (v' :: le) (Eletvar O)). + constructor. simpl; eauto. eauto. intros (v'' & C & D). inv D. + econstructor; eauto. congruence. + + eapply IHt; eauto. +Qed. + +Lemma sel_switch_correct: + forall dfl cases arg sp e m varg i t le, + validate_switch modulus dfl cases t = true -> + eval_expr tge sp e m le arg varg -> + R i varg -> + 0 <= i < modulus -> + eval_exitexpr tge sp e m le + (XElet arg (sel_switch make_cmp_eq make_cmp_ltu make_sub make_to_int O t)) + (switch_target i dfl cases). +Proof. + intros. exploit validate_switch_correct; eauto. omega. intros [A B]. + econstructor. eauto. eapply sel_switch_correct_rec; eauto. +Qed. + +End SEL_SWITCH. + +Lemma sel_switch_int_correct: + forall dfl cases arg sp e m i t le, + validate_switch Int.modulus dfl cases t = true -> + eval_expr tge sp e m le arg (Vint i) -> + eval_exitexpr tge sp e m le (XElet arg (sel_switch_int O t)) (switch_target (Int.unsigned i) dfl cases). +Proof. + assert (INTCONST: forall n sp e m le, + eval_expr tge sp e m le (Eop (Ointconst n) Enil) (Vint n)). + { intros. econstructor. constructor. auto. } + intros. eapply sel_switch_correct with (R := Rint); eauto. +- intros until n; intros EVAL R RANGE. + exploit eval_comp. eexact EVAL. apply (INTCONST (Int.repr n)). + instantiate (1 := Ceq). intros (vb & A & B). + inv R. unfold Val.cmp in B. simpl in B. revert B. + predSpec Int.eq Int.eq_spec n0 (Int.repr n); intros B; inv B. + rewrite Int.unsigned_repr. unfold proj_sumbool; rewrite zeq_true; auto. + unfold Int.max_unsigned; omega. + unfold proj_sumbool; rewrite zeq_false; auto. + red; intros; elim H1. rewrite <- (Int.repr_unsigned n0). congruence. +- intros until n; intros EVAL R RANGE. + exploit eval_compu. eexact EVAL. apply (INTCONST (Int.repr n)). + instantiate (1 := Clt). intros (vb & A & B). + inv R. unfold Val.cmpu in B. simpl in B. + unfold Int.ltu in B. rewrite Int.unsigned_repr in B. + destruct (zlt (Int.unsigned n0) n); inv B; auto. + unfold Int.max_unsigned; omega. +- intros until n; intros EVAL R RANGE. + exploit eval_sub. eexact EVAL. apply (INTCONST (Int.repr n)). intros (vb & A & B). + inv R. simpl in B. inv B. econstructor; split; eauto. + replace ((Int.unsigned n0 - n) mod Int.modulus) + with (Int.unsigned (Int.sub n0 (Int.repr n))). + constructor. + unfold Int.sub. rewrite Int.unsigned_repr_eq. f_equal. f_equal. + apply Int.unsigned_repr. unfold Int.max_unsigned; omega. +- intros until i0; intros EVAL R. exists v; split; auto. + inv R. rewrite Zmod_small by (apply Int.unsigned_range). constructor. +- constructor. +- apply Int.unsigned_range. +Qed. + +Lemma sel_switch_long_correct: + forall dfl cases arg sp e m i t le, + validate_switch Int64.modulus dfl cases t = true -> + eval_expr tge sp e m le arg (Vlong i) -> + eval_exitexpr tge sp e m le (XElet arg (sel_switch_long hf O t)) (switch_target (Int64.unsigned i) dfl cases). +Proof. + intros. eapply sel_switch_correct with (R := Rlong); eauto. +- intros until n; intros EVAL R RANGE. + eapply eval_cmpl. eexact EVAL. apply eval_longconst with (n := Int64.repr n). + inv R. unfold Val.cmpl. simpl. f_equal; f_equal. unfold Int64.eq. + rewrite Int64.unsigned_repr. destruct (zeq (Int64.unsigned n0) n); auto. + unfold Int64.max_unsigned; omega. +- intros until n; intros EVAL R RANGE. + eapply eval_cmplu. eexact EVAL. apply eval_longconst with (n := Int64.repr n). + inv R. unfold Val.cmplu. simpl. f_equal; f_equal. unfold Int64.ltu. + rewrite Int64.unsigned_repr. destruct (zlt (Int64.unsigned n0) n); auto. + unfold Int64.max_unsigned; omega. +- intros until n; intros EVAL R RANGE. + exploit eval_subl. eexact HELPERS. eexact EVAL. apply eval_longconst with (n := Int64.repr n). + intros (vb & A & B). + inv R. simpl in B. inv B. econstructor; split; eauto. + replace ((Int64.unsigned n0 - n) mod Int64.modulus) + with (Int64.unsigned (Int64.sub n0 (Int64.repr n))). + constructor. + unfold Int64.sub. rewrite Int64.unsigned_repr_eq. f_equal. f_equal. + apply Int64.unsigned_repr. unfold Int64.max_unsigned; omega. +- intros until i0; intros EVAL R. + exploit eval_lowlong. eexact EVAL. intros (vb & A & B). + inv R. simpl in B. inv B. econstructor; split; eauto. + replace (Int64.unsigned n mod Int.modulus) with (Int.unsigned (Int64.loword n)). + constructor. + unfold Int64.loword. apply Int.unsigned_repr_eq. +- constructor. +- apply Int64.unsigned_range. +Qed. + (** Compatibility of evaluation functions with the "less defined than" relation. *) Ltac TrivialExists := @@ -433,56 +609,62 @@ Qed. Inductive match_cont: Cminor.cont -> CminorSel.cont -> Prop := | match_cont_stop: match_cont Cminor.Kstop Kstop - | match_cont_seq: forall s k k', + | match_cont_seq: forall s s' k k', + sel_stmt hf ge s = OK s' -> match_cont k k' -> - match_cont (Cminor.Kseq s k) (Kseq (sel_stmt hf ge s) k') + match_cont (Cminor.Kseq s k) (Kseq s' k') | match_cont_block: forall k k', match_cont k k' -> match_cont (Cminor.Kblock k) (Kblock k') - | match_cont_call: forall id f sp e k e' k', + | match_cont_call: forall id f sp e k f' e' k', + sel_function hf ge f = OK f' -> match_cont k k' -> env_lessdef e e' -> - match_cont (Cminor.Kcall id f sp e k) (Kcall id (sel_function hf ge f) sp e' k'). + match_cont (Cminor.Kcall id f sp e k) (Kcall id f' sp e' k'). Inductive match_states: Cminor.state -> CminorSel.state -> Prop := - | match_state: forall f s k s' k' sp e m e' m', - s' = sel_stmt hf ge s -> - match_cont k k' -> - env_lessdef e e' -> - Mem.extends m m' -> + | match_state: forall f f' s k s' k' sp e m e' m' + (TF: sel_function hf ge f = OK f') + (TS: sel_stmt hf ge s = OK s') + (MC: match_cont k k') + (LD: env_lessdef e e') + (ME: Mem.extends m m'), match_states (Cminor.State f s k sp e m) - (State (sel_function hf ge f) s' k' sp e' m') - | match_callstate: forall f args args' k k' m m', - match_cont k k' -> - Val.lessdef_list args args' -> - Mem.extends m m' -> + (State f' s' k' sp e' m') + | match_callstate: forall f f' args args' k k' m m' + (TF: sel_fundef hf ge f = OK f') + (MC: match_cont k k') + (LD: Val.lessdef_list args args') + (ME: Mem.extends m m'), match_states (Cminor.Callstate f args k m) - (Callstate (sel_fundef hf ge f) args' k' m') - | match_returnstate: forall v v' k k' m m', - match_cont k k' -> - Val.lessdef v v' -> - Mem.extends m m' -> + (Callstate f' args' k' m') + | match_returnstate: forall v v' k k' m m' + (MC: match_cont k k') + (LD: Val.lessdef v v') + (ME: Mem.extends m m'), match_states (Cminor.Returnstate v k m) (Returnstate v' k' m') - | match_builtin_1: forall ef args args' optid f sp e k m al e' k' m', - match_cont k k' -> - Val.lessdef_list args args' -> - env_lessdef e e' -> - Mem.extends m m' -> - eval_exprlist tge sp e' m' nil al args' -> + | match_builtin_1: forall ef args args' optid f sp e k m al f' e' k' m' + (TF: sel_function hf ge f = OK f') + (MC: match_cont k k') + (LDA: Val.lessdef_list args args') + (LDE: env_lessdef e e') + (ME: Mem.extends m m') + (EA: eval_exprlist tge sp e' m' nil al args'), match_states (Cminor.Callstate (External ef) args (Cminor.Kcall optid f sp e k) m) - (State (sel_function hf ge f) (Sbuiltin optid ef al) k' sp e' m') - | match_builtin_2: forall v v' optid f sp e k m e' m' k', - match_cont k k' -> - Val.lessdef v v' -> - env_lessdef e e' -> - Mem.extends m m' -> + (State f' (Sbuiltin optid ef al) k' sp e' m') + | match_builtin_2: forall v v' optid f sp e k m f' e' m' k' + (TF: sel_function hf ge f = OK f') + (MC: match_cont k k') + (LDV: Val.lessdef v v') + (LDE: env_lessdef e e') + (ME: Mem.extends m m'), match_states (Cminor.Returnstate v (Cminor.Kcall optid f sp e k) m) - (State (sel_function hf ge f) Sskip k' sp (set_optvar optid v' e') m'). + (State f' Sskip k' sp (set_optvar optid v' e') m'). Remark call_cont_commut: forall k k', match_cont k k' -> match_cont (Cminor.call_cont k) (call_cont k'). @@ -491,15 +673,16 @@ Proof. Qed. Remark find_label_commut: - forall lbl s k k', + forall lbl s k s' k', match_cont k k' -> - match Cminor.find_label lbl s k, find_label lbl (sel_stmt hf ge s) k' with + sel_stmt hf ge s = OK s' -> + match Cminor.find_label lbl s k, find_label lbl s' k' with | None, None => True - | Some(s1, k1), Some(s1', k1') => s1' = sel_stmt hf ge s1 /\ match_cont k1 k1' + | Some(s1, k1), Some(s1', k1') => sel_stmt hf ge s1 = OK s1' /\ match_cont k1 k1' | _, _ => False end. Proof. - induction s; intros; simpl; auto. + induction s; intros until k'; simpl; intros MC SE; try (monadInv SE); simpl; auto. (* store *) unfold store. destruct (addressing m (sel_expr hf e)); simpl; auto. (* call *) @@ -507,21 +690,27 @@ Proof. (* tailcall *) destruct (classify_call ge e); simpl; auto. (* seq *) - exploit (IHs1 (Cminor.Kseq s2 k)). constructor; eauto. + exploit (IHs1 (Cminor.Kseq s2 k)). constructor; eauto. eauto. destruct (Cminor.find_label lbl s1 (Cminor.Kseq s2 k)) as [[sx kx] | ]; - destruct (find_label lbl (sel_stmt hf ge s1) (Kseq (sel_stmt hf ge s2) k')) as [[sy ky] | ]; + destruct (find_label lbl x (Kseq x0 k')) as [[sy ky] | ]; intuition. apply IHs2; auto. (* ifthenelse *) exploit (IHs1 k); eauto. destruct (Cminor.find_label lbl s1 k) as [[sx kx] | ]; - destruct (find_label lbl (sel_stmt hf ge s1) k') as [[sy ky] | ]; + destruct (find_label lbl x k') as [[sy ky] | ]; intuition. apply IHs2; auto. (* loop *) - apply IHs. constructor; auto. + apply IHs. constructor; auto. simpl; rewrite EQ; auto. auto. (* block *) - apply IHs. constructor; auto. + apply IHs. constructor; auto. auto. +(* switch *) + destruct b. + destruct (validate_switch Int64.modulus n l (compile_switch Int64.modulus n l)); inv SE. + simpl; auto. + destruct (validate_switch Int.modulus n l (compile_switch Int.modulus n l)); inv SE. + simpl; auto. (* return *) - destruct o; simpl; auto. + destruct o; inv SE; simpl; auto. (* label *) destruct (ident_eq lbl l). auto. apply IHs; auto. Qed. @@ -539,64 +728,68 @@ Lemma sel_step_correct: (exists T2, step tge T1 t T2 /\ match_states S2 T2) \/ (measure S2 < measure S1 /\ t = E0 /\ match_states S2 T1)%nat. Proof. - induction 1; intros T1 ME; inv ME; simpl. - (* skip seq *) - inv H7. left; econstructor; split. econstructor. constructor; auto. - (* skip block *) - inv H7. left; econstructor; split. econstructor. constructor; auto. - (* skip call *) + induction 1; intros T1 ME; inv ME; try (monadInv TS). +- (* skip seq *) + inv MC. left; econstructor; split. econstructor. constructor; auto. +- (* skip block *) + inv MC. left; econstructor; split. econstructor. constructor; auto. +- (* skip call *) exploit Mem.free_parallel_extends; eauto. intros [m2' [A B]]. left; econstructor; split. - econstructor. inv H9; simpl in H; simpl; auto. + econstructor. inv MC; simpl in H; simpl; auto. eauto. + erewrite stackspace_function_translated; eauto. constructor; auto. - (* assign *) +- (* assign *) exploit sel_expr_correct; eauto. intros [v' [A B]]. left; econstructor; split. econstructor; eauto. constructor; auto. apply set_var_lessdef; auto. - (* store *) +- (* store *) exploit sel_expr_correct. eexact H. eauto. eauto. intros [vaddr' [A B]]. exploit sel_expr_correct. eexact H0. eauto. eauto. intros [v' [C D]]. exploit Mem.storev_extends; eauto. intros [m2' [P Q]]. left; econstructor; split. eapply eval_store; eauto. constructor; auto. - (* Scall *) +- (* Scall *) exploit sel_exprlist_correct; eauto. intros [vargs' [C D]]. exploit classify_call_correct; eauto. destruct (classify_call ge a) as [ | id | ef]. - (* indirect *) ++ (* indirect *) exploit sel_expr_correct; eauto. intros [vf' [A B]]. + exploit functions_translated; eauto. intros (fd' & U & V). left; econstructor; split. econstructor; eauto. econstructor; eauto. - eapply functions_translated; eauto. - apply sig_function_translated. + apply sig_function_translated; auto. constructor; auto. constructor; auto. - (* direct *) ++ (* direct *) intros [b [U V]]. + exploit functions_translated; eauto. intros (fd' & X & Y). left; econstructor; split. - econstructor; eauto. econstructor; eauto. rewrite symbols_preserved; eauto. - eapply functions_translated; eauto. subst vf; auto. - apply sig_function_translated. + econstructor; eauto. + subst vf. econstructor; eauto. rewrite symbols_preserved; eauto. + apply sig_function_translated; auto. constructor; auto. constructor; auto. - (* turned into Sbuiltin *) ++ (* turned into Sbuiltin *) intros EQ. subst fd. - right; split. omega. split. auto. + right; split. simpl. omega. split. auto. econstructor; eauto. - (* Stailcall *) +- (* Stailcall *) exploit Mem.free_parallel_extends; eauto. intros [m2' [P Q]]. + erewrite <- stackspace_function_translated in P by eauto. exploit sel_expr_correct; eauto. intros [vf' [A B]]. exploit sel_exprlist_correct; eauto. intros [vargs' [C D]]. + exploit functions_translated; eauto. intros [fd' [E F]]. left; econstructor; split. exploit classify_call_correct; eauto. destruct (classify_call ge a) as [ | id | ef]; intros. - econstructor; eauto. econstructor; eauto. eapply functions_translated; eauto. apply sig_function_translated. - destruct H2 as [b [U V]]. - econstructor; eauto. econstructor; eauto. rewrite symbols_preserved; eauto. eapply functions_translated; eauto. subst vf; auto. apply sig_function_translated. - econstructor; eauto. econstructor; eauto. eapply functions_translated; eauto. apply sig_function_translated. + econstructor; eauto. econstructor; eauto. apply sig_function_translated; auto. + destruct H2 as [b [U V]]. subst vf. inv B. + econstructor; eauto. econstructor; eauto. rewrite symbols_preserved; eauto. apply sig_function_translated; auto. + econstructor; eauto. econstructor; eauto. apply sig_function_translated; auto. constructor; auto. apply call_cont_commut; auto. - (* Sbuiltin *) +- (* Sbuiltin *) exploit sel_exprlist_correct; eauto. intros [vargs' [P Q]]. exploit external_call_mem_extends; eauto. intros [vres' [m2 [A [B [C D]]]]]. @@ -605,77 +798,96 @@ Proof. exact symbols_preserved. exact varinfo_preserved. constructor; auto. destruct optid; simpl; auto. apply set_var_lessdef; auto. - (* Seq *) - left; econstructor; split. constructor. constructor; auto. constructor; auto. - (* Sifthenelse *) +- (* Seq *) + left; econstructor; split. + constructor. constructor; auto. constructor; auto. +- (* Sifthenelse *) exploit sel_expr_correct; eauto. intros [v' [A B]]. assert (Val.bool_of_val v' b). inv B. auto. inv H0. - left; exists (State (sel_function hf ge f) (if b then sel_stmt hf ge s1 else sel_stmt hf ge s2) k' sp e' m'); split. + left; exists (State f' (if b then x else x0) k' sp e' m'); split. econstructor; eauto. eapply eval_condexpr_of_expr; eauto. constructor; auto. destruct b; auto. - (* Sloop *) - left; econstructor; split. constructor. constructor; auto. constructor; auto. - (* Sblock *) +- (* Sloop *) + left; econstructor; split. constructor. constructor; auto. + constructor; auto. simpl; rewrite EQ; auto. +- (* Sblock *) left; econstructor; split. constructor. constructor; auto. constructor; auto. - (* Sexit seq *) - inv H7. left; econstructor; split. constructor. constructor; auto. - (* Sexit0 block *) - inv H7. left; econstructor; split. constructor. constructor; auto. - (* SexitS block *) - inv H7. left; econstructor; split. constructor. constructor; auto. - (* Sswitch *) +- (* Sexit seq *) + inv MC. left; econstructor; split. constructor. constructor; auto. +- (* Sexit0 block *) + inv MC. left; econstructor; split. constructor. constructor; auto. +- (* SexitS block *) + inv MC. left; econstructor; split. constructor. constructor; auto. +- (* Sswitch *) + inv H0; simpl in TS. ++ set (ct := compile_switch Int.modulus default cases) in *. + destruct (validate_switch Int.modulus default cases ct) eqn:VALID; inv TS. + exploit sel_expr_correct; eauto. intros [v' [A B]]. inv B. + left; econstructor; split. + econstructor. eapply sel_switch_int_correct; eauto. + constructor; auto. ++ set (ct := compile_switch Int64.modulus default cases) in *. + destruct (validate_switch Int64.modulus default cases ct) eqn:VALID; inv TS. exploit sel_expr_correct; eauto. intros [v' [A B]]. inv B. - left; econstructor; split. econstructor; eauto. constructor; auto. - (* Sreturn None *) + left; econstructor; split. + econstructor. eapply sel_switch_long_correct; eauto. + constructor; auto. +- (* Sreturn None *) exploit Mem.free_parallel_extends; eauto. intros [m2' [P Q]]. + erewrite <- stackspace_function_translated in P by eauto. left; econstructor; split. econstructor. simpl; eauto. constructor; auto. apply call_cont_commut; auto. - (* Sreturn Some *) +- (* Sreturn Some *) exploit Mem.free_parallel_extends; eauto. intros [m2' [P Q]]. + erewrite <- stackspace_function_translated in P by eauto. exploit sel_expr_correct; eauto. intros [v' [A B]]. left; econstructor; split. econstructor; eauto. constructor; auto. apply call_cont_commut; auto. - (* Slabel *) +- (* Slabel *) left; econstructor; split. constructor. constructor; auto. - (* Sgoto *) +- (* Sgoto *) + assert (sel_stmt hf ge (Cminor.fn_body f) = OK (fn_body f')). + { monadInv TF; simpl; auto. } exploit (find_label_commut lbl (Cminor.fn_body f) (Cminor.call_cont k)). - apply call_cont_commut; eauto. + apply call_cont_commut; eauto. eauto. rewrite H. - destruct (find_label lbl (sel_stmt hf ge (Cminor.fn_body f)) (call_cont k'0)) + destruct (find_label lbl (fn_body f') (call_cont k'0)) as [[s'' k'']|] eqn:?; intros; try contradiction. - destruct H0. + destruct H1. left; econstructor; split. econstructor; eauto. constructor; auto. - (* internal function *) +- (* internal function *) + monadInv TF. generalize EQ; intros TF; monadInv TF. exploit Mem.alloc_extends. eauto. eauto. apply Zle_refl. apply Zle_refl. intros [m2' [A B]]. left; econstructor; split. - econstructor; eauto. - constructor; auto. apply set_locals_lessdef. apply set_params_lessdef; auto. - (* external call *) + econstructor; simpl; eauto. + constructor; simpl; auto. apply set_locals_lessdef. apply set_params_lessdef; auto. +- (* external call *) + monadInv TF. exploit external_call_mem_extends; eauto. intros [vres' [m2 [A [B [C D]]]]]. left; econstructor; split. econstructor. eapply external_call_symbols_preserved; eauto. exact symbols_preserved. exact varinfo_preserved. constructor; auto. - (* external call turned into a Sbuiltin *) +- (* external call turned into a Sbuiltin *) exploit external_call_mem_extends; eauto. intros [vres' [m2 [A [B [C D]]]]]. left; econstructor; split. econstructor. eauto. eapply external_call_symbols_preserved; eauto. exact symbols_preserved. exact varinfo_preserved. constructor; auto. - (* return *) - inv H2. +- (* return *) + inv MC. left; econstructor; split. econstructor. constructor; auto. destruct optid; simpl; auto. apply set_var_lessdef; auto. - (* return of an external call turned into a Sbuiltin *) - right; split. omega. split. auto. constructor; auto. +- (* return of an external call turned into a Sbuiltin *) + right; split. simpl; omega. split. auto. constructor; auto. destruct optid; simpl; auto. apply set_var_lessdef; auto. Qed. @@ -684,11 +896,13 @@ Lemma sel_initial_states: exists R, initial_state tprog R /\ match_states S R. Proof. induction 1. + exploit function_ptr_translated; eauto. intros (f' & A & B). econstructor; split. econstructor. - apply Genv.init_mem_transf; eauto. - simpl. fold tge. rewrite symbols_preserved. eexact H0. - apply function_ptr_translated. eauto. + eapply Genv.init_mem_transf_partial; eauto. + simpl. fold tge. rewrite symbols_preserved. + erewrite transform_partial_program_main by eauto. eexact H0. + eauto. rewrite <- H2. apply sig_function_translated; auto. constructor; auto. constructor. apply Mem.extends_refl. Qed. @@ -697,7 +911,7 @@ Lemma sel_final_states: forall S R r, match_states S R -> Cminor.final_state S r -> final_state R r. Proof. - intros. inv H0. inv H. inv H3. inv H5. constructor. + intros. inv H0. inv H. inv MC. inv LD. constructor. Qed. End PRESERVATION. @@ -712,10 +926,9 @@ Theorem transf_program_correct: Proof. intros. unfold sel_program in H. destruct (get_helpers (Genv.globalenv prog)) as [hf|] eqn:E; simpl in H; try discriminate. - inv H. - eapply forward_simulation_opt. - apply symbols_preserved. - apply sel_initial_states. - apply sel_final_states. - apply sel_step_correct. apply helpers_correct_preserved. apply get_helpers_correct. auto. + apply forward_simulation_opt with (match_states := match_states prog tprog hf) (measure := measure). + eapply symbols_preserved; eauto. + apply sel_initial_states; auto. + apply sel_final_states; auto. + apply sel_step_correct; auto. eapply helpers_correct_preserved; eauto. apply get_helpers_correct. auto. Qed. -- cgit