diff options
author | xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e> | 2010-03-07 15:52:58 +0000 |
---|---|---|
committer | xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e> | 2010-03-07 15:52:58 +0000 |
commit | a74f6b45d72834b5b8417297017bd81424123d98 (patch) | |
tree | d291cf3f05397658f0fe9d8ecce9b8785a50d270 /backend/Machabstr2concr.v | |
parent | 54cba6d4cae1538887f296a62be1c99378fe0916 (diff) | |
download | compcert-a74f6b45d72834b5b8417297017bd81424123d98.tar.gz compcert-a74f6b45d72834b5b8417297017bd81424123d98.zip |
Merge of the newmem and newextcalls branches:
- Revised memory model with concrete representation of ints & floats,
and per-byte access permissions
- Revised Globalenvs implementation
- Matching changes in all languages and proofs.
git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@1282 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e
Diffstat (limited to 'backend/Machabstr2concr.v')
-rw-r--r-- | backend/Machabstr2concr.v | 669 |
1 files changed, 434 insertions, 235 deletions
diff --git a/backend/Machabstr2concr.v b/backend/Machabstr2concr.v index 89529fd4..7714f3d5 100644 --- a/backend/Machabstr2concr.v +++ b/backend/Machabstr2concr.v @@ -17,7 +17,7 @@ Require Import Maps. Require Import AST. Require Import Integers. Require Import Values. -Require Import Mem. +Require Import Memory. Require Import Events. Require Import Globalenvs. Require Import Smallstep. @@ -74,19 +74,27 @@ Hypothesis wt_f: wt_function f. semantics. [ms] is the current memory state in the concrete semantics. The stack pointer is [Vptr sp base] in both semantics. *) -Inductive frame_match (fr: frame) - (sp: block) (base: int) - (mm ms: mem) : Prop := - frame_match_intro: - valid_block ms sp -> - low_bound mm sp = 0 -> - low_bound ms sp = -f.(fn_framesize) -> - high_bound ms sp >= 0 -> - base = Int.repr (-f.(fn_framesize)) -> - (forall ty ofs, - -f.(fn_framesize) <= ofs -> ofs + AST.typesize ty <= 0 -> (4 | ofs) -> - load (chunk_of_type ty) ms sp ofs = Some(fr ty ofs)) -> - frame_match fr sp base mm ms. +Record frame_match (fr: frame) + (sp: block) (base: int) + (mm ms: mem) : Prop := + mk_frame_match { + fm_valid_1: + Mem.valid_block mm sp; + fm_valid_2: + Mem.valid_block ms sp; + fm_base: + base = Int.repr(- f.(fn_framesize)); + fm_stackdata_pos: + Mem.low_bound mm sp = 0; + fm_write_perm: + Mem.range_perm ms sp (-f.(fn_framesize)) 0 Freeable; + fm_contents_match: + forall ty ofs, + -f.(fn_framesize) <= ofs -> ofs + AST.typesize ty <= 0 -> (4 | ofs) -> + exists v, + Mem.load (chunk_of_type ty) ms sp ofs = Some v + /\ Val.lessdef (fr ty ofs) v + }. (** The following two innocuous-looking lemmas are the key results showing that [sp]-relative memory accesses in the concrete @@ -94,8 +102,8 @@ Inductive frame_match (fr: frame) semantics. First, a value [v] that has type [ty] is preserved when stored in memory with chunk [chunk_of_type ty], then read back with the same chunk. The typing hypothesis is crucial here: - for instance, a float value reads back as [Vundef] when stored - and load with chunk [Mint32]. *) + for instance, a float value is not preserved when stored + and loaded with chunk [Mint32]. *) Lemma load_result_ty: forall v ty, @@ -127,14 +135,15 @@ Lemma frame_match_load_stack: frame_match fr sp base mm ms -> 0 <= Int.signed ofs /\ Int.signed ofs + AST.typesize ty <= f.(fn_framesize) -> (4 | Int.signed ofs) -> - load_stack ms (Vptr sp base) ty ofs = - Some (fr ty (Int.signed ofs - f.(fn_framesize))). + exists v, + load_stack ms (Vptr sp base) ty ofs = Some v + /\ Val.lessdef (fr ty (Int.signed ofs - f.(fn_framesize))) v. Proof. intros. inv H. inv wt_f. - unfold load_stack, Val.add, loadv. + unfold load_stack, Val.add, Mem.loadv. replace (Int.signed (Int.add (Int.repr (- fn_framesize f)) ofs)) with (Int.signed ofs - fn_framesize f). - apply H7. omega. omega. + apply fm_contents_match0. omega. omega. apply Zdivide_minus_l; auto. assert (Int.signed (Int.repr (-fn_framesize f)) = -fn_framesize f). apply Int.signed_repr. @@ -149,9 +158,9 @@ Lemma frame_match_get_slot: forall fr sp base mm ms ty ofs v, frame_match fr sp base mm ms -> get_slot f fr ty (Int.signed ofs) v -> - load_stack ms (Vptr sp base) ty ofs = Some v. + exists v', load_stack ms (Vptr sp base) ty ofs = Some v' /\ Val.lessdef v v'. Proof. - intros. inversion H. inv H0. inv H7. eapply frame_match_load_stack; eauto. + intros. inv H0. inv H1. eapply frame_match_load_stack; eauto. Qed. (** Assigning a value to a frame slot (in the abstract semantics) @@ -160,19 +169,20 @@ Qed. and activation records is preserved. *) Lemma frame_match_store_stack: - forall fr sp base mm ms ty ofs v, + forall fr sp base mm ms ty ofs v v', frame_match fr sp base mm ms -> - 0 <= Int.signed ofs /\ Int.signed ofs + AST.typesize ty <= f.(fn_framesize) -> + 0 <= Int.signed ofs -> Int.signed ofs + AST.typesize ty <= f.(fn_framesize) -> (4 | Int.signed ofs) -> Val.has_type v ty -> + Val.lessdef v v' -> Mem.extends mm ms -> exists ms', - store_stack ms (Vptr sp base) ty ofs v = Some ms' /\ + store_stack ms (Vptr sp base) ty ofs v' = Some ms' /\ frame_match (update ty (Int.signed ofs - f.(fn_framesize)) v fr) sp base mm ms' /\ Mem.extends mm ms'. Proof. intros. inv H. inv wt_f. - unfold store_stack, Val.add, storev. + unfold store_stack, Val.add, Mem.storev. assert (Int.signed (Int.add (Int.repr (- fn_framesize f)) ofs) = Int.signed ofs - fn_framesize f). assert (Int.signed (Int.repr (-fn_framesize f)) = -fn_framesize f). @@ -183,58 +193,84 @@ Proof. apply Zle_trans with 0. generalize (AST.typesize_pos ty). omega. compute; congruence. rewrite H. - assert (exists ms', store (chunk_of_type ty) ms sp (Int.signed ofs - fn_framesize f) v = Some ms'). - apply valid_access_store. - constructor. auto. omega. - rewrite size_type_chunk. omega. + assert ({ ms' | Mem.store (chunk_of_type ty) ms sp (Int.signed ofs - fn_framesize f) v' = Some ms'}). + apply Mem.valid_access_store. constructor. + apply Mem.range_perm_implies with Freeable; auto with mem. + red; intros; apply fm_write_perm0. + rewrite <- size_type_chunk in H1. + generalize (size_chunk_pos (chunk_of_type ty)). + omega. replace (align_chunk (chunk_of_type ty)) with 4. apply Zdivide_minus_l; auto. destruct ty; auto. - destruct H8 as [ms' STORE]. - generalize (low_bound_store _ _ _ _ _ _ STORE sp). intro LB. - generalize (high_bound_store _ _ _ _ _ _ STORE sp). intro HB. + destruct X as [ms' STORE]. exists ms'. split. exact STORE. (* frame match *) - split. constructor; try congruence. - eauto with mem. intros. unfold update. - destruct (zeq (Int.signed ofs - fn_framesize f) ofs0). subst ofs0. + split. constructor. + (* valid *) + eauto with mem. + eauto with mem. + (* base *) + auto. + (* stackdata_pos *) + auto. + (* write_perm *) + red; intros; eauto with mem. + (* contents *) + intros. + exploit fm_contents_match0; eauto. intros [v0 [LOAD0 VLD0]]. + assert (exists v1, Mem.load (chunk_of_type ty0) ms' sp ofs0 = Some v1). + apply Mem.valid_access_load; eauto with mem. + destruct H9 as [v1 LOAD1]. + exists v1; split; auto. + unfold update. + destruct (zeq (Int.signed ofs - fn_framesize f) ofs0). subst ofs0. destruct (typ_eq ty ty0). subst ty0. (* same *) - transitivity (Some (Val.load_result (chunk_of_type ty) v)). - eapply load_store_same; eauto. - decEq. apply load_result_ty; auto. + inv H4. + assert (Some v1 = Some (Val.load_result (chunk_of_type ty) v')). + rewrite <- LOAD1. eapply Mem.load_store_same; eauto. + replace (type_of_chunk (chunk_of_type ty)) with ty. auto. + destruct ty; auto. + inv H4. rewrite load_result_ty; auto. + auto. (* mismatch *) - eapply load_store_mismatch'; eauto with mem. - destruct ty; destruct ty0; simpl; congruence. + auto. destruct (zle (ofs0 + AST.typesize ty0) (Int.signed ofs - fn_framesize f)). (* disjoint *) - rewrite <- H9; auto. eapply load_store_other; eauto. - right; left. rewrite size_type_chunk; auto. + assert (Some v1 = Some v0). + rewrite <- LOAD0; rewrite <- LOAD1. + eapply Mem.load_store_other; eauto. + right; left. rewrite size_type_chunk; auto. + inv H9. auto. destruct (zle (Int.signed ofs - fn_framesize f + AST.typesize ty)). - rewrite <- H9; auto. eapply load_store_other; eauto. - right; right. rewrite size_type_chunk; auto. + assert (Some v1 = Some v0). + rewrite <- LOAD0; rewrite <- LOAD1. + eapply Mem.load_store_other; eauto. + right; right. rewrite size_type_chunk; auto. + inv H9. auto. (* overlap *) - eapply load_store_overlap'; eauto with mem. - rewrite size_type_chunk; auto. - rewrite size_type_chunk; auto. + auto. (* extends *) - eapply store_outside_extends; eauto. - left. rewrite size_type_chunk. omega. + eapply Mem.store_outside_extends; eauto. + left. rewrite fm_stackdata_pos0. + rewrite size_type_chunk. omega. Qed. Lemma frame_match_set_slot: - forall fr sp base mm ms ty ofs v fr', + forall fr sp base mm ms ty ofs v fr' v', frame_match fr sp base mm ms -> set_slot f fr ty (Int.signed ofs) v fr' -> Val.has_type v ty -> + Val.lessdef v v' -> Mem.extends mm ms -> exists ms', - store_stack ms (Vptr sp base) ty ofs v = Some ms' /\ + store_stack ms (Vptr sp base) ty ofs v' = Some ms' /\ frame_match fr' sp base mm ms' /\ Mem.extends mm ms'. Proof. - intros. inv H0. inv H3. eapply frame_match_store_stack; eauto. + intros. inv H0. inv H4. eapply frame_match_store_stack; eauto. Qed. (** Agreement is preserved by stores within blocks other than the @@ -243,45 +279,40 @@ Qed. Lemma frame_match_store_other: forall fr sp base mm ms chunk b ofs v ms', frame_match fr sp base mm ms -> - store chunk ms b ofs v = Some ms' -> + Mem.store chunk ms b ofs v = Some ms' -> sp <> b -> frame_match fr sp base mm ms'. Proof. - intros. inv H. - generalize (low_bound_store _ _ _ _ _ _ H0 sp). intro LB. - generalize (high_bound_store _ _ _ _ _ _ H0 sp). intro HB. - apply frame_match_intro; auto. - eauto with mem. - congruence. - congruence. - intros. rewrite <- H7; auto. - eapply load_store_other; eauto. + intros. inv H. constructor; auto. + eauto with mem. + red; intros; eauto with mem. + intros. exploit fm_contents_match0; eauto. intros [v0 [LOAD LD]]. + exists v0; split; auto. rewrite <- LOAD. eapply Mem.load_store_other; eauto. Qed. (** Agreement is preserved by parallel stores in the Machabstr and the Machconcr semantics. *) Lemma frame_match_store: - forall fr sp base mm ms chunk b ofs v mm' ms', + forall fr sp base mm ms chunk b ofs v mm' v' ms', frame_match fr sp base mm ms -> - store chunk mm b ofs v = Some mm' -> - store chunk ms b ofs v = Some ms' -> + Mem.store chunk mm b ofs v = Some mm' -> + Mem.store chunk ms b ofs v' = Some ms' -> frame_match fr sp base mm' ms'. Proof. - intros. inv H. - generalize (low_bound_store _ _ _ _ _ _ H0 sp). intro LBm. - generalize (low_bound_store _ _ _ _ _ _ H1 sp). intro LBs. - generalize (high_bound_store _ _ _ _ _ _ H0 sp). intro HBm. - generalize (high_bound_store _ _ _ _ _ _ H1 sp). intro HBs. - apply frame_match_intro; auto. + intros. inv H. constructor; auto. eauto with mem. - congruence. congruence. congruence. - intros. rewrite <- H7; auto. eapply load_store_other; eauto. - destruct (zeq sp b). subst b. right. + eauto with mem. + rewrite (Mem.bounds_store _ _ _ _ _ _ H0). auto. + red; intros; eauto with mem. + intros. exploit fm_contents_match0; eauto. intros [v0 [LOAD LD]]. + exists v0; split; auto. rewrite <- LOAD. eapply Mem.load_store_other; eauto. + destruct (zeq sp b); auto. subst b. right. rewrite size_type_chunk. - assert (valid_access mm chunk sp ofs) by eauto with mem. - inv H9. left. omega. - auto. + assert (Mem.valid_access mm chunk sp ofs Nonempty) by eauto with mem. + exploit Mem.store_valid_access_3. eexact H0. intro. + exploit Mem.valid_access_in_bounds. eauto. rewrite fm_stackdata_pos0. + omega. Qed. (** Memory allocation of the Cminor stack data block (in the abstract @@ -291,68 +322,111 @@ Qed. remain true. *) Lemma frame_match_new: - forall mm ms mm' ms' sp sp', - mm.(nextblock) = ms.(nextblock) -> - alloc mm 0 f.(fn_stacksize) = (mm', sp) -> - alloc ms (- f.(fn_framesize)) f.(fn_stacksize) = (ms', sp') -> - sp = sp' /\ + forall mm ms mm' ms' sp, + Mem.alloc mm 0 f.(fn_stacksize) = (mm', sp) -> + Mem.alloc ms (- f.(fn_framesize)) f.(fn_stacksize) = (ms', sp) -> frame_match empty_frame sp (Int.repr (-f.(fn_framesize))) mm' ms'. Proof. intros. - assert (sp = sp'). - exploit alloc_result. eexact H0. exploit alloc_result. eexact H1. - congruence. - subst sp'. split. auto. - generalize (low_bound_alloc_same _ _ _ _ _ H0). intro LBm. - generalize (low_bound_alloc_same _ _ _ _ _ H1). intro LBs. - generalize (high_bound_alloc_same _ _ _ _ _ H0). intro HBm. - generalize (high_bound_alloc_same _ _ _ _ _ H1). intro HBs. inv wt_f. constructor; simpl; eauto with mem. - rewrite HBs. auto. - intros. - eapply load_alloc_same'; eauto. + rewrite (Mem.bounds_alloc_same _ _ _ _ _ H). auto. + red; intros. eapply Mem.perm_alloc_2; eauto. omega. + intros. exists Vundef; split. + eapply Mem.load_alloc_same'; eauto. rewrite size_type_chunk. omega. - replace (align_chunk (chunk_of_type ty)) with 4; auto. destruct ty; auto. + replace (align_chunk (chunk_of_type ty)) with 4; auto. + destruct ty; auto. + unfold empty_frame. auto. Qed. Lemma frame_match_alloc: - forall mm ms fr sp base lom him los his mm' ms' bm bs, - mm.(nextblock) = ms.(nextblock) -> + forall mm ms fr sp base lom him los his mm' ms' b, frame_match fr sp base mm ms -> - alloc mm lom him = (mm', bm) -> - alloc ms los his = (ms', bs) -> + Mem.alloc mm lom him = (mm', b) -> + Mem.alloc ms los his = (ms', b) -> frame_match fr sp base mm' ms'. Proof. - intros. inversion H0. - assert (valid_block mm sp). red. rewrite H. auto. - exploit low_bound_alloc_other. eexact H1. eexact H9. intro LBm. - exploit high_bound_alloc_other. eexact H1. eexact H9. intro HBm. - exploit low_bound_alloc_other. eexact H2. eexact H3. intro LBs. - exploit high_bound_alloc_other. eexact H2. eexact H3. intro HBs. - apply frame_match_intro. - eapply valid_block_alloc; eauto. - congruence. congruence. congruence. auto. auto. - intros. eapply load_alloc_other; eauto. + intros. inversion H. + assert (sp <> b). + apply Mem.valid_not_valid_diff with ms; eauto with mem. + constructor; auto. + eauto with mem. + eauto with mem. + rewrite (Mem.bounds_alloc_other _ _ _ _ _ H0); auto. + red; intros; eauto with mem. + intros. exploit fm_contents_match0; eauto. intros [v [LOAD LD]]. + exists v; split; auto. eapply Mem.load_alloc_other; eauto. Qed. (** [frame_match] relations are preserved by freeing a block other than the one pointed to by [sp]. *) Lemma frame_match_free: - forall fr sp base mm ms b, + forall fr sp base mm ms b lom him los his mm' ms', frame_match fr sp base mm ms -> sp <> b -> - frame_match fr sp base (free mm b) (free ms b). + Mem.free mm b lom him = Some mm' -> + Mem.free ms b los his = Some ms' -> + frame_match fr sp base mm' ms'. +Proof. + intros. inversion H. constructor; auto. + eauto with mem. + eauto with mem. + rewrite (Mem.bounds_free _ _ _ _ _ H1). auto. + red; intros; eauto with mem. + intros. rewrite (Mem.load_free _ _ _ _ _ H2); auto. +Qed. + +Lemma frame_match_delete: + forall fr sp base mm ms mm', + frame_match fr sp base mm ms -> + Mem.free mm sp 0 f.(fn_stacksize) = Some mm' -> + Mem.extends mm ms -> + exists ms', + Mem.free ms sp (-f.(fn_framesize)) f.(fn_stacksize) = Some ms' + /\ Mem.extends mm' ms'. Proof. intros. inversion H. - generalize (low_bound_free mm _ _ H0); intro LBm. - generalize (low_bound_free ms _ _ H0); intro LBs. - generalize (high_bound_free mm _ _ H0); intro HBm. - generalize (high_bound_free ms _ _ H0); intro HBs. - apply frame_match_intro; auto. - congruence. congruence. congruence. - intros. rewrite <- H6; auto. apply load_free. auto. + assert (Mem.range_perm mm sp 0 (fn_stacksize f) Freeable). + eapply Mem.free_range_perm; eauto. + assert ({ ms' | Mem.free ms sp (-f.(fn_framesize)) f.(fn_stacksize) = Some ms' }). + apply Mem.range_perm_free. + red; intros. destruct (zlt ofs 0). + apply fm_write_perm0. omega. + eapply Mem.perm_extends; eauto. apply H2. omega. + destruct X as [ms' FREE]. exists ms'; split; auto. + eapply Mem.free_right_extends; eauto. + eapply Mem.free_left_extends; eauto. + intros; red; intros. + exploit Mem.perm_in_bounds; eauto. + rewrite (Mem.bounds_free _ _ _ _ _ H0). rewrite fm_stackdata_pos0; intro. + exploit Mem.perm_free_2. eexact H0. instantiate (1 := ofs); omega. eauto. + auto. +Qed. + +(** [frame_match] is preserved by external calls. *) + +Lemma frame_match_external_call: + forall fr sp base mm ms mm' ms' ef vargs vres t vargs' vres', + frame_match fr sp base mm ms -> + Mem.extends mm ms -> + external_call ef vargs mm t vres mm' -> + Mem.extends mm' ms' -> + external_call ef vargs' ms t vres' ms' -> + mem_unchanged_on (loc_out_of_bounds mm) ms ms' -> + frame_match fr sp base mm' ms'. +Proof. + intros. destruct H4 as [A B]. inversion H. constructor. + eapply external_call_valid_block; eauto. + eapply external_call_valid_block; eauto. + auto. + rewrite (external_call_bounds _ _ _ _ _ _ _ H1); auto. + red; intros. apply A; auto. red. omega. + intros. exploit fm_contents_match0; eauto. intros [v [C D]]. + exists v; split; auto. + apply B; auto. + rewrite size_type_chunk; intros; red. omega. Qed. End FRAME_MATCH. @@ -430,61 +504,130 @@ Proof. simpl. omega. Qed. +Definition is_pointer_or_int (v: val) : Prop := + match v with + | Vint _ => True + | Vptr _ _ => True + | _ => False + end. + +Remark is_pointer_has_type: + forall v, is_pointer_or_int v -> Val.has_type v Tint. +Proof. + intros; destruct v; elim H; exact I. +Qed. + +Lemma frame_match_load_stack_pointer: + forall fr sp base mm ms ty ofs, + frame_match f fr sp base mm ms -> + 0 <= Int.signed ofs /\ Int.signed ofs + AST.typesize ty <= f.(fn_framesize) -> + (4 | Int.signed ofs) -> + is_pointer_or_int (fr ty (Int.signed ofs - f.(fn_framesize))) -> + load_stack ms (Vptr sp base) ty ofs = Some (fr ty (Int.signed ofs - f.(fn_framesize))). +Proof. + intros. exploit frame_match_load_stack; eauto. + intros [v [LOAD LD]]. + inv LD. auto. rewrite <- H4 in H2. elim H2. +Qed. + Lemma frame_match_load_link: forall fr sp base mm ms, frame_match f (extend_frame fr) sp base mm ms -> - load_stack ms (Vptr sp base) Tint f.(fn_link_ofs) = Some (parent_sp cs). + is_pointer_or_int (parent_sp cs) -> + load_stack ms (Vptr sp base) Tint f.(fn_link_ofs) = Some(parent_sp cs). Proof. intros. inversion wt_f. - replace (parent_sp cs) with - (extend_frame fr Tint (Int.signed f.(fn_link_ofs) - f.(fn_framesize))). - eapply frame_match_load_stack; eauto. - - unfold extend_frame. rewrite update_other. apply update_same. simpl. omega. + assert (parent_sp cs = + extend_frame fr Tint (Int.signed f.(fn_link_ofs) - f.(fn_framesize))). + unfold extend_frame. rewrite update_other. rewrite update_same. auto. + simpl. omega. + rewrite H1; eapply frame_match_load_stack_pointer; eauto. + rewrite <- H1; auto. Qed. Lemma frame_match_load_retaddr: forall fr sp base mm ms, frame_match f (extend_frame fr) sp base mm ms -> - load_stack ms (Vptr sp base) Tint f.(fn_retaddr_ofs) = Some (parent_ra cs). + is_pointer_or_int (parent_ra cs) -> + load_stack ms (Vptr sp base) Tint f.(fn_retaddr_ofs) = Some(parent_ra cs). Proof. intros. inversion wt_f. - replace (parent_ra cs) with - (extend_frame fr Tint (Int.signed f.(fn_retaddr_ofs) - f.(fn_framesize))). - eapply frame_match_load_stack; eauto. - unfold extend_frame. apply update_same. + assert (parent_ra cs = + extend_frame fr Tint (Int.signed f.(fn_retaddr_ofs) - f.(fn_framesize))). + unfold extend_frame. rewrite update_same. auto. + rewrite H1; eapply frame_match_load_stack_pointer; eauto. + rewrite <- H1; auto. Qed. Lemma frame_match_function_entry: - forall mm ms mm' ms1 sp sp', - extends mm ms -> - alloc mm 0 f.(fn_stacksize) = (mm', sp) -> - alloc ms (- f.(fn_framesize)) f.(fn_stacksize) = (ms1, sp') -> - Val.has_type (parent_sp cs) Tint -> - Val.has_type (parent_ra cs) Tint -> + forall mm ms mm' sp, + Mem.extends mm ms -> + Mem.alloc mm 0 f.(fn_stacksize) = (mm', sp) -> + is_pointer_or_int (parent_sp cs) -> + is_pointer_or_int (parent_ra cs) -> let base := Int.repr (-f.(fn_framesize)) in - exists ms2, exists ms3, - sp = sp' /\ + exists ms1, exists ms2, exists ms3, + Mem.alloc ms (- f.(fn_framesize)) f.(fn_stacksize) = (ms1, sp) /\ store_stack ms1 (Vptr sp base) Tint f.(fn_link_ofs) (parent_sp cs) = Some ms2 /\ store_stack ms2 (Vptr sp base) Tint f.(fn_retaddr_ofs) (parent_ra cs) = Some ms3 /\ frame_match f (extend_frame empty_frame) sp base mm' ms3 /\ - extends mm' ms3. + Mem.extends mm' ms3. Proof. intros. inversion wt_f. - exploit alloc_extends; eauto. omega. omega. intros [A EXT0]. - exploit frame_match_new. eauto. inv H. eexact H4. eauto. eauto. eauto. - fold base. intros [C FM0]. - destruct (frame_match_store_stack _ wt_f _ _ _ _ _ Tint _ _ - FM0 wt_function_link wt_function_link_aligned H2 EXT0) - as [ms2 [STORE1 [FM1 EXT1]]]. - destruct (frame_match_store_stack _ wt_f _ _ _ _ _ Tint _ _ - FM1 wt_function_retaddr wt_function_retaddr_aligned H3 EXT1) - as [ms3 [STORE2 [FM3 EXT3]]]. - exists ms2; exists ms3; auto. + exploit Mem.alloc_extends; eauto. + instantiate (1 := -f.(fn_framesize)). omega. + instantiate (1 := f.(fn_stacksize)). omega. + intros [ms1 [A EXT0]]. + exploit frame_match_new; eauto. fold base. intros FM0. + exploit frame_match_store_stack. eauto. eexact FM0. + instantiate (1 := fn_link_ofs f); omega. + instantiate (1 := Tint). simpl; omega. + auto. apply is_pointer_has_type. eexact H1. constructor. auto. + intros [ms2 [STORE1 [FM1 EXT1]]]. + exploit frame_match_store_stack. eauto. eexact FM1. + instantiate (1 := fn_retaddr_ofs f); omega. + instantiate (1 := Tint). simpl; omega. + auto. apply is_pointer_has_type. eexact H2. constructor. auto. + intros [ms3 [STORE2 [FM2 EXT2]]]. + exists ms1; exists ms2; exists ms3; auto. Qed. End EXTEND_FRAME. +(** ** The ``less defined than'' relation between register states. *) + +Definition regset_lessdef (rs1 rs2: regset) : Prop := + forall r, Val.lessdef (rs1 r) (rs2 r). + +Lemma regset_lessdef_list: + forall rs1 rs2, regset_lessdef rs1 rs2 -> + forall rl, Val.lessdef_list (rs1##rl) (rs2##rl). +Proof. + induction rl; simpl. + constructor. + constructor; auto. +Qed. + +Lemma regset_lessdef_set: + forall rs1 rs2 r v1 v2, + regset_lessdef rs1 rs2 -> Val.lessdef v1 v2 -> + regset_lessdef (rs1#r <- v1) (rs2#r <- v2). +Proof. + intros; red; intros. unfold Regmap.set. + destruct (RegEq.eq r0 r); auto. +Qed. + +Lemma regset_lessdef_find_function_ptr: + forall ge ros rs1 rs2 fb, + find_function_ptr ge ros rs1 = Some fb -> + regset_lessdef rs1 rs2 -> + find_function_ptr ge ros rs2 = Some fb. +Proof. + unfold find_function_ptr; intros; destruct ros; simpl in *. + generalize (H0 m); intro LD; inv LD. auto. rewrite <- H2 in H. congruence. + auto. +Qed. + (** ** Invariant for stacks *) Section SIMULATION. @@ -518,12 +661,26 @@ Inductive match_stacks: wt_function f -> frame_match f (extend_frame f ts fr) sp base mm ms -> stack_below ts sp -> - Val.has_type ra Tint -> + is_pointer_or_int ra -> match_stacks s ts mm ms -> match_stacks (Machabstr.Stackframe f (Vptr sp base) c fr :: s) (Machconcr.Stackframe fb (Vptr sp base) ra c :: ts) mm ms. +Lemma match_stacks_parent_sp_pointer: + forall s ts mm ms, + match_stacks s ts mm ms -> is_pointer_or_int (Machconcr.parent_sp ts). +Proof. + induction 1; simpl; auto. +Qed. + +Lemma match_stacks_parent_ra_pointer: + forall s ts mm ms, + match_stacks s ts mm ms -> is_pointer_or_int (Machconcr.parent_ra ts). +Proof. + induction 1; simpl; auto. +Qed. + (** If [match_stacks] holds, a lookup in the parent frame in the Machabstr semantics corresponds to two memory loads in the Machconcr semantics, one to load the pointer to the parent's @@ -533,7 +690,9 @@ Lemma match_stacks_get_parent: forall s ts mm ms ty ofs v, match_stacks s ts mm ms -> get_slot (parent_function s) (parent_frame s) ty (Int.signed ofs) v -> - load_stack ms (Machconcr.parent_sp ts) ty ofs = Some v. + exists v', + load_stack ms (Machconcr.parent_sp ts) ty ofs = Some v' + /\ Val.lessdef v v'. Proof. intros. inv H; simpl in H0. inv H0. inv H. simpl in H1. elimtype False. generalize (AST.typesize_pos ty). omega. @@ -542,7 +701,7 @@ Proof. Qed. (** Preservation of the [match_stacks] invariant - by various kinds of memory stores. *) + by various kinds of memory operations. *) Remark stack_below_trans: forall ts b b', @@ -556,7 +715,7 @@ Lemma match_stacks_store_other: forall s ts ms mm, match_stacks s ts mm ms -> forall chunk b ofs v ms', - store chunk ms b ofs v = Some ms' -> + Mem.store chunk ms b ofs v = Some ms' -> stack_below ts b -> match_stacks s ts mm ms'. Proof. @@ -593,9 +752,9 @@ Qed. Lemma match_stacks_store: forall s ts ms mm, match_stacks s ts mm ms -> - forall chunk b ofs v mm' ms', - store chunk mm b ofs v = Some mm' -> - store chunk ms b ofs v = Some ms' -> + forall chunk b ofs v mm' v' ms', + Mem.store chunk mm b ofs v = Some mm' -> + Mem.store chunk ms b ofs v' = Some ms' -> match_stacks s ts mm' ms'. Proof. induction 1; intros. @@ -607,28 +766,28 @@ Qed. Lemma match_stacks_alloc: forall s ts ms mm, match_stacks s ts mm ms -> - forall lom him mm' bm los his ms' bs, - mm.(nextblock) = ms.(nextblock) -> - alloc mm lom him = (mm', bm) -> - alloc ms los his = (ms', bs) -> + forall lom him mm' b los his ms', + Mem.alloc mm lom him = (mm', b) -> + Mem.alloc ms los his = (ms', b) -> match_stacks s ts mm' ms'. Proof. induction 1; intros. constructor. - econstructor; eauto. - eapply frame_match_alloc; eauto. + econstructor; eauto. eapply frame_match_alloc; eauto. Qed. Lemma match_stacks_free: forall s ts ms mm, match_stacks s ts mm ms -> - forall b, + forall b lom him los his mm' ms', + Mem.free mm b lom him = Some mm' -> + Mem.free ms b los his = Some ms' -> stack_below ts b -> - match_stacks s ts (Mem.free mm b) (Mem.free ms b). + match_stacks s ts mm' ms'. Proof. induction 1; intros. constructor. - red in H5; simpl in H5. + red in H7; simpl in H7. econstructor; eauto. eapply frame_match_free; eauto. unfold block; omega. eapply IHmatch_stacks; eauto. @@ -636,21 +795,36 @@ Proof. Qed. Lemma match_stacks_function_entry: - forall s ts mm ms lom him mm' los his ms' stk, + forall s ts ms mm, match_stacks s ts mm ms -> - alloc mm lom him = (mm', stk) -> - alloc ms los his = (ms', stk) -> + forall lom him mm' stk los his ms', + Mem.alloc mm lom him = (mm', stk) -> + Mem.alloc ms los his = (ms', stk) -> match_stacks s ts mm' ms' /\ stack_below ts stk. Proof. intros. - assert (stk = nextblock mm). eapply Mem.alloc_result; eauto. - assert (stk = nextblock ms). eapply Mem.alloc_result; eauto. - split. - eapply match_stacks_alloc; eauto. congruence. - red. - inv H; simpl. - unfold nullptr. apply Zgt_lt. apply nextblock_pos. - inv H6. red in H. rewrite H3. auto. + assert (stk = Mem.nextblock mm) by eauto with mem. + split. eapply match_stacks_alloc; eauto. + red. inv H; simpl. + unfold Mem.nullptr. apply Zgt_lt. apply Mem.nextblock_pos. + inv H5. auto. +Qed. + +Lemma match_stacks_external_call: + forall s ts mm ms, + match_stacks s ts mm ms -> + forall ef vargs t vres mm' ms' vargs' vres', + Mem.extends mm ms -> + external_call ef vargs mm t vres mm' -> + Mem.extends mm' ms' -> + external_call ef vargs' ms t vres' ms' -> + mem_unchanged_on (loc_out_of_bounds mm) ms ms' -> + match_stacks s ts mm' ms'. +Proof. + induction 1; intros. + constructor. + econstructor; eauto. + eapply frame_match_external_call; eauto. Qed. (** ** Invariant between states. *) @@ -666,27 +840,30 @@ Qed. Inductive match_states: Machabstr.state -> Machconcr.state -> Prop := | match_states_intro: - forall s f sp base c rs fr mm ts fb ms + forall s f sp base c rs fr mm ts trs fb ms (STACKS: match_stacks s ts mm ms) (FM: frame_match f (extend_frame f ts fr) sp base mm ms) (BELOW: stack_below ts sp) + (RLD: regset_lessdef rs trs) (MEXT: Mem.extends mm ms) (FIND: Genv.find_funct_ptr ge fb = Some (Internal f)), match_states (Machabstr.State s f (Vptr sp base) c rs fr mm) - (Machconcr.State ts fb (Vptr sp base) c rs ms) + (Machconcr.State ts fb (Vptr sp base) c trs ms) | match_states_call: - forall s f rs mm ts fb ms + forall s f rs mm ts trs fb ms (STACKS: match_stacks s ts mm ms) (MEXT: Mem.extends mm ms) + (RLD: regset_lessdef rs trs) (FIND: Genv.find_funct_ptr ge fb = Some f), match_states (Machabstr.Callstate s f rs mm) - (Machconcr.Callstate ts fb rs ms) + (Machconcr.Callstate ts fb trs ms) | match_states_return: - forall s rs mm ts ms + forall s rs mm ts trs ms (STACKS: match_stacks s ts mm ms) - (MEXT: Mem.extends mm ms), + (MEXT: Mem.extends mm ms) + (RLD: regset_lessdef rs trs), match_states (Machabstr.Returnstate s rs mm) - (Machconcr.Returnstate ts rs ms). + (Machconcr.Returnstate ts trs ms). (** * The proof of simulation *) @@ -725,20 +902,26 @@ Qed. (** Preservation of arguments to external functions. *) Lemma transl_extcall_arguments: - forall rs s sg args ts m ms, + forall rs s sg args ts trs m ms, Machabstr.extcall_arguments (parent_function s) rs (parent_frame s) sg args -> + regset_lessdef rs trs -> match_stacks s ts m ms -> - extcall_arguments rs ms (parent_sp ts) sg args. + exists targs, + extcall_arguments trs ms (parent_sp ts) sg targs + /\ Val.lessdef_list args targs. Proof. unfold Machabstr.extcall_arguments, extcall_arguments; intros. - assert (forall locs vals, - Machabstr.extcall_args (parent_function s) rs (parent_frame s) locs vals -> - extcall_args rs ms (parent_sp ts) locs vals). - induction locs; intros; inv H1. - constructor. + generalize (Conventions.loc_arguments sg) args H. + induction l; intros; inv H2. + exists (@nil val); split; constructor. + exploit IHl; eauto. intros [targs [A B]]. + inv H7. exists (trs r :: targs); split. + constructor; auto. constructor. + constructor; auto. + exploit match_stacks_get_parent; eauto. intros [targ [C D]]. + exists (targ :: targs); split. + constructor; auto. constructor; auto. constructor; auto. - inv H6. constructor. constructor. eapply match_stacks_get_parent; eauto. - auto. Qed. Hypothesis wt_prog: wt_program p. @@ -757,11 +940,11 @@ Proof. (* Mgetstack *) assert (WTF: wt_function f) by (inv WTS; auto). - exists (State ts fb (Vptr sp0 base) c (rs#dst <- v) ms); split. + exploit frame_match_get_slot; eauto. eapply get_slot_extends; eauto. + intros [v' [A B]]. + exists (State ts fb (Vptr sp0 base) c (trs#dst <- v') ms); split. constructor; auto. - eapply frame_match_get_slot; eauto. - eapply get_slot_extends; eauto. - econstructor; eauto with coqlib. + econstructor; eauto with coqlib. eapply regset_lessdef_set; eauto. (* Msetstack *) assert (WTF: wt_function f) by (inv WTS; auto). @@ -769,41 +952,51 @@ Proof. inv WTS. generalize (wt_function_instrs _ WTF _ (is_tail_in TAIL)); intro WTI. inv WTI. apply WTRS. - exploit frame_match_set_slot; eauto. + exploit frame_match_set_slot. eauto. eauto. eapply set_slot_extends; eauto. + auto. apply RLD. auto. intros [ms' [STORE [FM' EXT']]]. - exists (State ts fb (Vptr sp0 base) c rs ms'); split. + exists (State ts fb (Vptr sp0 base) c trs ms'); split. apply exec_Msetstack; auto. econstructor; eauto. eapply match_stacks_store_slot; eauto. (* Mgetparam *) assert (WTF: wt_function f) by (inv WTS; auto). - exists (State ts fb (Vptr sp0 base) c (rs#dst <- v) ms); split. + exploit match_stacks_get_parent; eauto. intros [v' [A B]]. + exists (State ts fb (Vptr sp0 base) c (trs#dst <- v') ms); split. eapply exec_Mgetparam; eauto. eapply frame_match_load_link; eauto. - eapply match_stacks_get_parent; eauto. - econstructor; eauto with coqlib. + eapply match_stacks_parent_sp_pointer; eauto. + econstructor; eauto with coqlib. apply regset_lessdef_set; eauto. (* Mop *) - exists (State ts fb (Vptr sp0 base) c (rs#res <- v) ms); split. + exploit eval_operation_lessdef. 2: eauto. + eapply regset_lessdef_list; eauto. + intros [v' [A B]]. + exists (State ts fb (Vptr sp0 base) c (trs#res <- v') ms); split. apply exec_Mop; auto. - econstructor; eauto with coqlib. + econstructor; eauto with coqlib. apply regset_lessdef_set; eauto. (* Mload *) - exists (State ts fb (Vptr sp0 base) c (rs#dst <- v) ms); split. + exploit eval_addressing_lessdef. 2: eauto. eapply regset_lessdef_list; eauto. + intros [a' [A B]]. + exploit Mem.loadv_extends. eauto. eauto. eexact B. + intros [v' [C D]]. + exists (State ts fb (Vptr sp0 base) c (trs#dst <- v') ms); split. eapply exec_Mload; eauto. - destruct a; simpl in H0; try discriminate. - simpl. eapply Mem.load_extends; eauto. - econstructor; eauto with coqlib. + econstructor; eauto with coqlib. apply regset_lessdef_set; eauto. (* Mstore *) - destruct a; simpl in H0; try discriminate. - exploit Mem.store_within_extends; eauto. intros [ms' [STORE MEXT']]. - exists (State ts fb (Vptr sp0 base) c rs ms'); split. + exploit eval_addressing_lessdef. 2: eauto. eapply regset_lessdef_list; eauto. + intros [a' [A B]]. + exploit Mem.storev_extends. eauto. eauto. eexact B. apply RLD. + intros [ms' [C D]]. + exists (State ts fb (Vptr sp0 base) c trs ms'); split. eapply exec_Mstore; eauto. + destruct a; simpl in H0; try congruence. inv B. simpl in C. econstructor; eauto with coqlib. - eapply match_stacks_store; eauto. + eapply match_stacks_store. eauto. eexact H0. eexact C. eapply frame_match_store; eauto. (* Mcall *) @@ -814,7 +1007,7 @@ Proof. inv WTS. eapply is_tail_cons_left; eauto. destruct H0 as [ra' RETADDR]. econstructor; split. - eapply exec_Mcall; eauto. + eapply exec_Mcall; eauto. eapply regset_lessdef_find_function_ptr; eauto. econstructor; eauto. econstructor; eauto. inv WTS; auto. exact I. @@ -822,12 +1015,13 @@ Proof. assert (WTF: wt_function f) by (inv WTS; auto). exploit find_function_find_function_ptr; eauto. intros [fb' [FIND' FINDFUNCT]]. + exploit frame_match_delete; eauto. intros [ms' [A B]]. econstructor; split. eapply exec_Mtailcall; eauto. - eapply frame_match_load_link; eauto. - eapply frame_match_load_retaddr; eauto. - econstructor; eauto. eapply match_stacks_free; auto. - apply free_extends; auto. + eapply regset_lessdef_find_function_ptr; eauto. + eapply frame_match_load_link; eauto. eapply match_stacks_parent_sp_pointer; eauto. + eapply frame_match_load_retaddr; eauto. eapply match_stacks_parent_ra_pointer; eauto. + econstructor; eauto. eapply match_stacks_free; eauto. (* Mgoto *) econstructor; split. @@ -837,49 +1031,50 @@ Proof. (* Mcond *) econstructor; split. eapply exec_Mcond_true; eauto. + eapply eval_condition_lessdef; eauto. apply regset_lessdef_list; auto. econstructor; eauto. econstructor; split. eapply exec_Mcond_false; eauto. + eapply eval_condition_lessdef; eauto. apply regset_lessdef_list; auto. econstructor; eauto. (* Mjumptable *) econstructor; split. - eapply exec_Mjumptable; eauto. + eapply exec_Mjumptable; eauto. + generalize (RLD arg); intro LD. rewrite H in LD. inv LD. auto. econstructor; eauto. (* Mreturn *) assert (WTF: wt_function f) by (inv WTS; auto). + exploit frame_match_delete; eauto. intros [ms' [A B]]. econstructor; split. eapply exec_Mreturn; eauto. - eapply frame_match_load_link; eauto. - eapply frame_match_load_retaddr; eauto. + eapply frame_match_load_link; eauto. eapply match_stacks_parent_sp_pointer; eauto. + eapply frame_match_load_retaddr; eauto. eapply match_stacks_parent_ra_pointer; eauto. econstructor; eauto. eapply match_stacks_free; eauto. - apply free_extends; auto. (* internal function *) assert (WTF: wt_function f). inv WTS. inv H5. auto. - caseEq (alloc ms (- f.(fn_framesize)) f.(fn_stacksize)). - intros ms' stk' ALLOC. - assert (Val.has_type (parent_sp ts) Tint). - inv STACKS; simpl; auto. - assert (Val.has_type (parent_ra ts) Tint). - inv STACKS; simpl; auto. - destruct (frame_match_function_entry _ WTF _ _ _ _ _ _ _ - MEXT H ALLOC H0 H1) - as [ms2 [ms3 [EQ [STORE1 [STORE2 [FM MEXT']]]]]]. - subst stk'. + exploit frame_match_function_entry. eauto. eauto. eauto. + instantiate (1 := ts). eapply match_stacks_parent_sp_pointer; eauto. + eapply match_stacks_parent_ra_pointer; eauto. + intros [ms1 [ms2 [ms3 [ALLOC [STORE1 [STORE2 [FM MEXT']]]]]]]. econstructor; split. eapply exec_function_internal; eauto. exploit match_stacks_function_entry; eauto. intros [STACKS' BELOW]. econstructor; eauto. eapply match_stacks_store_slot with (ms := ms2); eauto. - eapply match_stacks_store_slot with (ms := ms'); eauto. + eapply match_stacks_store_slot with (ms := ms1); eauto. (* external function *) + exploit transl_extcall_arguments; eauto. intros [targs [A B]]. + exploit external_call_mem_extends; eauto. + intros [tres [ms' [C [D [E F]]]]]. econstructor; split. - eapply exec_function_external; eauto. - eapply transl_extcall_arguments; eauto. + eapply exec_function_external. eauto. eexact C. eexact A. reflexivity. econstructor; eauto. + eapply match_stacks_external_call; eauto. + apply regset_lessdef_set; auto. (* return *) inv STACKS. @@ -894,8 +1089,10 @@ Lemma equiv_initial_states: Proof. intros. inversion H. econstructor; split. - econstructor. eauto. - split. econstructor. constructor. apply Mem.extends_refl. auto. + econstructor. eauto. eauto. + split. econstructor. constructor. apply Mem.extends_refl. + unfold Regmap.init; red; intros. constructor. + auto. econstructor. simpl; intros; contradiction. eapply Genv.find_funct_ptr_prop; eauto. red; intros; exact I. @@ -906,7 +1103,9 @@ Lemma equiv_final_states: match_states st1 st2 /\ wt_state st1 -> Machabstr.final_state st1 r -> Machconcr.final_state st2 r. Proof. intros. inv H0. destruct H. inv H. inv STACKS. - constructor; auto. + constructor. + generalize (RLD (Conventions.loc_result (mksignature nil (Some Tint)))). + rewrite H1. intro LD. inv LD. auto. Qed. Theorem exec_program_equiv: |