diff options
Diffstat (limited to 'arm/linux/Conventions1.v')
-rw-r--r-- | arm/linux/Conventions1.v | 337 |
1 files changed, 117 insertions, 220 deletions
diff --git a/arm/linux/Conventions1.v b/arm/linux/Conventions1.v index f1ddc23..1731eba 100644 --- a/arm/linux/Conventions1.v +++ b/arm/linux/Conventions1.v @@ -32,34 +32,19 @@ Require Import Locations. *) Definition int_caller_save_regs := - R0 :: R1 :: R2 :: R3 :: nil. + R0 :: R1 :: R2 :: R3 :: R12 :: nil. Definition float_caller_save_regs := - F0 :: F1 :: F2 :: F3 :: F4 :: F5 :: nil. + F0 :: F1 :: F2 :: F3 :: F4 :: F5 :: F6 :: F7 :: nil. Definition int_callee_save_regs := - R4 :: R5 :: R6 :: R7 :: R8 :: R9 :: R11 :: nil. + R4 :: R5 :: R6 :: R7 :: R8 :: R9 :: R10 :: R11 :: nil. Definition float_callee_save_regs := F8 :: F9 :: F10 :: F11 :: F12 :: F13 :: F14 :: F15 :: nil. -Definition destroyed_at_call_regs := - int_caller_save_regs ++ float_caller_save_regs. - Definition destroyed_at_call := - List.map R destroyed_at_call_regs. - -Definition int_temporaries := IT1 :: IT2 :: nil. - -Definition float_temporaries := FT1 :: FT2 :: nil. - -Definition temporary_regs := int_temporaries ++ float_temporaries. - -Definition temporaries := List.map R temporary_regs. - -Definition destroyed_at_move_regs: list mreg := nil. - -Definition destroyed_at_move := List.map R destroyed_at_move_regs. + int_caller_save_regs ++ float_caller_save_regs. Definition dummy_int_reg := R0. (**r Used in [Coloring]. *) Definition dummy_float_reg := F0. (**r Used in [Coloring]. *) @@ -72,7 +57,7 @@ Definition dummy_float_reg := F0. (**r Used in [Coloring]. *) Definition index_int_callee_save (r: mreg) := match r with | R4 => 0 | R5 => 1 | R6 => 2 | R7 => 3 - | R8 => 4 | R9 => 5 | R11 => 6 + | R8 => 4 | R9 => 5 | R10 => 6 | R11 => 7 | _ => -1 end. @@ -169,34 +154,27 @@ Qed. Lemma register_classification: forall r, - (In (R r) temporaries \/ In (R r) destroyed_at_call) \/ - (In r int_callee_save_regs \/ In r float_callee_save_regs). + In r destroyed_at_call \/ In r int_callee_save_regs \/ In r float_callee_save_regs. Proof. destruct r; - try (left; left; simpl; OrEq); - try (left; right; simpl; OrEq); + try (left; simpl; OrEq); try (right; left; simpl; OrEq); try (right; right; simpl; OrEq). Qed. + Lemma int_callee_save_not_destroyed: forall r, - In (R r) temporaries \/ In (R r) destroyed_at_call -> - ~(In r int_callee_save_regs). + In r destroyed_at_call -> In r int_callee_save_regs -> False. Proof. - intros; red; intros. elim H. - generalize H0. simpl; ElimOrEq; NotOrEq. - generalize H0. simpl; ElimOrEq; NotOrEq. + intros. revert H0 H. simpl. ElimOrEq; NotOrEq. Qed. Lemma float_callee_save_not_destroyed: forall r, - In (R r) temporaries \/ In (R r) destroyed_at_call -> - ~(In r float_callee_save_regs). + In r destroyed_at_call -> In r float_callee_save_regs -> False. Proof. - intros; red; intros. elim H. - generalize H0. simpl; ElimOrEq; NotOrEq. - generalize H0. simpl; ElimOrEq; NotOrEq. + intros. revert H0 H. simpl. ElimOrEq; NotOrEq. Qed. Lemma int_callee_save_type: @@ -245,51 +223,33 @@ Qed. Calling conventions are largely arbitrary: they must respect the properties proved in this section (such as no overlapping between the locations of function arguments), but this leaves much liberty in choosing actual - locations. To ensure binary interoperability of code generated by our - compiler with libraries compiled by another ARM EABI compiler, we - implement *almost* the standard conventions defined in the ARM EABI application - binary interface, with two exceptions: -- Double-precision arguments and results are passed in VFP double registers - instead of pairs of integer registers. -- Single-precision arguments and results are passed as double-precision floats. -*) + locations. *) (** ** Location of function result *) (** The result value of a function is passed back to the caller in - registers [R0] or [F0], depending on the type of the returned value. - We treat a function without result as a function with one integer result. *) + registers [R0] or [F0] or [R0,R1], depending on the type of the + returned value. We treat a function without result as a function + with one integer result. *) -Definition loc_result (s: signature) : mreg := +Definition loc_result (s: signature) : list mreg := match s.(sig_res) with - | None => R0 - | Some Tint => R0 - | Some Tfloat => F0 + | None => R0 :: nil + | Some Tint => R0 :: nil + | Some Tfloat => F0 :: nil + | Some Tlong => R1 :: R0 :: nil end. -(** The result location has the type stated in the signature. *) - -Lemma loc_result_type: - forall sig, - mreg_type (loc_result sig) = - match sig.(sig_res) with None => Tint | Some ty => ty end. -Proof. - intros; unfold loc_result. - destruct (sig_res sig). - destruct t; reflexivity. - reflexivity. -Qed. - (** The result location is a caller-save register or a temporary *) Lemma loc_result_caller_save: - forall (s: signature), - In (R (loc_result s)) destroyed_at_call \/ In (R (loc_result s)) temporaries. + forall (s: signature) (r: mreg), + In r (loc_result s) -> In r destroyed_at_call. Proof. - intros; unfold loc_result. left; - destruct (sig_res s). - destruct t; simpl; OrEq. - simpl; OrEq. + intros. + assert (r = R0 \/ r = R1 \/ r = F0). + unfold loc_result in H. destruct (sig_res s); [destruct t|idtac]; simpl in H; intuition. + destruct H0 as [A | [A | A]]; subst r; simpl; OrEq. Qed. (** ** Location of function arguments *) @@ -299,34 +259,37 @@ Qed. - The first 2 float arguments are passed in registers [F0] and [F1]. - Each float argument passed in a float register ``consumes'' an aligned pair of two integer registers. +- Each long integer argument is passed in an aligned pair of two integer + registers. - Extra arguments are passed on the stack, in [Outgoing] slots, consecutively - assigned (1 word for an integer argument, 2 words for a float), + assigned (1 word for an integer argument, 2 words for a float or a long), starting at word offset 0. *) -Function ireg_param (n: Z) : mreg := +Definition ireg_param (n: Z) : mreg := if zeq n (-4) then R0 else if zeq n (-3) then R1 else if zeq n (-2) then R2 - else if zeq n (-1) then R3 - else R4. (**r should not happen *) - -Function freg_param (n: Z) : mreg := - if zeq n (-4) then F0 - else if zeq n (-3) then F1 - else if zeq n (-2) then F1 - else F2. (**r should not happen *) + else R3. +Definition freg_param (n: Z) : mreg := + if zeq n (-4) then F0 else F1. Fixpoint loc_arguments_rec (tyl: list typ) (ofs: Z) {struct tyl} : list loc := match tyl with | nil => nil | Tint :: tys => - (if zle 0 ofs then S (Outgoing ofs Tint) else R (ireg_param ofs)) + (if zle 0 ofs then S Outgoing ofs Tint else R (ireg_param ofs)) :: loc_arguments_rec tys (ofs + 1) | Tfloat :: tys => - (if zle (-1) ofs then S (Outgoing (align ofs 2) Tfloat) else R (freg_param ofs)) - :: loc_arguments_rec tys (align ofs 2 + 2) + let ofs := align ofs 2 in + (if zle 0 ofs then S Outgoing ofs Tfloat else R (freg_param ofs)) + :: loc_arguments_rec tys (ofs + 2) + | Tlong :: tys => + let ofs := align ofs 2 in + (if zle 0 ofs then S Outgoing (ofs + 1) Tint else R (ireg_param (ofs + 1))) + :: (if zle 0 ofs then S Outgoing ofs Tint else R (ireg_param ofs)) + :: loc_arguments_rec tys (ofs + 2) end. (** [loc_arguments s] returns the list of locations where to store arguments @@ -342,7 +305,7 @@ Fixpoint size_arguments_rec (tyl: list typ) (ofs: Z) {struct tyl} : Z := match tyl with | nil => ofs | Tint :: tys => size_arguments_rec tys (ofs + 1) - | Tfloat :: tys => size_arguments_rec tys (align ofs 2 + 2) + | (Tfloat | Tlong) :: tys => size_arguments_rec tys (align ofs 2 + 2) end. Definition size_arguments (s: signature) : Z := @@ -353,109 +316,85 @@ Definition size_arguments (s: signature) : Z := Definition loc_argument_acceptable (l: loc) : Prop := match l with - | R r => ~(In l temporaries) - | S (Outgoing ofs ty) => ofs >= 0 + | R r => In r destroyed_at_call + | S Outgoing ofs ty => ofs >= 0 /\ ty <> Tlong | _ => False end. +(* Lemma align_monotone: forall x1 x2 y, y > 0 -> x1 <= x2 -> align x1 y <= align x2 y. Proof. intros. unfold align. apply Zmult_le_compat_r. apply Z_div_le. omega. omega. omega. Qed. +*) + +Remark ireg_param_caller_save: + forall n, In (ireg_param n) destroyed_at_call. +Proof. + unfold ireg_param; intros. + destruct (zeq n (-4)). simpl; auto. + destruct (zeq n (-3)). simpl; auto. + destruct (zeq n (-2)); simpl; auto. +Qed. + +Remark freg_param_caller_save: + forall n, In (freg_param n) destroyed_at_call. +Proof. + unfold freg_param; intros. destruct (zeq n (-4)); simpl; OrEq. +Qed. Remark loc_arguments_rec_charact: forall tyl ofs l, In l (loc_arguments_rec tyl ofs) -> match l with - | R r => - (exists n, ofs <= n < 0 /\ r = ireg_param n) - \/ (exists n, ofs <= n < -1 /\ r = freg_param n) - | S (Outgoing ofs' ty) => ofs' >= 0 /\ ofs' >= ofs - | S _ => False + | R r => In r destroyed_at_call + | S Outgoing ofs' ty => ofs' >= 0 /\ ofs <= ofs' /\ ty <> Tlong + | S _ _ _ => False end. Proof. induction tyl; simpl loc_arguments_rec; intros. elim H. - destruct a; elim H; intro. - subst l. destruct (zle 0 ofs). omega. - left. exists ofs; split; auto; omega. - generalize (IHtyl _ _ H0). - destruct l. intros [[n A] | [n A]]; [left|right]; exists n; intuition omega. - destruct s; auto; omega. - subst l. destruct (zle (-1) ofs). - split. apply Zle_ge. change 0 with (align (-1) 2). apply align_monotone; omega. - apply Zle_ge. apply align_le. omega. - right. exists ofs. intuition. + destruct a. +- (* Tint *) + destruct H. + subst l. destruct (zle 0 ofs). + split. omega. split. omega. congruence. + apply ireg_param_caller_save. + exploit IHtyl; eauto. destruct l; auto. destruct sl; auto. intuition omega. +- (* Tfloat *) assert (ofs <= align ofs 2) by (apply align_le; omega). - generalize (IHtyl _ _ H0). - destruct l. intros [[n A] | [n A]]; [left|right]; exists n; intuition omega. - destruct s; auto; omega. -Qed. - -Lemma loc_notin_in_diff: - forall l ll, - Loc.notin l ll <-> (forall l', In l' ll -> Loc.diff l l'). -Proof. - induction ll; simpl; intuition. subst l'. auto. -Qed. - -Remark loc_arguments_rec_notin_local: - forall tyl ofs ofs0 ty0, - Loc.notin (S (Local ofs0 ty0)) (loc_arguments_rec tyl ofs). -Proof. - intros. rewrite loc_notin_in_diff. intros. - exploit loc_arguments_rec_charact; eauto. - destruct l'; intros; simpl; auto. destruct s; auto; contradiction. + destruct H. + subst l. destruct (zle 0 (align ofs 2)). + split. omega. split. auto. congruence. + apply freg_param_caller_save. + exploit IHtyl; eauto. destruct l; auto. destruct sl; auto. intuition omega. +- (* Tlong *) + assert (ofs <= align ofs 2) by (apply align_le; omega). + destruct H. + subst l. destruct (zle 0 (align ofs 2)). + split. omega. split. omega. congruence. + apply ireg_param_caller_save. + destruct H. + subst l. destruct (zle 0 (align ofs 2)). + split. omega. split. omega. congruence. + apply ireg_param_caller_save. + exploit IHtyl; eauto. destruct l; auto. destruct sl; auto. intuition omega. Qed. Lemma loc_arguments_acceptable: forall (s: signature) (r: loc), In r (loc_arguments s) -> loc_argument_acceptable r. Proof. - unfold loc_arguments; intros. + unfold loc_arguments, loc_argument_acceptable; intros. generalize (loc_arguments_rec_charact _ _ _ H). - destruct r; simpl. - intros [[n [A B]] | [n [A B]]]; subst m. - functional induction (ireg_param n); intuition congruence. - functional induction (freg_param n); intuition congruence. - destruct s0; tauto. + destruct r; auto. + destruct sl; auto. + tauto. Qed. Hint Resolve loc_arguments_acceptable: locs. -(** Arguments are parwise disjoint (in the sense of [Loc.norepet]). *) - -Lemma loc_arguments_norepet: - forall (s: signature), Loc.norepet (loc_arguments s). -Proof. - unfold loc_arguments; intros. - assert (forall tyl ofs, -4 <= ofs -> Loc.norepet (loc_arguments_rec tyl ofs)). - induction tyl; simpl; intros. - constructor. - destruct a; constructor. - rewrite loc_notin_in_diff. intros. exploit loc_arguments_rec_charact; eauto. - destruct (zle 0 ofs); destruct l'; simpl; auto. - destruct s0; intuition. - intros [[n [A B]] | [n [A B]]]; subst m. - functional induction (ireg_param ofs); functional induction (ireg_param n); congruence || omegaContradiction. - functional induction (ireg_param ofs); functional induction (freg_param n); congruence || omegaContradiction. - apply IHtyl. omega. - rewrite loc_notin_in_diff. intros. exploit loc_arguments_rec_charact; eauto. - destruct (zle (-1) ofs); destruct l'; simpl; auto. - destruct s0; intuition. - intros [[n [A B]] | [n [A B]]]; subst m. - functional induction (freg_param ofs); functional induction (ireg_param n); congruence || omegaContradiction. - functional induction (freg_param ofs); functional induction (freg_param n); try (congruence || omegaContradiction). - compute in A. intuition. - compute in A. intuition. - compute in A. intuition. - compute in A. intuition. - compute in A. intuition. - apply IHtyl. assert (ofs <= align ofs 2) by (apply align_le; omega). omega. - apply H. omega. -Qed. - (** The offsets of [Outgoing] arguments are below [size_arguments s]. *) Remark size_arguments_rec_above: @@ -468,6 +407,8 @@ Proof. apply Zle_trans with (ofs + 1); auto; omega. assert (ofs <= align ofs 2) by (apply align_le; omega). apply Zle_trans with (align ofs 2 + 2); auto; omega. + assert (ofs <= align ofs 2) by (apply align_le; omega). + apply Zle_trans with (align ofs 2 + 2); auto; omega. Qed. Lemma size_arguments_above: @@ -478,79 +419,35 @@ Qed. Lemma loc_arguments_bounded: forall (s: signature) (ofs: Z) (ty: typ), - In (S (Outgoing ofs ty)) (loc_arguments s) -> + In (S Outgoing ofs ty) (loc_arguments s) -> ofs + typesize ty <= size_arguments s. Proof. intros. assert (forall tyl ofs0, 0 <= ofs0 -> ofs0 <= Zmax 0 (size_arguments_rec tyl ofs0)). + { intros. generalize (size_arguments_rec_above tyl ofs0). intros. - rewrite Zmax_spec. rewrite zlt_false. auto. omega. + rewrite Zmax_spec. rewrite zlt_false. auto. omega. + } assert (forall tyl ofs0, - In (S (Outgoing ofs ty)) (loc_arguments_rec tyl ofs0) -> + In (S Outgoing ofs ty) (loc_arguments_rec tyl ofs0) -> ofs + typesize ty <= Zmax 0 (size_arguments_rec tyl ofs0)). - induction tyl; simpl; intros. - elim H1. - destruct a; elim H1; intros. - destruct (zle 0 ofs0); inv H2. apply H0. omega. auto. - destruct (zle (-1) ofs0); inv H2. apply H0. - assert (align (-1) 2 <= align ofs0 2). apply align_monotone. omega. auto. - change (align (-1) 2) with 0 in H2. omega. - auto. - + { + induction tyl; simpl; intros. + elim H1. + destruct a. + - (* Tint *) + destruct H1; auto. destruct (zle 0 ofs0); inv H1. apply H0. omega. + - (* Tfloat *) + destruct H1; auto. destruct (zle 0 (align ofs0 2)); inv H1. apply H0. omega. + - (* Tlong *) + destruct H1. + destruct (zle 0 (align ofs0 2)); inv H1. + eapply Zle_trans. 2: apply H0. simpl typesize; omega. omega. + destruct H1; auto. + destruct (zle 0 (align ofs0 2)); inv H1. + eapply Zle_trans. 2: apply H0. simpl typesize; omega. omega. + } unfold size_arguments. apply H1. auto. Qed. - -(** Temporary registers do not overlap with argument locations. *) - -Lemma loc_arguments_not_temporaries: - forall sig, Loc.disjoint (loc_arguments sig) temporaries. -Proof. - intros; red; intros x1 x2 A B. - exploit loc_arguments_acceptable; eauto. unfold loc_argument_acceptable. - destruct x1; intros. simpl. destruct x2; auto. intuition congruence. - destruct s; try contradiction. revert B. simpl. ElimOrEq; auto. -Qed. -Hint Resolve loc_arguments_not_temporaries: locs. - -(** Argument registers are caller-save. *) - -Lemma arguments_caller_save: - forall sig r, - In (R r) (loc_arguments sig) -> In (R r) destroyed_at_call. -Proof. - unfold loc_arguments; intros. - destruct (loc_arguments_rec_charact _ _ _ H) as [[n [A B]] | [n [A B]]]; subst r. - functional induction (ireg_param n); simpl; auto. omegaContradiction. - functional induction (freg_param n); simpl; auto 10. -Qed. - -(** Argument locations agree in number with the function signature. *) - -Lemma loc_arguments_length: - forall sig, - List.length (loc_arguments sig) = List.length sig.(sig_args). -Proof. - assert (forall tyl ofs, List.length (loc_arguments_rec tyl ofs) = List.length tyl). - induction tyl; simpl; intros. - auto. - destruct a; simpl; decEq; auto. - - intros. unfold loc_arguments. auto. -Qed. - -(** Argument locations agree in types with the function signature. *) - -Lemma loc_arguments_type: - forall sig, List.map Loc.type (loc_arguments sig) = sig.(sig_args). -Proof. - assert (forall tyl ofs, List.map Loc.type (loc_arguments_rec tyl ofs) = tyl). - induction tyl; simpl; intros. - auto. - destruct a; simpl; decEq; auto. - destruct (zle 0 ofs). auto. functional induction (ireg_param ofs); auto. - destruct (zle (-1) ofs). auto. functional induction (freg_param ofs); auto. - - intros. unfold loc_arguments. apply H. -Qed. |