diff options
Diffstat (limited to 'cfrontend/SimplExprproof.v')
-rw-r--r-- | cfrontend/SimplExprproof.v | 1035 |
1 files changed, 575 insertions, 460 deletions
diff --git a/cfrontend/SimplExprproof.v b/cfrontend/SimplExprproof.v index 9a3f32ec..67bf0e51 100644 --- a/cfrontend/SimplExprproof.v +++ b/cfrontend/SimplExprproof.v @@ -22,7 +22,7 @@ Require Import SimplExpr SimplExprspec. (** ** Relational specification of the translation. *) Definition match_prog (p: Csyntax.program) (tp: Clight.program) := - match_program (fun ctx f tf => tr_fundef f tf) eq p tp + match_program_gen tr_fundef eq p p tp /\ prog_types tp = prog_types p. Lemma transf_program_match: @@ -30,8 +30,9 @@ Lemma transf_program_match: Proof. unfold transl_program; intros. monadInv H. split; auto. unfold program_of_program; simpl. destruct x; simpl. - eapply match_transform_partial_program_contextual. eexact EQ. - intros. apply transl_fundef_spec; auto. + eapply match_transform_partial_program2; eauto. +- intros. apply transl_fundef_spec; auto. +- intros. inv H. auto. Qed. (** ** Semantic preservation *) @@ -65,25 +66,19 @@ Proof (Genv.senv_match (proj1 TRANSL)). Lemma function_ptr_translated: forall b f, Genv.find_funct_ptr ge b = Some f -> - exists tf, - Genv.find_funct_ptr tge b = Some tf /\ tr_fundef f tf. -Proof. - intros. - edestruct (Genv.find_funct_ptr_match (proj1 TRANSL)) as (ctx & tf & A & B & C); eauto. -Qed. + exists cu tf, + Genv.find_funct_ptr tge b = Some tf /\ tr_fundef cu f tf /\ linkorder cu prog. +Proof (Genv.find_funct_ptr_match (proj1 TRANSL)). Lemma functions_translated: forall v f, Genv.find_funct ge v = Some f -> - exists tf, - Genv.find_funct tge v = Some tf /\ tr_fundef f tf. -Proof. - intros. - edestruct (Genv.find_funct_match (proj1 TRANSL)) as (ctx & tf & A & B & C); eauto. -Qed. + exists cu tf, + Genv.find_funct tge v = Some tf /\ tr_fundef cu f tf /\ linkorder cu prog. +Proof (Genv.find_funct_match (proj1 TRANSL)). Lemma type_of_fundef_preserved: - forall f tf, tr_fundef f tf -> + forall cu f tf, tr_fundef cu f tf -> type_of_fundef tf = Csyntax.type_of_fundef f. Proof. intros. inv H. @@ -92,7 +87,7 @@ Proof. Qed. Lemma function_return_preserved: - forall f tf, tr_function f tf -> + forall ce f tf, tr_function ce f tf -> fn_return tf = Csyntax.fn_return f. Proof. intros. inv H; auto. @@ -100,10 +95,16 @@ Qed. (** Properties of smart constructors. *) +Section TRANSLATION. + +Variable cunit: Csyntax.program. +Hypothesis LINKORDER: linkorder cunit prog. +Let ce := cunit.(prog_comp_env). + Lemma eval_Ederef': forall ge e le m a t l ofs, eval_expr ge e le m a (Vptr l ofs) -> - eval_lvalue ge e le m (Ederef' a t) l ofs. + eval_lvalue ge e le m (Ederef' a t) l ofs Full. Proof. intros. unfold Ederef'; destruct a; auto using eval_Ederef. destruct (type_eq t (typeof a)); auto using eval_Ederef. @@ -120,7 +121,7 @@ Qed. Lemma eval_Eaddrof': forall ge e le m a t l ofs, - eval_lvalue ge e le m a l ofs -> + eval_lvalue ge e le m a l ofs Full -> eval_expr ge e le m (Eaddrof' a t) (Vptr l ofs). Proof. intros. unfold Eaddrof'; destruct a; auto using eval_Eaddrof. @@ -134,12 +135,45 @@ Proof. unfold Eaddrof'; intros; destruct a; auto. destruct (type_eq t (typeof a)); auto. Qed. +Lemma eval_make_normalize: + forall ge e le m a n sz sg sg1 attr width, + 0 < width -> width <= bitsize_intsize sz -> + typeof a = Tint sz sg1 attr -> + eval_expr ge e le m a (Vint n) -> + eval_expr ge e le m (make_normalize sz sg width a) (Vint (bitfield_normalize sz sg width n)). +Proof. + intros. unfold make_normalize, bitfield_normalize. + assert (bitsize_intsize sz <= Int.zwordsize) by (destruct sz; compute; congruence). + destruct (intsize_eq sz IBool || signedness_eq sg Unsigned). +- rewrite Int.zero_ext_and by lia. econstructor. eauto. econstructor. + rewrite H1; simpl. unfold sem_and, sem_binarith. + assert (A: exists sg2, classify_binarith (Tint sz sg1 attr) type_int32s = bin_case_i sg2). + { unfold classify_binarith. unfold type_int32s. destruct sz, sg1; econstructor; eauto. } + destruct A as (sg2 & A); rewrite A. + unfold binarith_type. + assert (B: forall i sz0 sg0 attr0, + sem_cast (Vint i) (Tint sz0 sg0 attr0) (Tint I32 sg2 noattr) m = Some (Vint i)). + { intros. unfold sem_cast, classify_cast. destruct Archi.ptr64; reflexivity. } + unfold type_int32s; rewrite ! B. auto. +- rewrite Int.sign_ext_shr_shl by lia. + set (amount := Int.repr (Int.zwordsize - width)). + assert (LT: Int.ltu amount Int.iwordsize = true). + { unfold Int.ltu. rewrite Int.unsigned_repr_wordsize. apply zlt_true. + unfold amount; rewrite Int.unsigned_repr. lia. + assert (Int.zwordsize < Int.max_unsigned) by reflexivity. lia. } + econstructor. + econstructor. eauto. econstructor. + rewrite H1. unfold sem_binary_operation, sem_shl, sem_shift. rewrite LT. destruct sz, sg1; reflexivity. + econstructor. + unfold sem_binary_operation, sem_shr, sem_shift. rewrite LT. reflexivity. +Qed. + (** Translation of simple expressions. *) Lemma tr_simple_nil: - (forall le dst r sl a tmps, tr_expr le dst r sl a tmps -> + (forall le dst r sl a tmps, tr_expr ce le dst r sl a tmps -> dst = For_val \/ dst = For_effects -> simple r = true -> sl = nil) -/\(forall le rl sl al tmps, tr_exprlist le rl sl al tmps -> +/\(forall le rl sl al tmps, tr_exprlist ce le rl sl al tmps -> simplelist rl = true -> sl = nil). Proof. assert (A: forall dst a, dst = For_val \/ dst = For_effects -> final dst a = nil). @@ -160,52 +194,104 @@ Proof. Qed. Lemma tr_simple_expr_nil: - forall le dst r sl a tmps, tr_expr le dst r sl a tmps -> + forall le dst r sl a tmps, tr_expr ce le dst r sl a tmps -> dst = For_val \/ dst = For_effects -> simple r = true -> sl = nil. Proof (proj1 tr_simple_nil). Lemma tr_simple_exprlist_nil: - forall le rl sl al tmps, tr_exprlist le rl sl al tmps -> + forall le rl sl al tmps, tr_exprlist ce le rl sl al tmps -> simplelist rl = true -> sl = nil. Proof (proj2 tr_simple_nil). (** Translation of [deref_loc] and [assign_loc] operations. *) Remark deref_loc_translated: - forall ty m b ofs t v, - Csem.deref_loc ge ty m b ofs t v -> - match chunk_for_volatile_type ty with - | None => t = E0 /\ Clight.deref_loc ty m b ofs v - | Some chunk => volatile_load tge chunk m b ofs t v + forall ty m b ofs bf t v, + Csem.deref_loc ge ty m b ofs bf t v -> + match chunk_for_volatile_type ty bf with + | None => t = E0 /\ Clight.deref_loc ty m b ofs bf v + | Some chunk => bf = Full /\ volatile_load tge chunk m b ofs t v end. Proof. intros. unfold chunk_for_volatile_type. inv H. - (* By_value, not volatile *) +- (* By_value, not volatile *) rewrite H1. split; auto. eapply deref_loc_value; eauto. - (* By_value, volatile *) - rewrite H0; rewrite H1. eapply volatile_load_preserved with (ge1 := ge); auto. apply senv_preserved. - (* By reference *) +- (* By_value, volatile *) + rewrite H0, H1. split; auto. eapply volatile_load_preserved with (ge1 := ge); auto. apply senv_preserved. +- (* By reference *) rewrite H0. destruct (type_is_volatile ty); split; auto; eapply deref_loc_reference; eauto. - (* By copy *) +- (* By copy *) rewrite H0. destruct (type_is_volatile ty); split; auto; eapply deref_loc_copy; eauto. +- (* Bitfield *) + destruct (type_is_volatile ty); [destruct (access_mode ty)|]; auto using deref_loc_bitfield. Qed. Remark assign_loc_translated: - forall ty m b ofs v t m', - Csem.assign_loc ge ty m b ofs v t m' -> - match chunk_for_volatile_type ty with - | None => t = E0 /\ Clight.assign_loc tge ty m b ofs v m' - | Some chunk => volatile_store tge chunk m b ofs v t m' + forall ty m b ofs bf v t m' v', + Csem.assign_loc ge ty m b ofs bf v t m' v' -> + match chunk_for_volatile_type ty bf with + | None => t = E0 /\ Clight.assign_loc tge ty m b ofs bf v m' + | Some chunk => bf = Full /\ volatile_store tge chunk m b ofs v t m' end. Proof. intros. unfold chunk_for_volatile_type. inv H. - (* By_value, not volatile *) +- (* By_value, not volatile *) rewrite H1. split; auto. eapply assign_loc_value; eauto. - (* By_value, volatile *) - rewrite H0; rewrite H1. eapply volatile_store_preserved with (ge1 := ge); auto. apply senv_preserved. - (* By copy *) +- (* By_value, volatile *) + rewrite H0, H1. split; auto. eapply volatile_store_preserved with (ge1 := ge); auto. apply senv_preserved. +- (* By copy *) rewrite H0. rewrite <- comp_env_preserved in *. destruct (type_is_volatile ty); split; auto; eapply assign_loc_copy; eauto. +- (* Bitfield *) + destruct (type_is_volatile ty); [destruct (access_mode ty)|]; eauto using assign_loc_bitfield. +Qed. + +(** Bitfield accesses *) + +Lemma is_bitfield_access_sound: forall e le m a b ofs bf bf', + eval_lvalue tge e le m a b ofs bf -> + tr_is_bitfield_access ce a bf' -> + bf' = bf. +Proof. + assert (A: forall id co co', + tge.(genv_cenv)!id = Some co -> ce!id = Some co' -> + co' = co /\ complete_members ce (co_members co) = true). + { intros. rewrite comp_env_preserved in H. + assert (ge.(Csem.genv_cenv) ! id = Some co') by (apply LINKORDER; auto). + replace co' with co in * by congruence. + split; auto. apply co_consistent_complete. + eapply build_composite_env_consistent. eapply prog_comp_env_eq. eauto. + } + induction 1; simpl; auto. +- rewrite H0. intros (co' & delta' & E1 & E2). rewrite comp_env_preserved in H2. + exploit A; eauto. intros (E3 & E4). subst co'. + assert (field_offset ge i (co_members co) = field_offset ce i (co_members co)). + { apply field_offset_stable. apply LINKORDER. auto. } + congruence. +- rewrite H0. intros (co' & delta' & E1 & E2). rewrite comp_env_preserved in H2. + exploit A; eauto. intros (E3 & E4). subst co'. + assert (union_field_offset ge i (co_members co) = union_field_offset ce i (co_members co)). + { apply union_field_offset_stable. apply LINKORDER. auto. } + congruence. +Qed. + +Lemma make_assign_value_sound: + forall ty m b ofs bf v t m' v', + Csem.assign_loc ge ty m b ofs bf v t m' v' -> + forall tge e le m'' r, + typeof r = ty -> + eval_expr tge e le m'' r v -> + eval_expr tge e le m'' (make_assign_value bf r) v'. +Proof. + unfold make_assign_value; destruct 1; intros; auto. + inv H. eapply eval_make_normalize; eauto; lia. +Qed. + +Lemma typeof_make_assign_value: forall bf r, + typeof (make_assign_value bf r) = typeof r. +Proof. + intros. destruct bf; simpl; auto. unfold make_normalize. + destruct (intsize_eq sz IBool || signedness_eq sg Unsigned); auto. Qed. (** Evaluation of simple expressions and of their translation *) @@ -215,7 +301,7 @@ Lemma tr_simple: (forall r v, eval_simple_rvalue ge e m r v -> forall le dst sl a tmps, - tr_expr le dst r sl a tmps -> + tr_expr ce le dst r sl a tmps -> match dst with | For_val => sl = nil /\ Csyntax.typeof r = typeof a /\ eval_expr tge e le m a v | For_effects => sl = nil @@ -225,11 +311,11 @@ Lemma tr_simple: /\ eval_expr tge e le m b v end) /\ - (forall l b ofs, - eval_simple_lvalue ge e m l b ofs -> + (forall l b ofs bf, + eval_simple_lvalue ge e m l b ofs bf -> forall le sl a tmps, - tr_expr le For_val l sl a tmps -> - sl = nil /\ Csyntax.typeof l = typeof a /\ eval_lvalue tge e le m a b ofs). + tr_expr ce le For_val l sl a tmps -> + sl = nil /\ Csyntax.typeof l = typeof a /\ eval_lvalue tge e le m a b ofs bf). Proof. Opaque makeif. intros e m. @@ -306,7 +392,7 @@ Lemma tr_simple_rvalue: forall e m r v, eval_simple_rvalue ge e m r v -> forall le dst sl a tmps, - tr_expr le dst r sl a tmps -> + tr_expr ce le dst r sl a tmps -> match dst with | For_val => sl = nil /\ Csyntax.typeof r = typeof a /\ eval_expr tge e le m a v | For_effects => sl = nil @@ -320,18 +406,18 @@ Proof. Qed. Lemma tr_simple_lvalue: - forall e m l b ofs, - eval_simple_lvalue ge e m l b ofs -> + forall e m l b ofs bf, + eval_simple_lvalue ge e m l b ofs bf -> forall le sl a tmps, - tr_expr le For_val l sl a tmps -> - sl = nil /\ Csyntax.typeof l = typeof a /\ eval_lvalue tge e le m a b ofs. + tr_expr ce le For_val l sl a tmps -> + sl = nil /\ Csyntax.typeof l = typeof a /\ eval_lvalue tge e le m a b ofs bf. Proof. intros e m. exact (proj2 (tr_simple e m)). Qed. Lemma tr_simple_exprlist: forall le rl sl al tmps, - tr_exprlist le rl sl al tmps -> + tr_exprlist ce le rl sl al tmps -> forall e m tyl vl, eval_simple_list ge e m rl tyl vl -> sl = nil /\ eval_exprlist tge e le m al tyl vl. @@ -362,29 +448,29 @@ Lemma tr_expr_leftcontext_rec: ( forall from to C, leftcontext from to C -> forall le e dst sl a tmps, - tr_expr le dst (C e) sl a tmps -> + tr_expr ce le dst (C e) sl a tmps -> exists dst', exists sl1, exists sl2, exists a', exists tmp', - tr_expr le dst' e sl1 a' tmp' + tr_expr ce le dst' e sl1 a' tmp' /\ sl = sl1 ++ sl2 /\ incl tmp' tmps /\ (forall le' e' sl3, - tr_expr le' dst' e' sl3 a' tmp' -> + tr_expr ce le' dst' e' sl3 a' tmp' -> (forall id, ~In id tmp' -> le'!id = le!id) -> Csyntax.typeof e' = Csyntax.typeof e -> - tr_expr le' dst (C e') (sl3 ++ sl2) a tmps) + tr_expr ce le' dst (C e') (sl3 ++ sl2) a tmps) ) /\ ( forall from C, leftcontextlist from C -> forall le e sl a tmps, - tr_exprlist le (C e) sl a tmps -> + tr_exprlist ce le (C e) sl a tmps -> exists dst', exists sl1, exists sl2, exists a', exists tmp', - tr_expr le dst' e sl1 a' tmp' + tr_expr ce le dst' e sl1 a' tmp' /\ sl = sl1 ++ sl2 /\ incl tmp' tmps /\ (forall le' e' sl3, - tr_expr le' dst' e' sl3 a' tmp' -> + tr_expr ce le' dst' e' sl3 a' tmp' -> (forall id, ~In id tmp' -> le'!id = le!id) -> Csyntax.typeof e' = Csyntax.typeof e -> - tr_exprlist le' (C e') (sl3 ++ sl2) a tmps) + tr_exprlist ce le' (C e') (sl3 ++ sl2) a tmps) ). Proof. @@ -553,7 +639,7 @@ Ltac UNCHANGED := red; auto. intros. rewrite <- app_ass. econstructor. apply S; auto. eapply tr_expr_invariant; eauto. UNCHANGED. - auto. auto. auto. + auto. auto. auto. auto. + (* for val *) exploit H0; eauto. intros [dst' [sl1' [sl2' [a' [tmp' [P [Q [R S]]]]]]]]. TR. subst sl1. rewrite app_ass. eauto. @@ -561,7 +647,7 @@ Ltac UNCHANGED := intros. rewrite <- app_ass. econstructor. apply S; auto. eapply tr_expr_invariant; eauto. UNCHANGED. auto. auto. auto. auto. auto. auto. - eapply typeof_context; eauto. + eapply typeof_context. eauto. auto. eauto. auto. - (* assign right *) inv H2. @@ -573,7 +659,7 @@ Ltac UNCHANGED := intros. rewrite <- app_ass. change (sl3 ++ sl2') with (nil ++ (sl3 ++ sl2')). rewrite app_ass. econstructor. eapply tr_expr_invariant; eauto. UNCHANGED. - apply S; auto. auto. auto. auto. + apply S; auto. auto. auto. auto. auto. + (* for val *) assert (sl1 = nil) by (eapply tr_simple_expr_nil; eauto). subst sl1; simpl. exploit H1; eauto. intros [dst' [sl1' [sl2' [a' [tmp' [P [Q [R S]]]]]]]]. @@ -583,7 +669,7 @@ Ltac UNCHANGED := econstructor. eapply tr_expr_invariant; eauto. UNCHANGED. apply S; auto. auto. auto. auto. auto. auto. auto. auto. - eapply typeof_context; eauto. + eapply typeof_context; eauto. auto. - (* assignop left *) inv H1. + (* for effects *) @@ -593,7 +679,7 @@ Ltac UNCHANGED := intros. rewrite <- app_ass. econstructor. apply S; auto. eapply tr_expr_invariant; eauto. UNCHANGED. symmetry; eapply typeof_context; eauto. eauto. - auto. auto. auto. auto. auto. auto. + auto. auto. auto. auto. auto. auto. auto. + (* for val *) exploit H0; eauto. intros [dst' [sl1' [sl2' [a' [tmp' [P [Q [R S]]]]]]]]. TR. subst sl1. rewrite app_ass. eauto. @@ -601,7 +687,7 @@ Ltac UNCHANGED := intros. rewrite <- app_ass. econstructor. apply S; auto. eapply tr_expr_invariant; eauto. UNCHANGED. eauto. auto. auto. auto. auto. auto. auto. auto. auto. auto. auto. - eapply typeof_context; eauto. + eapply typeof_context; eauto. auto. - (* assignop right *) inv H2. + (* for effects *) @@ -611,7 +697,7 @@ Ltac UNCHANGED := red; auto. intros. rewrite <- app_ass. change (sl0 ++ sl2') with (nil ++ sl0 ++ sl2'). rewrite app_ass. econstructor. eapply tr_expr_invariant; eauto. UNCHANGED. - apply S; auto. auto. eauto. auto. auto. auto. auto. auto. auto. + apply S; auto. auto. eauto. auto. auto. auto. auto. auto. auto. auto. + (* for val *) assert (sl1 = nil) by (eapply tr_simple_expr_nil; eauto). subst sl1; simpl. exploit H1; eauto. intros [dst' [sl1' [sl2' [a' [tmp' [P [Q [R S]]]]]]]]. @@ -619,7 +705,7 @@ Ltac UNCHANGED := red; auto. intros. rewrite <- app_ass. change (sl0 ++ sl2') with (nil ++ sl0 ++ sl2'). rewrite app_ass. econstructor. eapply tr_expr_invariant; eauto. UNCHANGED. - apply S; auto. eauto. auto. auto. auto. auto. auto. auto. auto. auto. auto. auto. auto. + apply S; auto. eauto. auto. auto. auto. auto. auto. auto. auto. auto. auto. auto. auto. auto. - (* postincr *) inv H1. + (* for effects *) @@ -725,35 +811,35 @@ Qed. Theorem tr_expr_leftcontext: forall C le r dst sl a tmps, leftcontext RV RV C -> - tr_expr le dst (C r) sl a tmps -> + tr_expr ce le dst (C r) sl a tmps -> exists dst', exists sl1, exists sl2, exists a', exists tmp', - tr_expr le dst' r sl1 a' tmp' + tr_expr ce le dst' r sl1 a' tmp' /\ sl = sl1 ++ sl2 /\ incl tmp' tmps /\ (forall le' r' sl3, - tr_expr le' dst' r' sl3 a' tmp' -> + tr_expr ce le' dst' r' sl3 a' tmp' -> (forall id, ~In id tmp' -> le'!id = le!id) -> Csyntax.typeof r' = Csyntax.typeof r -> - tr_expr le' dst (C r') (sl3 ++ sl2) a tmps). + tr_expr ce le' dst (C r') (sl3 ++ sl2) a tmps). Proof. intros. eapply (proj1 tr_expr_leftcontext_rec); eauto. Qed. Theorem tr_top_leftcontext: forall e le m dst rtop sl a tmps, - tr_top tge e le m dst rtop sl a tmps -> + tr_top ce tge e le m dst rtop sl a tmps -> forall r C, rtop = C r -> leftcontext RV RV C -> exists dst', exists sl1, exists sl2, exists a', exists tmp', - tr_top tge e le m dst' r sl1 a' tmp' + tr_top ce tge e le m dst' r sl1 a' tmp' /\ sl = sl1 ++ sl2 /\ incl tmp' tmps /\ (forall le' m' r' sl3, - tr_expr le' dst' r' sl3 a' tmp' -> + tr_expr ce le' dst' r' sl3 a' tmp' -> (forall id, ~In id tmp' -> le'!id = le!id) -> Csyntax.typeof r' = Csyntax.typeof r -> - tr_top tge e le' m' dst (C r') (sl3 ++ sl2) a tmps). + tr_top ce tge e le' m' dst (C r') (sl3 ++ sl2) a tmps). Proof. induction 1; intros. (* val for val *) @@ -835,17 +921,18 @@ Proof. Qed. Lemma step_make_set: - forall id a ty m b ofs t v e le f k, - Csem.deref_loc ge ty m b ofs t v -> - eval_lvalue tge e le m a b ofs -> + forall id a ty m b ofs bf t v e le f k, + Csem.deref_loc ge ty m b ofs bf t v -> + eval_lvalue tge e le m a b ofs bf -> typeof a = ty -> - step1 tge (State f (make_set id a) k e le m) + step1 tge (State f (make_set bf id a) k e le m) t (State f Sskip k e (PTree.set id v le) m). Proof. intros. exploit deref_loc_translated; eauto. rewrite <- H1. - unfold make_set. destruct (chunk_for_volatile_type (typeof a)) as [chunk|]. + unfold make_set. destruct (chunk_for_volatile_type (typeof a) bf) as [chunk|]. (* volatile case *) - intros. change (PTree.set id v le) with (set_opttemp (Some id) v le). econstructor. + intros [A B]. subst bf. + change (PTree.set id v le) with (set_opttemp (Some id) v le). econstructor. econstructor. constructor. eauto. simpl. unfold sem_cast. simpl. eauto. constructor. simpl. econstructor; eauto. @@ -854,19 +941,19 @@ Proof. Qed. Lemma step_make_assign: - forall a1 a2 ty m b ofs t v m' v2 e le f k, - Csem.assign_loc ge ty m b ofs v t m' -> - eval_lvalue tge e le m a1 b ofs -> + forall a1 a2 ty m b ofs bf t v m' v' v2 e le f k, + Csem.assign_loc ge ty m b ofs bf v t m' v' -> + eval_lvalue tge e le m a1 b ofs bf -> eval_expr tge e le m a2 v2 -> sem_cast v2 (typeof a2) ty m = Some v -> typeof a1 = ty -> - step1 tge (State f (make_assign a1 a2) k e le m) + step1 tge (State f (make_assign bf a1 a2) k e le m) t (State f Sskip k e le m'). Proof. intros. exploit assign_loc_translated; eauto. rewrite <- H3. - unfold make_assign. destruct (chunk_for_volatile_type (typeof a1)) as [chunk|]. + unfold make_assign. destruct (chunk_for_volatile_type (typeof a1) bf) as [chunk|]. (* volatile case *) - intros. change le with (set_opttemp None Vundef le) at 2. econstructor. + intros [A B]. subst bf. change le with (set_opttemp None Vundef le) at 2. econstructor. econstructor. constructor. eauto. simpl. unfold sem_cast. simpl. eauto. econstructor; eauto. rewrite H3; eauto. constructor. @@ -900,10 +987,10 @@ Proof. Qed. Lemma step_tr_rvalof: - forall ty m b ofs t v e le a sl a' tmp f k, - Csem.deref_loc ge ty m b ofs t v -> - eval_lvalue tge e le m a b ofs -> - tr_rvalof ty a sl a' tmp -> + forall ty m b ofs bf t v e le a sl a' tmp f k, + Csem.deref_loc ge ty m b ofs bf t v -> + eval_lvalue tge e le m a b ofs bf -> + tr_rvalof ce ty a sl a' tmp -> typeof a = ty -> exists le', star step1 tge (State f Sskip (Kseqlist sl k) e le m) @@ -920,141 +1007,149 @@ Proof. split. eapply eval_Elvalue; eauto. auto. (* volatile *) - intros. exists (PTree.set t0 v le); split. + intros. + exploit is_bitfield_access_sound; eauto. intros EQ; subst bf0. + exists (PTree.set t0 v le); split. simpl. eapply star_two. econstructor. eapply step_make_set; eauto. traceEq. split. constructor. apply PTree.gss. split. auto. intros. apply PTree.gso. congruence. Qed. +End TRANSLATION. + + (** Matching between continuations *) -Inductive match_cont : Csem.cont -> cont -> Prop := - | match_Kstop: - match_cont Csem.Kstop Kstop - | match_Kseq: forall s k ts tk, - tr_stmt s ts -> - match_cont k tk -> - match_cont (Csem.Kseq s k) (Kseq ts tk) - | match_Kwhile2: forall r s k s' ts tk, - tr_if r Sskip Sbreak s' -> - tr_stmt s ts -> - match_cont k tk -> - match_cont (Csem.Kwhile2 r s k) - (Kloop1 (Ssequence s' ts) Sskip tk) - | match_Kdowhile1: forall r s k s' ts tk, - tr_if r Sskip Sbreak s' -> - tr_stmt s ts -> - match_cont k tk -> - match_cont (Csem.Kdowhile1 r s k) - (Kloop1 ts s' tk) - | match_Kfor3: forall r s3 s k ts3 s' ts tk, - tr_if r Sskip Sbreak s' -> - tr_stmt s3 ts3 -> - tr_stmt s ts -> - match_cont k tk -> - match_cont (Csem.Kfor3 r s3 s k) - (Kloop1 (Ssequence s' ts) ts3 tk) - | match_Kfor4: forall r s3 s k ts3 s' ts tk, - tr_if r Sskip Sbreak s' -> - tr_stmt s3 ts3 -> - tr_stmt s ts -> - match_cont k tk -> - match_cont (Csem.Kfor4 r s3 s k) - (Kloop2 (Ssequence s' ts) ts3 tk) - | match_Kswitch2: forall k tk, - match_cont k tk -> - match_cont (Csem.Kswitch2 k) (Kswitch tk) - | match_Kcall: forall f e C ty k optid tf le sl tk a dest tmps, - tr_function f tf -> - leftcontext RV RV C -> - (forall v m, tr_top tge e (set_opttemp optid v le) m dest (C (Csyntax.Eval v ty)) sl a tmps) -> - match_cont_exp dest a k tk -> - match_cont (Csem.Kcall f e C ty k) - (Kcall optid tf e le (Kseqlist sl tk)) -(* - | match_Kcall_some: forall f e C ty k dst tf le sl tk a dest tmps, - transl_function f = Errors.OK tf -> +Inductive match_cont : composite_env -> Csem.cont -> cont -> Prop := + | match_Kstop: forall ce, + match_cont ce Csem.Kstop Kstop + | match_Kseq: forall ce s k ts tk, + tr_stmt ce s ts -> + match_cont ce k tk -> + match_cont ce (Csem.Kseq s k) (Kseq ts tk) + | match_Kwhile2: forall ce r s k s' ts tk, + tr_if ce r Sskip Sbreak s' -> + tr_stmt ce s ts -> + match_cont ce k tk -> + match_cont ce (Csem.Kwhile2 r s k) + (Kloop1 (Ssequence s' ts) Sskip tk) + | match_Kdowhile1: forall ce r s k s' ts tk, + tr_if ce r Sskip Sbreak s' -> + tr_stmt ce s ts -> + match_cont ce k tk -> + match_cont ce (Csem.Kdowhile1 r s k) + (Kloop1 ts s' tk) + | match_Kfor3: forall ce r s3 s k ts3 s' ts tk, + tr_if ce r Sskip Sbreak s' -> + tr_stmt ce s3 ts3 -> + tr_stmt ce s ts -> + match_cont ce k tk -> + match_cont ce (Csem.Kfor3 r s3 s k) + (Kloop1 (Ssequence s' ts) ts3 tk) + | match_Kfor4: forall ce r s3 s k ts3 s' ts tk, + tr_if ce r Sskip Sbreak s' -> + tr_stmt ce s3 ts3 -> + tr_stmt ce s ts -> + match_cont ce k tk -> + match_cont ce (Csem.Kfor4 r s3 s k) + (Kloop2 (Ssequence s' ts) ts3 tk) + | match_Kswitch2: forall ce k tk, + match_cont ce k tk -> + match_cont ce (Csem.Kswitch2 k) (Kswitch tk) + | match_Kcall: forall f e C ty k optid tf le sl tk a dest tmps cu ce, + linkorder cu prog -> + tr_function cu.(prog_comp_env) f tf -> leftcontext RV RV C -> - (forall v m, tr_top tge e (PTree.set dst v le) m dest (C (C.Eval v ty)) sl a tmps) -> - match_cont_exp dest a k tk -> - match_cont (Csem.Kcall f e C ty k) - (Kcall (Some dst) tf e le (Kseqlist sl tk)) -*) - -with match_cont_exp : destination -> expr -> Csem.cont -> cont -> Prop := - | match_Kdo: forall k a tk, - match_cont k tk -> - match_cont_exp For_effects a (Csem.Kdo k) tk - | match_Kifthenelse_empty: forall a k tk, - match_cont k tk -> - match_cont_exp For_val a (Csem.Kifthenelse Csyntax.Sskip Csyntax.Sskip k) (Kseq Sskip tk) - | match_Kifthenelse_1: forall a s1 s2 k ts1 ts2 tk, - tr_stmt s1 ts1 -> tr_stmt s2 ts2 -> - match_cont k tk -> - match_cont_exp For_val a (Csem.Kifthenelse s1 s2 k) (Kseq (Sifthenelse a ts1 ts2) tk) - | match_Kwhile1: forall r s k s' a ts tk, - tr_if r Sskip Sbreak s' -> - tr_stmt s ts -> - match_cont k tk -> - match_cont_exp For_val a + (forall v m, tr_top cu.(prog_comp_env) tge e (set_opttemp optid v le) m dest (C (Csyntax.Eval v ty)) sl a tmps) -> + match_cont_exp cu.(prog_comp_env) dest a k tk -> + match_cont ce (Csem.Kcall f e C ty k) + (Kcall optid tf e le (Kseqlist sl tk)) + +with match_cont_exp : composite_env -> destination -> expr -> Csem.cont -> cont -> Prop := + | match_Kdo: forall ce k a tk, + match_cont ce k tk -> + match_cont_exp ce For_effects a (Csem.Kdo k) tk + | match_Kifthenelse_empty: forall ce a k tk, + match_cont ce k tk -> + match_cont_exp ce For_val a (Csem.Kifthenelse Csyntax.Sskip Csyntax.Sskip k) (Kseq Sskip tk) + | match_Kifthenelse_1: forall ce a s1 s2 k ts1 ts2 tk, + tr_stmt ce s1 ts1 -> tr_stmt ce s2 ts2 -> + match_cont ce k tk -> + match_cont_exp ce For_val a (Csem.Kifthenelse s1 s2 k) (Kseq (Sifthenelse a ts1 ts2) tk) + | match_Kwhile1: forall ce r s k s' a ts tk, + tr_if ce r Sskip Sbreak s' -> + tr_stmt ce s ts -> + match_cont ce k tk -> + match_cont_exp ce For_val a (Csem.Kwhile1 r s k) (Kseq (makeif a Sskip Sbreak) (Kseq ts (Kloop1 (Ssequence s' ts) Sskip tk))) - | match_Kdowhile2: forall r s k s' a ts tk, - tr_if r Sskip Sbreak s' -> - tr_stmt s ts -> - match_cont k tk -> - match_cont_exp For_val a + | match_Kdowhile2: forall ce r s k s' a ts tk, + tr_if ce r Sskip Sbreak s' -> + tr_stmt ce s ts -> + match_cont ce k tk -> + match_cont_exp ce For_val a (Csem.Kdowhile2 r s k) (Kseq (makeif a Sskip Sbreak) (Kloop2 ts s' tk)) - | match_Kfor2: forall r s3 s k s' a ts3 ts tk, - tr_if r Sskip Sbreak s' -> - tr_stmt s3 ts3 -> - tr_stmt s ts -> - match_cont k tk -> - match_cont_exp For_val a + | match_Kfor2: forall ce r s3 s k s' a ts3 ts tk, + tr_if ce r Sskip Sbreak s' -> + tr_stmt ce s3 ts3 -> + tr_stmt ce s ts -> + match_cont ce k tk -> + match_cont_exp ce For_val a (Csem.Kfor2 r s3 s k) (Kseq (makeif a Sskip Sbreak) (Kseq ts (Kloop1 (Ssequence s' ts) ts3 tk))) - | match_Kswitch1: forall ls k a tls tk, - tr_lblstmts ls tls -> - match_cont k tk -> - match_cont_exp For_val a (Csem.Kswitch1 ls k) (Kseq (Sswitch a tls) tk) - | match_Kreturn: forall k a tk, - match_cont k tk -> - match_cont_exp For_val a (Csem.Kreturn k) (Kseq (Sreturn (Some a)) tk). - -Lemma match_cont_call: - forall k tk, - match_cont k tk -> - match_cont (Csem.call_cont k) (call_cont tk). + | match_Kswitch1: forall ce ls k a tls tk, + tr_lblstmts ce ls tls -> + match_cont ce k tk -> + match_cont_exp ce For_val a (Csem.Kswitch1 ls k) (Kseq (Sswitch a tls) tk) + | match_Kreturn: forall ce k a tk, + match_cont ce k tk -> + match_cont_exp ce For_val a (Csem.Kreturn k) (Kseq (Sreturn (Some a)) tk). + +Lemma match_cont_is_call_cont: + forall ce k tk, + match_cont ce k tk -> Csem.is_call_cont k -> + forall ce', match_cont ce' k tk. Proof. - induction 1; simpl; auto. constructor. econstructor; eauto. + destruct 1; simpl; intros; try contradiction; econstructor; eauto. +Qed. + +Lemma match_cont_call_cont: + forall ce k tk, + match_cont ce k tk -> + forall ce', match_cont ce' (Csem.call_cont k) (call_cont tk). +Proof. + induction 1; simpl; auto; intros; econstructor; eauto. Qed. (** Matching between states *) Inductive match_states: Csem.state -> state -> Prop := - | match_exprstates: forall f r k e m tf sl tk le dest a tmps, - tr_function f tf -> - tr_top tge e le m dest r sl a tmps -> - match_cont_exp dest a k tk -> + | match_exprstates: forall f r k e m tf sl tk le dest a tmps cu + (LINK: linkorder cu prog) + (TRF: tr_function cu.(prog_comp_env) f tf) + (TR: tr_top cu.(prog_comp_env) tge e le m dest r sl a tmps) + (MK: match_cont_exp cu.(prog_comp_env) dest a k tk), match_states (Csem.ExprState f r k e m) (State tf Sskip (Kseqlist sl tk) e le m) - | match_regularstates: forall f s k e m tf ts tk le, - tr_function f tf -> - tr_stmt s ts -> - match_cont k tk -> + | match_regularstates: forall f s k e m tf ts tk le cu + (LINK: linkorder cu prog) + (TRF: tr_function cu.(prog_comp_env) f tf) + (TR: tr_stmt cu.(prog_comp_env) s ts) + (MK: match_cont cu.(prog_comp_env) k tk), match_states (Csem.State f s k e m) (State tf ts tk e le m) - | match_callstates: forall fd args k m tfd tk, - tr_fundef fd tfd -> - match_cont k tk -> + | match_callstates: forall fd args k m tfd tk cu + (LINK: linkorder cu prog) + (TR: tr_fundef cu fd tfd) + (MK: forall ce, match_cont ce k tk), match_states (Csem.Callstate fd args k m) (Callstate tfd args tk m) - | match_returnstates: forall res k m tk, - match_cont k tk -> + | match_returnstates: forall res k m tk + (MK: forall ce, match_cont ce k tk), match_states (Csem.Returnstate res k m) (Returnstate res tk m) | match_stuckstate: forall S, @@ -1063,21 +1158,22 @@ Inductive match_states: Csem.state -> state -> Prop := (** Additional results on translation of statements *) Lemma tr_select_switch: - forall n ls tls, - tr_lblstmts ls tls -> - tr_lblstmts (Csem.select_switch n ls) (select_switch n tls). + forall ce n ls tls, + tr_lblstmts ce ls tls -> + tr_lblstmts ce (Csem.select_switch n ls) (select_switch n tls). Proof. + intros ce. assert (DFL: forall ls tls, - tr_lblstmts ls tls -> - tr_lblstmts (Csem.select_switch_default ls) (select_switch_default tls)). + tr_lblstmts ce ls tls -> + tr_lblstmts ce (Csem.select_switch_default ls) (select_switch_default tls)). { induction 1; simpl. constructor. destruct c; auto. constructor; auto. } assert (CASE: forall n ls tls, - tr_lblstmts ls tls -> + tr_lblstmts ce ls tls -> match Csem.select_switch_case n ls with | None => select_switch_case n tls = None | Some ls' => - exists tls', select_switch_case n tls = Some tls' /\ tr_lblstmts ls' tls' + exists tls', select_switch_case n tls = Some tls' /\ tr_lblstmts ce ls' tls' end). { induction 1; simpl; intros. auto. @@ -1091,9 +1187,9 @@ Proof. Qed. Lemma tr_seq_of_labeled_statement: - forall ls tls, - tr_lblstmts ls tls -> - tr_stmt (Csem.seq_of_labeled_statement ls) (seq_of_labeled_statement tls). + forall ce ls tls, + tr_lblstmts ce ls tls -> + tr_stmt ce (Csem.seq_of_labeled_statement ls) (seq_of_labeled_statement tls). Proof. induction 1; simpl; constructor; auto. Qed. @@ -1102,6 +1198,7 @@ Qed. Section FIND_LABEL. +Variable ce: composite_env. Variable lbl: label. Definition nolabel (s: statement) : Prop := @@ -1137,21 +1234,21 @@ Proof. Qed. Lemma make_set_nolabel: - forall t a, nolabel (make_set t a). + forall bf t a, nolabel (make_set bf t a). Proof. unfold make_set; intros; red; intros. - destruct (chunk_for_volatile_type (typeof a)); auto. + destruct (chunk_for_volatile_type (typeof a) bf); auto. Qed. Lemma make_assign_nolabel: - forall l r, nolabel (make_assign l r). + forall bf l r, nolabel (make_assign bf l r). Proof. unfold make_assign; intros; red; intros. - destruct (chunk_for_volatile_type (typeof l)); auto. + destruct (chunk_for_volatile_type (typeof l) bf); auto. Qed. Lemma tr_rvalof_nolabel: - forall ty a sl a' tmp, tr_rvalof ty a sl a' tmp -> nolabel_list sl. + forall ce ty a sl a' tmp, tr_rvalof ce ty a sl a' tmp -> nolabel_list sl. Proof. destruct 1; simpl; intuition. apply make_set_nolabel. Qed. @@ -1177,16 +1274,16 @@ Ltac NoLabelTac := | [ H: _ -> nolabel_list ?x |- nolabel_list ?x ] => apply H; NoLabelTac | [ |- nolabel (makeseq _) ] => apply makeseq_nolabel; NoLabelTac | [ |- nolabel (makeif _ _ _) ] => apply makeif_nolabel; NoLabelTac - | [ |- nolabel (make_set _ _) ] => apply make_set_nolabel - | [ |- nolabel (make_assign _ _) ] => apply make_assign_nolabel + | [ |- nolabel (make_set _ _ _) ] => apply make_set_nolabel + | [ |- nolabel (make_assign _ _ _) ] => apply make_assign_nolabel | [ |- nolabel _ ] => red; intros; simpl; auto | [ |- _ /\ _ ] => split; NoLabelTac | _ => auto end. Lemma tr_find_label_expr: - (forall le dst r sl a tmps, tr_expr le dst r sl a tmps -> nolabel_list sl) -/\(forall le rl sl al tmps, tr_exprlist le rl sl al tmps -> nolabel_list sl). + (forall le dst r sl a tmps, tr_expr ce le dst r sl a tmps -> nolabel_list sl) +/\(forall le rl sl al tmps, tr_exprlist ce le rl sl al tmps -> nolabel_list sl). Proof. apply tr_expr_exprlist; intros; NoLabelTac. apply nolabel_do_set. @@ -1200,14 +1297,14 @@ Qed. Lemma tr_find_label_top: forall e le m dst r sl a tmps, - tr_top tge e le m dst r sl a tmps -> nolabel_list sl. + tr_top ce tge e le m dst r sl a tmps -> nolabel_list sl. Proof. induction 1; intros; NoLabelTac. eapply (proj1 tr_find_label_expr); eauto. Qed. Lemma tr_find_label_expression: - forall r s a, tr_expression r s a -> forall k, find_label lbl s k = None. + forall r s a, tr_expression ce r s a -> forall k, find_label lbl s k = None. Proof. intros. inv H. assert (nolabel (makeseq sl)). apply makeseq_nolabel. @@ -1216,7 +1313,7 @@ Proof. Qed. Lemma tr_find_label_expr_stmt: - forall r s, tr_expr_stmt r s -> forall k, find_label lbl s k = None. + forall r s, tr_expr_stmt ce r s -> forall k, find_label lbl s k = None. Proof. intros. inv H. assert (nolabel (makeseq sl)). apply makeseq_nolabel. @@ -1226,7 +1323,7 @@ Qed. Lemma tr_find_label_if: forall r s, - tr_if r Sskip Sbreak s -> + tr_if ce r Sskip Sbreak s -> forall k, find_label lbl s k = None. Proof. intros. inv H. @@ -1241,29 +1338,29 @@ Qed. Lemma tr_find_label: forall s k ts tk - (TR: tr_stmt s ts) - (MC: match_cont k tk), + (TR: tr_stmt ce s ts) + (MC: match_cont ce k tk), match Csem.find_label lbl s k with | None => find_label lbl ts tk = None | Some (s', k') => exists ts', exists tk', find_label lbl ts tk = Some (ts', tk') - /\ tr_stmt s' ts' - /\ match_cont k' tk' + /\ tr_stmt ce s' ts' + /\ match_cont ce k' tk' end with tr_find_label_ls: forall s k ts tk - (TR: tr_lblstmts s ts) - (MC: match_cont k tk), + (TR: tr_lblstmts ce s ts) + (MC: match_cont ce k tk), match Csem.find_label_ls lbl s k with | None => find_label_ls lbl ts tk = None | Some (s', k') => exists ts', exists tk', find_label_ls lbl ts tk = Some (ts', tk') - /\ tr_stmt s' ts' - /\ match_cont k' tk' + /\ tr_stmt ce s' ts' + /\ match_cont ce k' tk' end. Proof. induction s; intros; inversion TR; subst; clear TR; simpl. @@ -1362,7 +1459,7 @@ The following measure decreases for these stuttering steps. *) Fixpoint esize (a: Csyntax.expr) : nat := match a with - | Csyntax.Eloc _ _ _ => 1%nat + | Csyntax.Eloc _ _ _ _ => 1%nat | Csyntax.Evar _ _ => 1%nat | Csyntax.Ederef r1 _ => S(esize r1) | Csyntax.Efield l1 _ _ => S(esize l1) @@ -1423,12 +1520,12 @@ Qed. (** Forward simulation for expressions. *) Lemma tr_val_gen: - forall le dst v ty a tmp, + forall ce le dst v ty a tmp, typeof a = ty -> (forall tge e le' m, (forall id, In id tmp -> le'!id = le!id) -> eval_expr tge e le' m a v) -> - tr_expr le dst (Csyntax.Eval v ty) (final dst a) a tmp. + tr_expr ce le dst (Csyntax.Eval v ty) (final dst a) a tmp. Proof. intros. destruct dst; simpl; econstructor; auto. Qed. @@ -1441,43 +1538,53 @@ Lemma estep_simulation: (star step1 tge S1' t S2' /\ measure S2 < measure S1)%nat) /\ match_states S2 S2'. Proof. + +Ltac NOTIN := + match goal with + | [ H1: In ?x ?l, H2: list_disjoint ?l _ |- ~In ?x _ ] => + red; intro; elim (H2 x x); auto; fail + | [ H1: In ?x ?l, H2: list_disjoint _ ?l |- ~In ?x _ ] => + red; intro; elim (H2 x x); auto; fail + end. + induction 1; intros; inv MS. -(* expr *) - assert (tr_expr le dest r sl a tmps). - inv H9. contradiction. auto. +- (* expr *) + assert (tr_expr (prog_comp_env cu) le dest r sl a tmps). + { inv TR. contradiction. auto. } exploit tr_simple_rvalue; eauto. destruct dest. - (* for val *) ++ (* for val *) intros [SL1 [TY1 EV1]]. subst sl. econstructor; split. - right; split. apply star_refl. destruct r; simpl; (contradiction || omega). + right; split. apply star_refl. destruct r; simpl; (contradiction || lia). econstructor; eauto. instantiate (1 := tmps). apply tr_top_val_val; auto. - (* for effects *) ++ (* for effects *) intros SL1. subst sl. econstructor; split. - right; split. apply star_refl. destruct r; simpl; (contradiction || omega). + right; split. apply star_refl. destruct r; simpl; (contradiction || lia). econstructor; eauto. instantiate (1 := tmps). apply tr_top_base. constructor. - (* for set *) - inv H10. -(* rval volatile *) - exploit tr_top_leftcontext; eauto. clear H11. ++ (* for set *) + inv MK. +- (* rval volatile *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H2. inv H7; try congruence. exploit tr_simple_lvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl. + exploit is_bitfield_access_sound; eauto. intros EQ; subst bf0. econstructor; split. left. eapply plus_two. constructor. eapply step_make_set; eauto. traceEq. econstructor; eauto. change (final dst' (Etempvar t0 (Csyntax.typeof l)) ++ sl2) with (nil ++ (final dst' (Etempvar t0 (Csyntax.typeof l)) ++ sl2)). apply S. apply tr_val_gen. auto. - intros. constructor. rewrite H5; auto. apply PTree.gss. - intros. apply PTree.gso. red; intros; subst; elim H5; auto. + intros. constructor. rewrite H7; auto. apply PTree.gss. + intros. apply PTree.gso. red; intros; subst; elim H7; auto. auto. -(* seqand true *) - exploit tr_top_leftcontext; eauto. clear H9. +- (* seqand true *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H2. - (* for val *) ++ (* for val *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. econstructor; split. @@ -1488,7 +1595,7 @@ Proof. eapply match_exprstates; eauto. apply S. apply tr_paren_val with (a1 := a2); auto. apply tr_expr_monotone with tmp2; eauto. auto. auto. - (* for effects *) ++ (* for effects *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. econstructor; split. @@ -1499,7 +1606,7 @@ Proof. eapply match_exprstates; eauto. apply S. apply tr_paren_effects with (a1 := a2); auto. apply tr_expr_monotone with tmp2; eauto. auto. auto. - (* for set *) ++ (* for set *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. econstructor; split. @@ -1510,11 +1617,11 @@ Proof. eapply match_exprstates; eauto. apply S. apply tr_paren_set with (a1 := a2) (t := sd_temp sd); auto. apply tr_expr_monotone with tmp2; eauto. auto. auto. -(* seqand false *) - exploit tr_top_leftcontext; eauto. clear H9. +- (* seqand false *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H2. - (* for val *) ++ (* for val *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. econstructor; split. @@ -1526,7 +1633,7 @@ Proof. intros. constructor. rewrite H2. apply PTree.gss. auto. intros. apply PTree.gso. congruence. auto. - (* for effects *) ++ (* for effects *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. econstructor; split. @@ -1536,7 +1643,7 @@ Proof. eapply match_exprstates; eauto. change sl2 with (nil ++ sl2). apply S. econstructor; eauto. auto. auto. - (* for set *) ++ (* for set *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. econstructor; split. @@ -1546,11 +1653,11 @@ Proof. rewrite <- Kseqlist_app. eapply match_exprstates; eauto. apply S. econstructor; eauto. intros. constructor. auto. auto. -(* seqor true *) - exploit tr_top_leftcontext; eauto. clear H9. +- (* seqor true *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H2. - (* for val *) ++ (* for val *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. econstructor; split. @@ -1562,7 +1669,7 @@ Proof. intros. constructor. rewrite H2. apply PTree.gss. auto. intros. apply PTree.gso. congruence. auto. - (* for effects *) ++ (* for effects *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. econstructor; split. @@ -1572,7 +1679,7 @@ Proof. eapply match_exprstates; eauto. change sl2 with (nil ++ sl2). apply S. econstructor; eauto. auto. auto. - (* for set *) ++ (* for set *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. econstructor; split. @@ -1582,11 +1689,11 @@ Proof. rewrite <- Kseqlist_app. eapply match_exprstates; eauto. apply S. econstructor; eauto. intros. constructor. auto. auto. -(* seqand false *) - exploit tr_top_leftcontext; eauto. clear H9. +- (* seqand false *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H2. - (* for val *) ++ (* for val *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. econstructor; split. @@ -1597,7 +1704,7 @@ Proof. eapply match_exprstates; eauto. apply S. apply tr_paren_val with (a1 := a2); auto. apply tr_expr_monotone with tmp2; eauto. auto. auto. - (* for effects *) ++ (* for effects *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. econstructor; split. @@ -1608,7 +1715,7 @@ Proof. eapply match_exprstates; eauto. apply S. apply tr_paren_effects with (a1 := a2); auto. apply tr_expr_monotone with tmp2; eauto. auto. auto. - (* for set *) ++ (* for set *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. econstructor; split. @@ -1619,11 +1726,11 @@ Proof. eapply match_exprstates; eauto. apply S. apply tr_paren_set with (a1 := a2) (t := sd_temp sd); auto. apply tr_expr_monotone with tmp2; eauto. auto. auto. -(* condition *) - exploit tr_top_leftcontext; eauto. clear H9. +- (* condition *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H2. - (* for value *) ++ (* for value *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. destruct b. econstructor; split. @@ -1640,7 +1747,7 @@ Proof. rewrite <- Kseqlist_app. eapply match_exprstates; eauto. apply S. econstructor; eauto. apply tr_expr_monotone with tmp3; eauto. auto. auto. - (* for effects *) ++ (* for effects *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. destruct b. econstructor; split. @@ -1649,7 +1756,7 @@ Proof. apply push_seq. reflexivity. traceEq. rewrite <- Kseqlist_app. - econstructor. eauto. apply S. + econstructor; eauto. apply S. econstructor; eauto. apply tr_expr_monotone with tmp2; eauto. econstructor; eauto. auto. auto. @@ -1659,11 +1766,11 @@ Proof. apply push_seq. reflexivity. traceEq. rewrite <- Kseqlist_app. - econstructor. eauto. apply S. + econstructor; eauto. apply S. econstructor; eauto. apply tr_expr_monotone with tmp3; eauto. econstructor; eauto. - auto. auto. - (* for set *) + auto. ++ (* for set *) exploit tr_simple_rvalue; eauto. intros [SL [TY EV]]. subst sl0; simpl Kseqlist. destruct b. econstructor; split. @@ -1672,40 +1779,42 @@ Proof. apply push_seq. reflexivity. traceEq. rewrite <- Kseqlist_app. - econstructor. eauto. apply S. + econstructor; eauto. apply S. econstructor; eauto. apply tr_expr_monotone with tmp2; eauto. econstructor; eauto. - auto. auto. + auto. econstructor; split. left. eapply plus_left. constructor. eapply star_trans. apply step_makeif with (b := false) (v1 := v); auto. congruence. apply push_seq. reflexivity. traceEq. rewrite <- Kseqlist_app. - econstructor. eauto. apply S. + econstructor; eauto. apply S. econstructor; eauto. apply tr_expr_monotone with tmp3; eauto. econstructor; eauto. - auto. auto. -(* assign *) - exploit tr_top_leftcontext; eauto. clear H12. + auto. +- (* assign *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H4. - (* for effects *) ++ (* for effects *) exploit tr_simple_rvalue; eauto. intros [SL2 [TY2 EV2]]. exploit tr_simple_lvalue; eauto. intros [SL1 [TY1 EV1]]. + assert (bf0 = bf) by (eapply is_bitfield_access_sound; eauto). subst; simpl Kseqlist. econstructor; split. left. eapply plus_left. constructor. apply star_one. eapply step_make_assign; eauto. rewrite <- TY2; eauto. traceEq. - econstructor. auto. change sl2 with (nil ++ sl2). apply S. - constructor. auto. auto. auto. - (* for value *) + econstructor; eauto. change sl2 with (nil ++ sl2). apply S. + constructor. auto. auto. ++ (* for value *) exploit tr_simple_rvalue; eauto. intros [SL2 [TY2 EV2]]. exploit tr_simple_lvalue. eauto. - eapply tr_expr_invariant with (le' := PTree.set t0 v' le). eauto. + eapply tr_expr_invariant with (le' := PTree.set t0 v1 le). eauto. intros. apply PTree.gso. intuition congruence. intros [SL1 [TY1 EV1]]. + assert (bf0 = bf) by (eapply is_bitfield_access_sound; eauto). subst; simpl Kseqlist. econstructor; split. left. eapply plus_left. constructor. @@ -1714,22 +1823,24 @@ Proof. apply star_one. eapply step_make_assign; eauto. constructor. apply PTree.gss. simpl. eapply cast_idempotent; eauto. reflexivity. reflexivity. traceEq. - econstructor. auto. apply S. - apply tr_val_gen. auto. intros. constructor. - rewrite H4; auto. apply PTree.gss. + econstructor; eauto. apply S. + apply tr_val_gen. rewrite typeof_make_assign_value; auto. + intros. eapply make_assign_value_sound; eauto. + constructor. rewrite H4; auto. apply PTree.gss. intros. apply PTree.gso. intuition congruence. - auto. auto. -(* assignop *) - exploit tr_top_leftcontext; eauto. clear H15. + auto. +- (* assignop *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H6. - (* for effects *) ++ (* for effects *) exploit tr_simple_lvalue; eauto. intros [SL1 [TY1 EV1]]. exploit step_tr_rvalof; eauto. intros [le' [EXEC [EV3 [TY3 INV]]]]. exploit tr_simple_lvalue. eauto. eapply tr_expr_invariant with (le := le) (le' := le'). eauto. intros. apply INV. NOTIN. intros [? [? EV1']]. exploit tr_simple_rvalue. eauto. eapply tr_expr_invariant with (le := le) (le' := le'). eauto. intros. apply INV. NOTIN. simpl. intros [SL2 [TY2 EV2]]. + assert (bf0 = bf) by (eapply is_bitfield_access_sound; eauto). subst; simpl Kseqlist. econstructor; split. left. eapply star_plus_trans. rewrite app_ass. rewrite Kseqlist_app. eexact EXEC. @@ -1737,9 +1848,9 @@ Proof. econstructor. eexact EV3. eexact EV2. rewrite TY3; rewrite <- TY1; rewrite <- TY2; rewrite comp_env_preserved; auto. reflexivity. traceEq. - econstructor. auto. change sl2 with (nil ++ sl2). apply S. - constructor. auto. auto. auto. - (* for value *) + econstructor; eauto. change sl2 with (nil ++ sl2). apply S. + constructor. auto. auto. ++ (* for value *) exploit tr_simple_lvalue; eauto. intros [SL1 [TY1 EV1]]. exploit step_tr_rvalof; eauto. intros [le' [EXEC [EV3 [TY3 INV]]]]. exploit tr_simple_lvalue. eauto. eapply tr_expr_invariant with (le := le) (le' := le'). eauto. @@ -1750,6 +1861,7 @@ Proof. eapply tr_expr_invariant with (le := le) (le' := PTree.set t v4 le'). eauto. intros. rewrite PTree.gso. apply INV. NOTIN. intuition congruence. intros [? [? EV1'']]. + assert (bf0 = bf) by (eapply is_bitfield_access_sound; eauto). subst; simpl Kseqlist. econstructor; split. left. rewrite app_ass. rewrite Kseqlist_app. @@ -1761,44 +1873,46 @@ Proof. econstructor. eapply step_make_assign; eauto. constructor. apply PTree.gss. simpl. eapply cast_idempotent; eauto. reflexivity. traceEq. - econstructor. auto. apply S. - apply tr_val_gen. auto. intros. constructor. - rewrite H10; auto. apply PTree.gss. + econstructor; eauto. apply S. + apply tr_val_gen. rewrite typeof_make_assign_value; auto. + intros. eapply make_assign_value_sound; eauto. + constructor. rewrite H10; auto. apply PTree.gss. intros. rewrite PTree.gso. apply INV. red; intros; elim H10; auto. intuition congruence. - auto. auto. -(* assignop stuck *) - exploit tr_top_leftcontext; eauto. clear H12. + auto. +- (* assignop stuck *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H4. - (* for effects *) ++ (* for effects *) exploit tr_simple_lvalue; eauto. intros [SL1 [TY1 EV1]]. exploit tr_simple_rvalue; eauto. intros [SL2 [TY2 EV2]]. exploit step_tr_rvalof; eauto. intros [le' [EXEC [EV3 [TY3 INV]]]]. subst; simpl Kseqlist. econstructor; split. right; split. rewrite app_ass. rewrite Kseqlist_app. eexact EXEC. - simpl. omega. + simpl. lia. constructor. - (* for value *) ++ (* for value *) exploit tr_simple_lvalue; eauto. intros [SL1 [TY1 EV1]]. exploit tr_simple_rvalue; eauto. intros [SL2 [TY2 EV2]]. exploit step_tr_rvalof; eauto. intros [le' [EXEC [EV3 [TY3 INV]]]]. subst; simpl Kseqlist. econstructor; split. right; split. rewrite app_ass. rewrite Kseqlist_app. eexact EXEC. - simpl. omega. + simpl. lia. constructor. -(* postincr *) - exploit tr_top_leftcontext; eauto. clear H14. +- (* postincr *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H5. - (* for effects *) ++ (* for effects *) exploit tr_simple_lvalue; eauto. intros [SL1 [TY1 EV1]]. exploit step_tr_rvalof; eauto. intros [le' [EXEC [EV3 [TY3 INV]]]]. exploit tr_simple_lvalue. eauto. eapply tr_expr_invariant with (le := le) (le' := le'). eauto. intros. apply INV. NOTIN. intros [? [? EV1']]. + assert (bf0 = bf) by (eapply is_bitfield_access_sound; eauto). subst; simpl Kseqlist. econstructor; split. left. rewrite app_ass; rewrite Kseqlist_app. @@ -1810,14 +1924,15 @@ Proof. econstructor. eauto. constructor. rewrite TY3; rewrite <- TY1; rewrite comp_env_preserved. simpl; eauto. destruct id; auto. reflexivity. traceEq. - econstructor. auto. change sl2 with (nil ++ sl2). apply S. - constructor. auto. auto. auto. - (* for value *) + econstructor; eauto. change sl2 with (nil ++ sl2). apply S. + constructor. auto. auto. ++ (* for value *) exploit tr_simple_lvalue; eauto. intros [SL1 [TY1 EV1]]. exploit tr_simple_lvalue. eauto. eapply tr_expr_invariant with (le' := PTree.set t v1 le). eauto. intros. apply PTree.gso. intuition congruence. intros [SL2 [TY2 EV2]]. + assert (bf0 = bf) by (eapply is_bitfield_access_sound; eauto). subst; simpl Kseqlist. econstructor; split. left. eapply plus_four. constructor. @@ -1831,47 +1946,48 @@ Proof. rewrite comp_env_preserved; simpl; eauto. destruct id; auto. traceEq. - econstructor. auto. apply S. + econstructor; eauto. apply S. apply tr_val_gen. auto. intros. econstructor; eauto. rewrite H5; auto. apply PTree.gss. intros. apply PTree.gso. intuition congruence. - auto. auto. -(* postincr stuck *) - exploit tr_top_leftcontext; eauto. clear H11. + auto. +- (* postincr stuck *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H3. - (* for effects *) ++ (* for effects *) exploit tr_simple_lvalue; eauto. intros [SL1 [TY1 EV1]]. exploit step_tr_rvalof; eauto. intros [le' [EXEC [EV3 [TY3 INV]]]]. subst. simpl Kseqlist. econstructor; split. right; split. rewrite app_ass; rewrite Kseqlist_app. eexact EXEC. - simpl; omega. + simpl; lia. constructor. - (* for value *) ++ (* for value *) exploit tr_simple_lvalue; eauto. intros [SL1 [TY1 EV1]]. + assert (bf0 = bf) by (eapply is_bitfield_access_sound; eauto). subst. simpl Kseqlist. econstructor; split. left. eapply plus_two. constructor. eapply step_make_set; eauto. traceEq. constructor. -(* comma *) - exploit tr_top_leftcontext; eauto. clear H9. +- (* comma *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H1. exploit tr_simple_rvalue; eauto. simpl; intro SL1. subst sl0; simpl Kseqlist. econstructor; split. right; split. apply star_refl. simpl. apply plus_lt_compat_r. - apply (leftcontext_size _ _ _ H). simpl. omega. + apply (leftcontext_size _ _ _ H). simpl. lia. econstructor; eauto. apply S. eapply tr_expr_monotone; eauto. auto. auto. -(* paren *) - exploit tr_top_leftcontext; eauto. clear H9. +- (* paren *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H2. - (* for value *) ++ (* for value *) exploit tr_simple_rvalue; eauto. intros [b [SL1 [TY1 EV1]]]. subst sl1; simpl Kseqlist. econstructor; split. @@ -1882,14 +1998,14 @@ Proof. constructor. auto. intros. constructor. rewrite H2; auto. apply PTree.gss. intros. apply PTree.gso. intuition congruence. auto. - (* for effects *) ++ (* for effects *) econstructor; split. right; split. apply star_refl. simpl. apply plus_lt_compat_r. - apply (leftcontext_size _ _ _ H). simpl. omega. + apply (leftcontext_size _ _ _ H). simpl. lia. econstructor; eauto. exploit tr_simple_rvalue; eauto. simpl. intros A. subst sl1. apply S. constructor; auto. auto. auto. - (* for set *) ++ (* for set *) exploit tr_simple_rvalue; eauto. simpl. intros [b [SL1 [TY1 EV1]]]. subst sl1. simpl Kseqlist. econstructor; split. @@ -1901,46 +2017,46 @@ Proof. intros. apply PTree.gso. congruence. auto. -(* call *) - exploit tr_top_leftcontext; eauto. clear H12. +- (* call *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H5. - (* for effects *) ++ (* for effects *) exploit tr_simple_rvalue; eauto. intros [SL1 [TY1 EV1]]. exploit tr_simple_exprlist; eauto. intros [SL2 EV2]. subst. simpl Kseqlist. - exploit functions_translated; eauto. intros [tfd [J K]]. + exploit functions_translated; eauto. intros (cu' & tfd & J & K & L). econstructor; split. left. eapply plus_left. constructor. apply star_one. econstructor; eauto. rewrite <- TY1; eauto. exploit type_of_fundef_preserved; eauto. congruence. traceEq. - constructor; auto. econstructor; eauto. + econstructor. eexact L. eauto. econstructor. eexact LINK. auto. auto. intros. change sl2 with (nil ++ sl2). apply S. - constructor. auto. auto. - (* for value *) + constructor. auto. auto. auto. ++ (* for value *) exploit tr_simple_rvalue; eauto. intros [SL1 [TY1 EV1]]. exploit tr_simple_exprlist; eauto. intros [SL2 EV2]. subst. simpl Kseqlist. - exploit functions_translated; eauto. intros [tfd [J K]]. + exploit functions_translated; eauto. intros (cu' & tfd & J & K & L). econstructor; split. left. eapply plus_left. constructor. apply star_one. econstructor; eauto. rewrite <- TY1; eauto. exploit type_of_fundef_preserved; eauto. congruence. traceEq. - constructor; auto. econstructor; eauto. + econstructor. eexact L. eauto. econstructor. eexact LINK. auto. auto. intros. apply S. destruct dst'; constructor. auto. intros. constructor. rewrite H5; auto. apply PTree.gss. auto. intros. constructor. rewrite H5; auto. apply PTree.gss. intros. apply PTree.gso. intuition congruence. - auto. + auto. auto. -(* builtin *) - exploit tr_top_leftcontext; eauto. clear H9. +- (* builtin *) + exploit tr_top_leftcontext; eauto. clear TR. intros [dst' [sl1 [sl2 [a' [tmp' [P [Q [R S]]]]]]]]. inv P. inv H2. - (* for effects *) ++ (* for effects *) exploit tr_simple_exprlist; eauto. intros [SL EV]. subst. simpl Kseqlist. econstructor; split. @@ -1950,7 +2066,7 @@ Proof. traceEq. econstructor; eauto. change sl2 with (nil ++ sl2). apply S. constructor. simpl; auto. auto. - (* for value *) ++ (* for value *) exploit tr_simple_exprlist; eauto. intros [SL EV]. subst. simpl Kseqlist. econstructor; split. @@ -1968,8 +2084,8 @@ Qed. (** Forward simulation for statements. *) Lemma tr_top_val_for_val_inv: - forall e le m v ty sl a tmps, - tr_top tge e le m For_val (Csyntax.Eval v ty) sl a tmps -> + forall ce e le m v ty sl a tmps, + tr_top ce tge e le m For_val (Csyntax.Eval v ty) sl a tmps -> sl = nil /\ typeof a = ty /\ eval_expr tge e le m a v. Proof. intros. inv H. auto. inv H0. auto. @@ -2011,264 +2127,263 @@ Lemma sstep_simulation: /\ match_states S2 S2'. Proof. induction 1; intros; inv MS. -(* do 1 *) - inv H6. inv H0. +- (* do 1 *) + inv TR. inv H0. econstructor; split. right; split. apply push_seq. - simpl. omega. + simpl. lia. econstructor; eauto. constructor. auto. -(* do 2 *) - inv H7. inv H6. inv H. +- (* do 2 *) + inv MK. inv TR. inv H. econstructor; split. - right; split. apply star_refl. simpl. omega. + right; split. apply star_refl. simpl. lia. econstructor; eauto. constructor. -(* seq *) - inv H6. econstructor; split. left. apply plus_one. constructor. +- (* seq *) + inv TR. econstructor; split. left. apply plus_one. constructor. econstructor; eauto. constructor; auto. -(* skip seq *) - inv H6; inv H7. econstructor; split. +- (* skip seq *) + inv TR; inv MK. econstructor; split. left. apply plus_one; constructor. econstructor; eauto. -(* continue seq *) - inv H6; inv H7. econstructor; split. +- (* continue seq *) + inv TR; inv MK. econstructor; split. left. apply plus_one; constructor. econstructor; eauto. constructor. -(* break seq *) - inv H6; inv H7. econstructor; split. +- (* break seq *) + inv TR; inv MK. econstructor; split. left. apply plus_one; constructor. econstructor; eauto. constructor. -(* ifthenelse *) - inv H6. -(* ifthenelse empty *) +- (* ifthenelse *) + inv TR. ++ (* ifthenelse empty *) inv H3. econstructor; split. left. eapply plus_left. constructor. apply push_seq. econstructor; eauto. econstructor; eauto. econstructor; eauto. -(* ifthenelse non empty *) ++ (* ifthenelse non empty *) inv H2. econstructor; split. left. eapply plus_left. constructor. apply push_seq. traceEq. econstructor; eauto. econstructor; eauto. -(* ifthenelse *) - inv H8. -(* ifthenelse empty *) +- (* ifthenelse *) + inv MK. ++ (* ifthenelse empty *) exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. econstructor; split; simpl. right. destruct b; econstructor; eauto. eapply star_left. apply step_skip_seq. econstructor. traceEq. eapply star_left. apply step_skip_seq. econstructor. traceEq. destruct b; econstructor; eauto. econstructor; eauto. econstructor; eauto. - (* ifthenelse non empty *) ++ (* ifthenelse non empty *) exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. econstructor; split. left. eapply plus_two. constructor. apply step_ifthenelse with (v1 := v) (b := b); auto. traceEq. destruct b; econstructor; eauto. -(* while *) - inv H6. inv H1. econstructor; split. +- (* while *) + inv TR. inv H1. econstructor; split. left. eapply plus_left. constructor. eapply star_left. constructor. apply push_seq. reflexivity. traceEq. rewrite Kseqlist_app. - econstructor; eauto. simpl. econstructor; eauto. econstructor; eauto. -(* while false *) - inv H8. + econstructor; eauto. simpl. econstructor; eauto. econstructor; eauto. +- (* while false *) + inv MK. exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. econstructor; split. left. simpl. eapply plus_left. constructor. eapply star_trans. apply step_makeif with (v1 := v) (b := false); auto. eapply star_two. constructor. apply step_break_loop1. reflexivity. reflexivity. traceEq. - constructor; auto. constructor. -(* while true *) - inv H8. + econstructor; eauto. constructor. +- (* while true *) + inv MK. exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. econstructor; split. left. simpl. eapply plus_left. constructor. eapply star_right. apply step_makeif with (v1 := v) (b := true); auto. constructor. reflexivity. traceEq. - constructor; auto. constructor; auto. -(* skip-or-continue while *) - assert (ts = Sskip \/ ts = Scontinue). destruct H; subst s0; inv H7; auto. - inv H8. + econstructor; eauto. constructor; auto. +- (* skip-or-continue while *) + assert (ts = Sskip \/ ts = Scontinue). { destruct H; subst s0; inv TR; auto. } + inv MK. econstructor; split. left. eapply plus_two. apply step_skip_or_continue_loop1; auto. apply step_skip_loop2. traceEq. - constructor; auto. constructor; auto. -(* break while *) - inv H6. inv H7. + econstructor; eauto. constructor; auto. +- (* break while *) + inv TR. inv MK. econstructor; split. left. apply plus_one. apply step_break_loop1. - constructor; auto. constructor. + econstructor; eauto. constructor. -(* dowhile *) - inv H6. +- (* dowhile *) + inv TR. econstructor; split. left. apply plus_one. apply step_loop. - constructor; auto. constructor; auto. -(* skip_or_continue dowhile *) - assert (ts = Sskip \/ ts = Scontinue). destruct H; subst s0; inv H7; auto. - inv H8. inv H4. + econstructor; eauto. constructor; auto. +- (* skip_or_continue dowhile *) + assert (ts = Sskip \/ ts = Scontinue). { destruct H; subst s0; inv TR; auto. } + inv MK. inv H5. econstructor; split. left. eapply plus_left. apply step_skip_or_continue_loop1. auto. apply push_seq. traceEq. rewrite Kseqlist_app. econstructor; eauto. simpl. econstructor; auto. econstructor; eauto. -(* dowhile false *) - inv H8. +- (* dowhile false *) + inv MK. exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. econstructor; split. left. simpl. eapply plus_left. constructor. eapply star_right. apply step_makeif with (v1 := v) (b := false); auto. constructor. reflexivity. traceEq. - constructor; auto. constructor. -(* dowhile true *) - inv H8. + econstructor; eauto. constructor. +- (* dowhile true *) + inv MK. exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. econstructor; split. left. simpl. eapply plus_left. constructor. eapply star_right. apply step_makeif with (v1 := v) (b := true); auto. constructor. reflexivity. traceEq. - constructor; auto. constructor; auto. -(* break dowhile *) - inv H6. inv H7. + econstructor; eauto. constructor; auto. +- (* break dowhile *) + inv TR. inv MK. econstructor; split. left. apply plus_one. apply step_break_loop1. - constructor; auto. constructor. + econstructor; eauto. constructor. -(* for start *) - inv H7. congruence. +- (* for start *) + inv TR. congruence. econstructor; split. left; apply plus_one. constructor. econstructor; eauto. constructor; auto. econstructor; eauto. -(* for *) - inv H6; try congruence. inv H2. +- (* for *) + inv TR; try congruence. inv H2. econstructor; split. left. eapply plus_left. apply step_loop. eapply star_left. constructor. apply push_seq. reflexivity. traceEq. rewrite Kseqlist_app. econstructor; eauto. simpl. constructor; auto. econstructor; eauto. -(* for false *) - inv H8. exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. +- (* for false *) + inv MK. exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. econstructor; split. left. simpl. eapply plus_left. constructor. eapply star_trans. apply step_makeif with (v1 := v) (b := false); auto. eapply star_two. constructor. apply step_break_loop1. reflexivity. reflexivity. traceEq. - constructor; auto. constructor. -(* for true *) - inv H8. exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. + econstructor; eauto. constructor. +- (* for true *) + inv MK. exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. econstructor; split. left. simpl. eapply plus_left. constructor. eapply star_right. apply step_makeif with (v1 := v) (b := true); auto. constructor. reflexivity. traceEq. - constructor; auto. constructor; auto. -(* skip_or_continue for3 *) - assert (ts = Sskip \/ ts = Scontinue). destruct H; subst x; inv H7; auto. - inv H8. + econstructor; eauto. constructor; auto. +- (* skip_or_continue for3 *) + assert (ts = Sskip \/ ts = Scontinue). { destruct H; subst x; inv TR; auto. } + inv MK. econstructor; split. left. apply plus_one. apply step_skip_or_continue_loop1. auto. econstructor; eauto. econstructor; auto. -(* break for3 *) - inv H6. inv H7. +- (* break for3 *) + inv TR. inv MK. econstructor; split. left. apply plus_one. apply step_break_loop1. econstructor; eauto. constructor. -(* skip for4 *) - inv H6. inv H7. +- (* skip for4 *) + inv TR. inv MK. econstructor; split. left. apply plus_one. constructor. econstructor; eauto. constructor; auto. - -(* return none *) - inv H7. econstructor; split. +- (* return none *) + inv TR. econstructor; split. left. apply plus_one. econstructor; eauto. rewrite blocks_of_env_preserved; eauto. - constructor. apply match_cont_call; auto. -(* return some 1 *) - inv H6. inv H0. econstructor; split. + econstructor. intros; eapply match_cont_call_cont; eauto. +- (* return some 1 *) + inv TR. inv H0. econstructor; split. left; eapply plus_left. constructor. apply push_seq. traceEq. econstructor; eauto. constructor. auto. -(* return some 2 *) - inv H9. exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. +- (* return some 2 *) + inv MK. exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. econstructor; split. left. eapply plus_two. constructor. econstructor. eauto. erewrite function_return_preserved; eauto. rewrite blocks_of_env_preserved; eauto. eauto. traceEq. - constructor. apply match_cont_call; auto. -(* skip return *) - inv H8. - assert (is_call_cont tk). inv H9; simpl in *; auto. + econstructor. intros; eapply match_cont_call_cont; eauto. +- (* skip return *) + inv TR. + assert (is_call_cont tk). { inv MK; simpl in *; auto. } econstructor; split. left. apply plus_one. apply step_skip_call; eauto. rewrite blocks_of_env_preserved; eauto. - constructor. auto. + econstructor. intros; eapply match_cont_is_call_cont; eauto. -(* switch *) - inv H6. inv H1. +- (* switch *) + inv TR. inv H1. econstructor; split. left; eapply plus_left. constructor. apply push_seq. traceEq. econstructor; eauto. constructor; auto. -(* expr switch *) - inv H8. exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. +- (* expr switch *) + inv MK. exploit tr_top_val_for_val_inv; eauto. intros [A [B C]]. subst. econstructor; split. left; eapply plus_two. constructor. econstructor; eauto. traceEq. econstructor; eauto. apply tr_seq_of_labeled_statement. apply tr_select_switch. auto. constructor; auto. -(* skip-or-break switch *) - assert (ts = Sskip \/ ts = Sbreak). destruct H; subst x; inv H7; auto. - inv H8. +- (* skip-or-break switch *) + assert (ts = Sskip \/ ts = Sbreak). { destruct H; subst x; inv TR; auto. } + inv MK. econstructor; split. left; apply plus_one. apply step_skip_break_switch. auto. - constructor; auto. constructor. + econstructor; eauto. constructor. -(* continue switch *) - inv H6. inv H7. +- (* continue switch *) + inv TR. inv MK. econstructor; split. left; apply plus_one. apply step_continue_switch. - constructor; auto. constructor. + econstructor; eauto. constructor. -(* label *) - inv H6. econstructor; split. +- (* label *) + inv TR. econstructor; split. left; apply plus_one. constructor. - constructor; auto. + econstructor; eauto. -(* goto *) - inv H7. - inversion H6; subst. - exploit tr_find_label. eauto. apply match_cont_call. eauto. +- (* goto *) + inv TR. + inversion TRF; subst. + exploit tr_find_label. eauto. eapply match_cont_call_cont; eauto. instantiate (1 := lbl). rewrite H. intros [ts' [tk' [P [Q R]]]]. econstructor; split. left. apply plus_one. econstructor; eauto. econstructor; eauto. -(* internal function *) - inv H7. inversion H3; subst. +- (* internal function *) + inv TR. inversion H3; subst. econstructor; split. left; apply plus_one. eapply step_internal_function. econstructor. rewrite H6; rewrite H7; auto. rewrite H6; rewrite H7. eapply alloc_variables_preserved; eauto. rewrite H6. eapply bind_parameters_preserved; eauto. eauto. - constructor; auto. + econstructor; eauto. -(* external function *) - inv H5. +- (* external function *) + inv TR. econstructor; split. left; apply plus_one. econstructor; eauto. eapply external_call_symbols_preserved; eauto. apply senv_preserved. - constructor; auto. + econstructor; eauto. -(* return *) - inv H3. +- (* return *) + specialize (MK (PTree.empty _)). inv MK. econstructor; split. left; apply plus_one. constructor. econstructor; eauto. @@ -2295,7 +2410,7 @@ Lemma transl_initial_states: exists S', Clight.initial_state tprog S' /\ match_states S S'. Proof. intros. inv H. - exploit function_ptr_translated; eauto. intros [tf [FIND TR]]. + exploit function_ptr_translated; eauto. intros (cu & tf & FIND & TR & L). econstructor; split. econstructor. eapply (Genv.init_mem_match (proj1 TRANSL)); eauto. @@ -2303,15 +2418,15 @@ Proof. rewrite symbols_preserved. eauto. destruct TRANSL. destruct H as (A & B & C). simpl in B. auto. eexact FIND. - rewrite <- H3. apply type_of_fundef_preserved. auto. - constructor. auto. constructor. + rewrite <- H3. eapply type_of_fundef_preserved; eauto. + econstructor; eauto. intros; constructor. Qed. Lemma transl_final_states: forall S S' r, match_states S S' -> Csem.final_state S r -> Clight.final_state S' r. Proof. - intros. inv H0. inv H. inv H4. constructor. + intros. inv H0. inv H. specialize (MK (PTree.empty _)). inv MK. constructor. Qed. Theorem transl_program_correct: @@ -2331,13 +2446,13 @@ End PRESERVATION. Instance TransfSimplExprLink : TransfLink match_prog. Proof. - red; intros. eapply Ctypes.link_match_program; eauto. + red; intros. eapply Ctypes.link_match_program_gen; eauto. - intros. Local Transparent Linker_fundef. simpl in *; unfold link_fundef in *. inv H3; inv H4; try discriminate. - destruct ef; inv H2. exists (Internal tf); split; auto. constructor; auto. - destruct ef; inv H2. exists (Internal tf); split; auto. constructor; auto. + destruct ef; inv H2. exists (Internal tf); split; auto. left; constructor; auto. + destruct ef; inv H2. exists (Internal tf); split; auto. right; constructor; auto. destruct (external_function_eq ef ef0 && typelist_eq targs targs0 && type_eq tres tres0 && calling_convention_eq cconv cconv0); inv H2. - exists (External ef targs tres cconv); split; auto. constructor. + exists (External ef targs tres cconv); split; auto. left; constructor. Qed. |