diff options
author | xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e> | 2006-02-09 14:55:48 +0000 |
---|---|---|
committer | xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e> | 2006-02-09 14:55:48 +0000 |
commit | 2ae43be7b9d4118335c9d2cef6e098f9b9f807fe (patch) | |
tree | bbb5e49ccbf7e3614966571acc317f8d318fecad /backend/Alloctyping.v | |
download | compcert-2ae43be7b9d4118335c9d2cef6e098f9b9f807fe.tar.gz compcert-2ae43be7b9d4118335c9d2cef6e098f9b9f807fe.zip |
Initial import of compcert
git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@1 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e
Diffstat (limited to 'backend/Alloctyping.v')
-rw-r--r-- | backend/Alloctyping.v | 509 |
1 files changed, 509 insertions, 0 deletions
diff --git a/backend/Alloctyping.v b/backend/Alloctyping.v new file mode 100644 index 00000000..39e53eef --- /dev/null +++ b/backend/Alloctyping.v @@ -0,0 +1,509 @@ +(** Preservation of typing during register allocation. *) + +Require Import Coqlib. +Require Import Maps. +Require Import AST. +Require Import Op. +Require Import Registers. +Require Import RTL. +Require Import Locations. +Require Import LTL. +Require Import Coloring. +Require Import Coloringproof. +Require Import Allocation. +Require Import Allocproof. +Require Import RTLtyping. +Require Import LTLtyping. +Require Import Conventions. +Require Import Alloctyping_aux. + +(** This file proves that register allocation (the translation from + RTL to LTL defined in file [Allocation]) preserves typing: + given a well-typed RTL input, it produces LTL code that is + well-typed. *) + +Section TYPING_FUNCTION. + +Variable f: RTL.function. +Variable env: regenv. +Variable live: PMap.t Regset.t. +Variable alloc: reg -> loc. +Variable tf: LTL.function. + +Hypothesis TYPE_RTL: type_rtl_function f = Some env. +Hypothesis ALLOC: regalloc f live (live0 f live) env = Some alloc. +Hypothesis TRANSL: transf_function f = Some tf. + +Lemma wt_rtl_function: RTLtyping.wt_function env f. +Proof. + apply type_rtl_function_correct; auto. +Qed. + +Lemma alloc_type: forall r, Loc.type (alloc r) = env r. +Proof. + intro. eapply regalloc_preserves_types; eauto. +Qed. + +Lemma alloc_types: + forall rl, List.map Loc.type (List.map alloc rl) = List.map env rl. +Proof. + intros. rewrite list_map_compose. apply list_map_exten. + intros. symmetry. apply alloc_type. +Qed. + +(** [loc_read_ok l] states whether location [l] is well-formed in an + argument context (for reading). *) + +Definition loc_read_ok (l: loc) : Prop := + match l with R r => True | S s => slot_bounded tf s end. + +(** [loc_write_ok l] states whether location [l] is well-formed in a + result context (for writing). *) + +Definition loc_write_ok (l: loc) : Prop := + match l with + | R r => True + | S (Incoming _ _) => False + | S s => slot_bounded tf s end. + +Definition locs_read_ok (ll: list loc) : Prop := + forall l, In l ll -> loc_read_ok l. + +Definition locs_write_ok (ll: list loc) : Prop := + forall l, In l ll -> loc_write_ok l. + +Remark loc_write_ok_read_ok: + forall l, loc_write_ok l -> loc_read_ok l. +Proof. + destruct l; simpl. auto. + destruct s; tauto. +Qed. +Hint Resolve loc_write_ok_read_ok: allocty. + +Remark locs_write_ok_read_ok: + forall ll, locs_write_ok ll -> locs_read_ok ll. +Proof. + unfold locs_write_ok, locs_read_ok. auto with allocty. +Qed. +Hint Resolve locs_write_ok_read_ok: allocty. + +Lemma alloc_write_ok: + forall r, loc_write_ok (alloc r). +Proof. + intros. generalize (regalloc_acceptable _ _ _ _ _ r ALLOC). + destruct (alloc r); simpl. auto. + destruct s; try contradiction. simpl. omega. +Qed. +Hint Resolve alloc_write_ok: allocty. + +Lemma allocs_write_ok: + forall rl, locs_write_ok (List.map alloc rl). +Proof. + intros; red; intros. + generalize (list_in_map_inv _ _ _ H). intros [r [EQ IN]]. + subst l. auto with allocty. +Qed. +Hint Resolve allocs_write_ok: allocty. + +(** * Typing LTL constructors *) + +(** We show that the LTL constructor functions defined in [Allocation] + generate well-typed LTL basic blocks, given sufficient typing + and well-formedness hypotheses over the locations involved. *) + +Lemma wt_add_reload: + forall src dst k, + loc_read_ok src -> + Loc.type src = mreg_type dst -> + wt_block tf k -> + wt_block tf (add_reload src dst k). +Proof. + intros. unfold add_reload. destruct src. + case (mreg_eq m dst); intro. auto. apply wt_Bopmove. exact H0. auto. + apply wt_Bgetstack. exact H0. exact H. auto. +Qed. + +Lemma wt_add_spill: + forall src dst k, + loc_write_ok dst -> + mreg_type src = Loc.type dst -> + wt_block tf k -> + wt_block tf (add_spill src dst k). +Proof. + intros. unfold add_spill. destruct dst. + case (mreg_eq src m); intro. auto. + apply wt_Bopmove. exact H0. auto. + apply wt_Bsetstack. generalize H. simpl. destruct s; auto. + symmetry. exact H0. generalize H. simpl. destruct s; auto. contradiction. + auto. +Qed. + +Lemma wt_add_reloads: + forall srcs dsts k, + locs_read_ok srcs -> + List.map Loc.type srcs = List.map mreg_type dsts -> + wt_block tf k -> + wt_block tf (add_reloads srcs dsts k). +Proof. + induction srcs; intros. + destruct dsts. simpl; auto. simpl in H0; discriminate. + destruct dsts; simpl in H0. discriminate. simpl. + apply wt_add_reload. apply H; apply in_eq. congruence. + apply IHsrcs. red; intros; apply H; apply in_cons; auto. + congruence. auto. +Qed. + +Lemma wt_reg_for: + forall l, mreg_type (reg_for l) = Loc.type l. +Proof. + intros. destruct l; simpl. auto. + case (slot_type s); reflexivity. +Qed. +Hint Resolve wt_reg_for: allocty. + +Lemma wt_regs_for_rec: + forall locs itmps ftmps, + (List.length locs <= List.length itmps)%nat -> + (List.length locs <= List.length ftmps)%nat -> + (forall r, In r itmps -> mreg_type r = Tint) -> + (forall r, In r ftmps -> mreg_type r = Tfloat) -> + List.map mreg_type (regs_for_rec locs itmps ftmps) = List.map Loc.type locs. +Proof. + induction locs; intros. + simpl. auto. + destruct itmps; simpl in H. omegaContradiction. + destruct ftmps; simpl in H0. omegaContradiction. + simpl. apply (f_equal2 (@cons typ)). + destruct a. reflexivity. simpl. case (slot_type s). + apply H1; apply in_eq. apply H2; apply in_eq. + apply IHlocs. omega. omega. + intros; apply H1; apply in_cons; auto. + intros; apply H2; apply in_cons; auto. +Qed. + +Lemma wt_regs_for: + forall locs, + (List.length locs <= 3)%nat -> + List.map mreg_type (regs_for locs) = List.map Loc.type locs. +Proof. + intros. unfold regs_for. apply wt_regs_for_rec. + simpl. auto. simpl. auto. + simpl; intros; intuition; subst r; reflexivity. + simpl; intros; intuition; subst r; reflexivity. +Qed. +Hint Resolve wt_regs_for: allocty. + +Lemma wt_add_move: + forall src dst b, + loc_read_ok src -> loc_write_ok dst -> + Loc.type src = Loc.type dst -> + wt_block tf b -> + wt_block tf (add_move src dst b). +Proof. + intros. unfold add_move. + case (Loc.eq src dst); intro. + auto. + destruct src. apply wt_add_spill; auto. + destruct dst. apply wt_add_reload; auto. + set (tmp := match slot_type s with Tint => IT1 | Tfloat => FT1 end). + apply wt_add_reload. auto. + simpl. unfold tmp. case (slot_type s); reflexivity. + apply wt_add_spill. auto. + simpl. simpl in H1. rewrite <- H1. unfold tmp. case (slot_type s); reflexivity. + auto. +Qed. + +Theorem wt_parallel_move: + forall srcs dsts b, + List.map Loc.type srcs = List.map Loc.type dsts -> + locs_read_ok srcs -> + locs_write_ok dsts -> wt_block tf b -> wt_block tf (parallel_move srcs dsts b). +Proof. + unfold locs_read_ok, locs_write_ok. + apply wt_parallel_moveX; simpl; auto. + exact wt_add_move. +Qed. + +Lemma wt_add_op_move: + forall src res s, + Loc.type src = Loc.type res -> + loc_read_ok src -> loc_write_ok res -> + wt_block tf (add_op Omove (src :: nil) res s). +Proof. + intros. unfold add_op. simpl. + apply wt_add_move. auto. auto. auto. constructor. +Qed. + +Lemma wt_add_op_undef: + forall res s, + loc_write_ok res -> + wt_block tf (add_op Oundef nil res s). +Proof. + intros. unfold add_op. simpl. + apply wt_Bopundef. apply wt_add_spill. auto. auto with allocty. + constructor. +Qed. + +Lemma wt_add_op_others: + forall op args res s, + op <> Omove -> op <> Oundef -> + (List.map Loc.type args, Loc.type res) = type_of_operation op -> + locs_read_ok args -> + loc_write_ok res -> + wt_block tf (add_op op args res s). +Proof. + intros. unfold add_op. + caseEq (is_move_operation op args). intros. + generalize (is_move_operation_correct op args H4). tauto. + intro. assert ((List.length args <= 3)%nat). + replace (length args) with (length (fst (type_of_operation op))). + apply Allocproof.length_type_of_operation. + rewrite <- H1. simpl. apply list_length_map. + generalize (wt_regs_for args H5); intro. + generalize (wt_reg_for res); intro. + apply wt_add_reloads. auto. auto. + apply wt_Bop. auto. auto. congruence. + apply wt_add_spill. auto. auto. constructor. +Qed. + +Lemma wt_add_load: + forall chunk addr args dst s, + List.map Loc.type args = type_of_addressing addr -> + Loc.type dst = type_of_chunk chunk -> + locs_read_ok args -> + loc_write_ok dst -> + wt_block tf (add_load chunk addr args dst s). +Proof. + intros. unfold add_load. + assert ((List.length args <= 2)%nat). + replace (length args) with (length (type_of_addressing addr)). + apply Allocproof.length_type_of_addressing. + rewrite <- H. apply list_length_map. + assert ((List.length args <= 3)%nat). omega. + generalize (wt_regs_for args H4); intro. + generalize (wt_reg_for dst); intro. + apply wt_add_reloads. auto. auto. + apply wt_Bload. congruence. congruence. + apply wt_add_spill. auto. auto. constructor. +Qed. + +Lemma wt_add_store: + forall chunk addr args src s, + List.map Loc.type args = type_of_addressing addr -> + Loc.type src = type_of_chunk chunk -> + locs_read_ok args -> + loc_read_ok src -> + wt_block tf (add_store chunk addr args src s). +Proof. + intros. unfold add_store. + assert ((List.length args <= 2)%nat). + replace (length args) with (length (type_of_addressing addr)). + apply Allocproof.length_type_of_addressing. + rewrite <- H. apply list_length_map. + assert ((List.length (src :: args) <= 3)%nat). simpl. omega. + generalize (wt_regs_for (src :: args) H4); intro. + caseEq (regs_for (src :: args)). + intro. constructor. + intros rsrc rargs EQ. rewrite EQ in H5. simpl in H5. + apply wt_add_reloads. + red; intros. elim H6; intro. subst l; auto. auto. + simpl. congruence. + apply wt_Bstore. congruence. congruence. constructor. +Qed. + +Lemma wt_add_call: + forall sig los args res s, + match los with inl l => Loc.type l = Tint | inr s => True end -> + List.map Loc.type args = sig.(sig_args) -> + Loc.type res = match sig.(sig_res) with None => Tint | Some ty => ty end -> + locs_read_ok args -> + match los with inl l => loc_read_ok l | inr s => True end -> + loc_write_ok res -> + wt_block tf (add_call sig los args res s). +Proof. + intros. + assert (locs_write_ok (loc_arguments sig)). + red; intros. generalize (loc_arguments_acceptable sig l H5). + destruct l; simpl. auto. + destruct s0; try contradiction. simpl. omega. + unfold add_call. destruct los. + apply wt_add_reload. auto. simpl; congruence. + apply wt_parallel_move. rewrite loc_arguments_type. auto. + auto. auto. + apply wt_Bcall. reflexivity. + apply wt_add_spill. auto. + rewrite loc_result_type. auto. constructor. + apply wt_parallel_move. rewrite loc_arguments_type. auto. + auto. auto. + apply wt_Bcall. auto. + apply wt_add_spill. auto. + rewrite loc_result_type. auto. constructor. +Qed. + +Lemma wt_add_cond: + forall cond args ifso ifnot, + List.map Loc.type args = type_of_condition cond -> + locs_read_ok args -> + wt_block tf (add_cond cond args ifso ifnot). +Proof. + intros. + assert ((List.length args) <= 3)%nat. + replace (length args) with (length (type_of_condition cond)). + apply Allocproof.length_type_of_condition. + rewrite <- H. apply list_length_map. + generalize (wt_regs_for args H1). intro. + unfold add_cond. apply wt_add_reloads. + auto. auto. + apply wt_Bcond. congruence. +Qed. + +Lemma wt_add_return: + forall sig optarg, + option_map Loc.type optarg = sig.(sig_res) -> + match optarg with None => True | Some arg => loc_read_ok arg end -> + wt_block tf (add_return sig optarg). +Proof. + intros. unfold add_return. destruct optarg. + apply wt_add_reload. auto. rewrite loc_result_type. + simpl in H. destruct (sig_res sig). congruence. discriminate. + constructor. + apply wt_Bopundef. constructor. +Qed. + +Lemma wt_add_undefs: + forall ll b, + wt_block tf b -> wt_block tf (add_undefs ll b). +Proof. + induction ll; intros. + simpl. auto. + simpl. destruct a. apply wt_Bopundef. auto. auto. +Qed. + +Lemma wt_add_entry: + forall params undefs s, + List.map Loc.type params = sig_args (RTL.fn_sig f) -> + locs_write_ok params -> + wt_block tf (add_entry (RTL.fn_sig f) params undefs s). +Proof. + set (sig := RTL.fn_sig f). + assert (sig = tf.(fn_sig)). + unfold sig. symmetry. apply Allocproof.sig_function_translated. auto. + assert (locs_read_ok (loc_parameters sig)). + red; unfold loc_parameters. intros. + generalize (list_in_map_inv _ _ _ H0). intros [l1 [EQ IN]]. + subst l. generalize (loc_arguments_acceptable _ _ IN). + destruct l1. simpl. auto. + destruct s; try contradiction. + simpl; intros. split. omega. rewrite <- H. + apply loc_arguments_bounded. auto. + intros. unfold add_entry. + apply wt_parallel_move. rewrite loc_parameters_type. auto. + auto. auto. + apply wt_add_undefs. constructor. +Qed. + +(** * Type preservation during translation from RTL to LTL *) + +Lemma wt_transf_instr: + forall pc instr, + RTLtyping.wt_instr env f instr -> + wt_block tf (transf_instr f live alloc pc instr). +Proof. + intros. inversion H; simpl. + (* nop *) + constructor. + (* move *) + case (Regset.mem r live!!pc). + apply wt_add_op_move; auto with allocty. + repeat rewrite alloc_type. auto. constructor. + (* undef *) + case (Regset.mem r live!!pc). + apply wt_add_op_undef; auto with allocty. + constructor. + (* other ops *) + case (Regset.mem res live!!pc). + apply wt_add_op_others; auto with allocty. + rewrite alloc_types. rewrite alloc_type. auto. + constructor. + (* load *) + case (Regset.mem dst live!!pc). + apply wt_add_load; auto with allocty. + rewrite alloc_types. auto. rewrite alloc_type. auto. + constructor. + (* store *) + apply wt_add_store; auto with allocty. + rewrite alloc_types. auto. rewrite alloc_type. auto. + (* call *) + apply wt_add_call. + destruct ros; simpl. rewrite alloc_type; auto. auto. + rewrite alloc_types; auto. + rewrite alloc_type. auto. + auto with allocty. + destruct ros; simpl; auto with allocty. + auto with allocty. + (* cond *) + apply wt_add_cond. rewrite alloc_types; auto. auto with allocty. + (* return *) + apply wt_add_return. + destruct optres; simpl. rewrite alloc_type. exact H0. exact H0. + destruct optres; simpl; auto with allocty. +Qed. + +Lemma wt_transf_instrs: + let c := PTree.map (transf_instr f live alloc) (RTL.fn_code f) in + forall pc b, c!pc = Some b -> wt_block tf b. +Proof. + intros until b. + unfold c. rewrite PTree.gmap. caseEq (RTL.fn_code f)!pc. + intros instr EQ. simpl. intros. injection H; intro; subst b. + apply wt_transf_instr. eapply RTLtyping.wt_instrs; eauto. + apply wt_rtl_function. + simpl; intros; discriminate. +Qed. + +Lemma wt_transf_entrypoint: + let c := transf_entrypoint f live alloc + (PTree.map (transf_instr f live alloc) (RTL.fn_code f)) in + (forall pc b, c!pc = Some b -> wt_block tf b). +Proof. + simpl. unfold transf_entrypoint. + intros pc b. rewrite PTree.gsspec. + case (peq pc (fn_nextpc f)); intros. + injection H; intro; subst b. + apply wt_add_entry. + rewrite alloc_types. eapply RTLtyping.wt_params. apply wt_rtl_function. + auto with allocty. + apply wt_transf_instrs with pc; auto. +Qed. + +End TYPING_FUNCTION. + +Lemma wt_transf_function: + forall f tf, + transf_function f = Some tf -> wt_function tf. +Proof. + intros. generalize H; unfold transf_function. + caseEq (type_rtl_function f). intros env TYP. + caseEq (analyze f). intros live ANL. + change (transfer f (RTL.fn_entrypoint f) + live!!(RTL.fn_entrypoint f)) + with (live0 f live). + caseEq (regalloc f live (live0 f live) env). + intros alloc ALLOC. + intro EQ; injection EQ; intro; subst tf. + red. simpl. intros. eapply wt_transf_entrypoint; eauto. + intros; discriminate. + intros; discriminate. + intros; discriminate. +Qed. + +Lemma program_typing_preserved: + forall (p: RTL.program) (tp: LTL.program), + transf_program p = Some tp -> + LTLtyping.wt_program tp. +Proof. + intros; red; intros. + generalize (transform_partial_program_function transf_function p i f H H0). + intros [f0 [IN TRANSF]]. + apply wt_transf_function with f0; auto. +Qed. |