Skip to content

Commit 8ef73e7

Browse files
committed
Introduce and use Memdata.min_safe_alignment
This computation (of the minimal alignment for a block of a given size) used to be done in Cminorgen, but it's generally useful.
1 parent 0737ca9 commit 8ef73e7

3 files changed

Lines changed: 48 additions & 41 deletions

File tree

‎cfrontend/Cminorgen.v‎

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
(** Translation from Csharpminor to Cminor. *)
1414

1515
From Coq Require Import FSets FSetAVL Orders Mergesort.
16-
Require Import Coqlib Maps Ordered Errors Integers Floats.
16+
Require Import Coqlib Maps Ordered Errors Integers Floats Memory.
1717
Require Import AST Linking.
1818
Require Import Csharpminor Cminor.
1919

@@ -216,16 +216,11 @@ with transl_lblstmt (cenv: compilenv) (xenv: exit_env) (ls: Csharpminor.lbl_stmt
216216
allocated a slot in the Cminor stack data. Sufficient padding is
217217
inserted to ensure adequate alignment of addresses. *)
218218

219-
Definition block_alignment (sz: Z) : Z :=
220-
if zlt sz 2 then 1
221-
else if zlt sz 4 then 2
222-
else if zlt sz 8 then 4 else 8.
223-
224219
Definition assign_variable
225220
(cenv_stacksize: compilenv * Z) (id_sz: ident * Z) : compilenv * Z :=
226221
let (id, sz) := id_sz in
227222
let (cenv, stacksize) := cenv_stacksize in
228-
let ofs := align stacksize (block_alignment sz) in
223+
let ofs := align stacksize (min_safe_alignment sz) in
229224
(PTree.set id ofs cenv, ofs + Z.max 0 sz).
230225

231226
Definition assign_variables (cenv_stacksize: compilenv * Z) (vars: list (ident * Z)) : compilenv * Z :=

‎cfrontend/Cminorgenproof.v‎

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -885,21 +885,12 @@ Qed.
885885

886886
(** Properties of the compilation environment produced by [build_compilenv] *)
887887

888-
Remark block_alignment_pos:
889-
forall sz, block_alignment sz > 0.
890-
Proof.
891-
unfold block_alignment; intros.
892-
destruct (zlt sz 2). lia.
893-
destruct (zlt sz 4). lia.
894-
destruct (zlt sz 8); lia.
895-
Qed.
896-
897888
Remark assign_variable_incr:
898889
forall id sz cenv stksz cenv' stksz',
899890
assign_variable (cenv, stksz) (id, sz) = (cenv', stksz') -> stksz <= stksz'.
900891
Proof.
901892
simpl; intros. inv H.
902-
generalize (align_le stksz (block_alignment sz) (block_alignment_pos sz)).
893+
generalize (align_le stksz (min_safe_alignment sz) (min_safe_alignment_pos sz)).
903894
assert (0 <= Z.max 0 sz). apply Zmax_bound_l. lia.
904895
lia.
905896
Qed.
@@ -919,35 +910,22 @@ Qed.
919910

920911
Remark inj_offset_aligned_block:
921912
forall stacksize sz,
922-
Mem.inj_offset_aligned (align stacksize (block_alignment sz)) sz.
913+
Mem.inj_offset_aligned (align stacksize (min_safe_alignment sz)) sz.
923914
Proof.
924-
intros; red; intros.
925-
apply Z.divide_trans with (block_alignment sz).
926-
unfold align_chunk. unfold block_alignment.
927-
generalize Z.divide_1_l; intro.
928-
generalize Z.divide_refl; intro.
929-
assert (2 | 4). exists 2; auto.
930-
assert (2 | 8). exists 4; auto.
931-
assert (4 | 8). exists 2; auto.
932-
destruct (zlt sz 2).
933-
destruct chunk; simpl in *; auto; extlia.
934-
destruct (zlt sz 4).
935-
destruct chunk; simpl in *; auto; extlia.
936-
destruct (zlt sz 8).
937-
destruct chunk; simpl in *; auto; extlia.
938-
destruct chunk; simpl; auto.
939-
apply align_divides. apply block_alignment_pos.
915+
intros; red; intros. apply Z.divide_trans with (min_safe_alignment sz).
916+
- apply min_safe_alignment_safe; auto.
917+
- apply align_divides. apply min_safe_alignment_pos.
940918
Qed.
941919

942920
Remark inj_offset_aligned_block':
943921
forall stacksize sz,
944-
Mem.inj_offset_aligned (align stacksize (block_alignment sz)) (Z.max 0 sz).
922+
Mem.inj_offset_aligned (align stacksize (min_safe_alignment sz)) (Z.max 0 sz).
945923
Proof.
946924
intros.
947-
replace (block_alignment sz) with (block_alignment (Z.max 0 sz)).
925+
replace (min_safe_alignment sz) with (min_safe_alignment (Z.max 0 sz)).
948926
apply inj_offset_aligned_block.
949927
rewrite Zmax_spec. destruct (zlt sz 0); auto.
950-
transitivity 1. reflexivity. unfold block_alignment. rewrite zlt_true. auto. lia.
928+
transitivity 1. reflexivity. unfold min_safe_alignment. rewrite zlt_true. auto. lia.
951929
Qed.
952930

953931
Lemma assign_variable_sound:
@@ -962,21 +940,22 @@ Lemma assign_variable_sound:
962940
Proof.
963941
unfold assign_variable; intros until vars; intros ASV NOREPET POS COMPAT SEP.
964942
inv ASV.
965-
assert (LE: sz1 <= align sz1 (block_alignment sz)). apply align_le. apply block_alignment_pos.
943+
assert (LE: sz1 <= align sz1 (min_safe_alignment sz)).
944+
{ apply align_le. apply min_safe_alignment_pos. }
966945
assert (EITHER: forall id' sz',
967946
In (id', sz') (vars ++ (id, sz) :: nil) ->
968947
In (id', sz') vars /\ id' <> id \/ (id', sz') = (id, sz)).
969-
intros. rewrite in_app in H. destruct H.
948+
{ intros. rewrite in_app in H. destruct H.
970949
left; split; auto. red; intros; subst id'. elim NOREPET.
971950
change id with (fst (id, sz')). apply in_map; auto.
972-
simpl in H. destruct H. auto. contradiction.
951+
simpl in H. destruct H. auto. contradiction. }
973952
split; red; intros.
974953
apply EITHER in H. destruct H as [[P Q] | P].
975954
exploit COMPAT; eauto. intros [ofs [A [B [C D]]]].
976955
exists ofs.
977956
split. rewrite PTree.gso; auto.
978957
split. auto. split. auto. zify; lia.
979-
inv P. exists (align sz1 (block_alignment sz)).
958+
inv P. exists (align sz1 (min_safe_alignment sz)).
980959
split. apply PTree.gss.
981960
split. apply inj_offset_aligned_block.
982961
split. lia.

‎common/Memdata.v‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,39 @@ Proof.
126126
| exists 8; reflexivity ].
127127
Qed.
128128

129+
(** Given the size [sz] of a block, [min_safe_alignment sz] is the minimum
130+
alignment that guarantees that all valid memory accesses in the block
131+
have at least this alignment. *)
132+
133+
Definition min_safe_alignment (sz: Z) : Z :=
134+
if zlt sz 2 then 1
135+
else if zlt sz 4 then 2
136+
else if zlt sz 8 then 4 else 8.
137+
138+
Lemma min_safe_alignment_pos: forall sz,
139+
min_safe_alignment sz > 0.
140+
Proof.
141+
intros; unfold min_safe_alignment. repeat (destruct zlt); lia.
142+
Qed.
143+
144+
Lemma min_safe_alignment_safe: forall sz chunk,
145+
size_chunk chunk <= sz -> (align_chunk chunk | min_safe_alignment sz).
146+
Proof.
147+
intros.
148+
generalize Z.divide_1_l Z.divide_refl; intros.
149+
assert (2 | 4) by (exists 2; auto).
150+
assert (2 | 8) by (exists 4; auto).
151+
assert (4 | 8) by (exists 2; auto).
152+
unfold size_chunk, align_chunk, min_safe_alignment in *.
153+
destruct (zlt sz 2). destruct chunk; auto; lia.
154+
destruct (zlt sz 4). destruct chunk; auto; lia.
155+
destruct (zlt sz 8). destruct chunk; auto; lia.
156+
destruct chunk; auto.
157+
Qed.
158+
159+
(** Memory quantities are a coarser variant of memory chunks, used to represent
160+
the size of a pointer (32 or 64 bits). *)
161+
129162
Inductive quantity : Type := Q32 | Q64.
130163

131164
Definition quantity_eq (q1 q2: quantity) : {q1 = q2} + {q1 <> q2}.

0 commit comments

Comments
 (0)