Skip to content

Commit 7120520

Browse files
authored
Merge pull request #581 from AbsInt/global_alignment
Enforce minimal safe alignment on global variables
2 parents 508575c + 4ff1b27 commit 7120520

8 files changed

Lines changed: 70 additions & 96 deletions

File tree

‎backend/Inlining.v‎

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
(** RTL function inlining *)
1414

15-
Require Import Coqlib Wfsimpl Maps Errors Integers.
15+
Require Import Coqlib Wfsimpl Maps Errors Integers Memory.
1616
Require Import AST Linking.
1717
Require Import Op Registers RTL.
1818

@@ -230,17 +230,12 @@ Definition initcontext (dpc dreg nreg: positive) (sz: Z) :=
230230

231231
(** The context used to inline a call to another function. *)
232232

233-
Definition min_alignment (sz: Z) :=
234-
if zle sz 1 then 1
235-
else if zle sz 2 then 2
236-
else if zle sz 4 then 4 else 8.
237-
238233
Definition callcontext (ctx: context)
239234
(dpc dreg nreg: positive) (sz: Z)
240235
(retpc: node) (retreg: reg) :=
241236
{| dpc := dpc;
242237
dreg := dreg;
243-
dstk := align (ctx.(dstk) + ctx.(mstk)) (min_alignment sz);
238+
dstk := align (ctx.(dstk) + ctx.(mstk)) (min_safe_alignment sz);
244239
mreg := nreg;
245240
mstk := Z.max sz 0;
246241
retinfo := Some (spc ctx retpc, sreg ctx retreg) |}.
@@ -250,7 +245,7 @@ Definition callcontext (ctx: context)
250245
Definition tailcontext (ctx: context) (dpc dreg nreg: positive) (sz: Z) :=
251246
{| dpc := dpc;
252247
dreg := dreg;
253-
dstk := align ctx.(dstk) (min_alignment sz);
248+
dstk := align ctx.(dstk) (min_safe_alignment sz);
254249
mreg := nreg;
255250
mstk := Z.max sz 0;
256251
retinfo := ctx.(retinfo) |}.

‎backend/Inliningproof.v‎

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -748,30 +748,6 @@ Proof.
748748
intros. eapply Mem.perm_free_3; eauto.
749749
Qed.
750750

751-
Lemma min_alignment_sound:
752-
forall sz n, (min_alignment sz | n) -> Mem.inj_offset_aligned n sz.
753-
Proof.
754-
intros; red; intros. unfold min_alignment in H.
755-
assert (2 <= sz -> (2 | n)). intros.
756-
destruct (zle sz 1). extlia.
757-
destruct (zle sz 2). auto.
758-
destruct (zle sz 4). apply Z.divide_trans with 4; auto. exists 2; auto.
759-
apply Z.divide_trans with 8; auto. exists 4; auto.
760-
assert (4 <= sz -> (4 | n)). intros.
761-
destruct (zle sz 1). extlia.
762-
destruct (zle sz 2). extlia.
763-
destruct (zle sz 4). auto.
764-
apply Z.divide_trans with 8; auto. exists 2; auto.
765-
assert (8 <= sz -> (8 | n)). intros.
766-
destruct (zle sz 1). extlia.
767-
destruct (zle sz 2). extlia.
768-
destruct (zle sz 4). extlia.
769-
auto.
770-
destruct chunk; simpl in *; auto using Z.divide_1_l.
771-
apply H2; lia.
772-
apply H2; lia.
773-
Qed.
774-
775751
(** Preservation by external calls *)
776752

777753
Section EXTCALL.
@@ -843,9 +819,9 @@ Proof.
843819
intros. inv H.
844820
(* base *)
845821
eapply match_stacks_inside_base; eauto. congruence.
846-
rewrite H1. rewrite DSTK. apply align_unchanged. apply min_alignment_pos. apply Z.divide_0_r.
822+
rewrite H1. rewrite DSTK. apply align_unchanged. apply min_safe_alignment_pos. apply Z.divide_0_r.
847823
(* inlined *)
848-
assert (dstk ctx <= dstk ctx'). rewrite H1. apply align_le. apply min_alignment_pos.
824+
assert (dstk ctx <= dstk ctx'). rewrite H1. apply align_le. apply min_safe_alignment_pos.
849825
eapply match_stacks_inside_inlined; eauto.
850826
red; intros. destruct (zlt ofs (dstk ctx)). apply PAD; lia. apply H3. inv H4. extlia.
851827
congruence.
@@ -1071,7 +1047,7 @@ Proof.
10711047
apply agree_val_regs_gen; auto.
10721048
eapply Mem.free_left_inject; eauto.
10731049
red; intros; apply PRIV'.
1074-
assert (dstk ctx <= dstk ctx'). red in H14; rewrite H14. apply align_le. apply min_alignment_pos.
1050+
assert (dstk ctx <= dstk ctx'). red in H14; rewrite H14. apply align_le. apply min_safe_alignment_pos.
10751051
lia.
10761052

10771053
- (* builtin *)
@@ -1210,7 +1186,7 @@ Proof.
12101186
eapply range_private_perms; eauto. extlia.
12111187
(* offset is aligned *)
12121188
replace (fn_stacksize f - 0) with (fn_stacksize f) by lia.
1213-
inv FB. apply min_alignment_sound; auto.
1189+
inv FB. red; intros. eapply Z.divide_trans; eauto. apply min_safe_alignment_sound; auto.
12141190
(* nobody maps to (sp, dstk ctx...) *)
12151191
intros. exploit (PRIV (ofs + delta')); eauto. extlia.
12161192
intros [A B]. eelim B; eauto.

‎backend/Inliningspec.v‎

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
(** RTL function inlining: relational specification *)
1414

15-
Require Import Coqlib Wfsimpl Maps Errors Integers.
15+
Require Import Coqlib Wfsimpl Maps Errors Integers Memory.
1616
Require Import AST Linking.
1717
Require Import Op Registers RTL.
1818
Require Import Inlining.
@@ -256,7 +256,7 @@ Definition context_stack_call (ctx1 ctx2: context): Prop :=
256256
ctx1.(mstk) >= 0 /\ ctx1.(dstk) + ctx1.(mstk) <= ctx2.(dstk).
257257

258258
Definition context_stack_tailcall (ctx1: context) (f: function) (ctx2: context) : Prop :=
259-
ctx2.(dstk) = align ctx1.(dstk) (min_alignment f.(fn_stacksize)).
259+
ctx2.(dstk) = align ctx1.(dstk) (min_safe_alignment f.(fn_stacksize)).
260260

261261
Section INLINING_BODY_SPEC.
262262

@@ -332,7 +332,7 @@ with tr_funbody: context -> function -> code -> Prop :=
332332
(forall r, In r f.(fn_params) -> Ple r ctx.(mreg)) ->
333333
(forall pc i, f.(fn_code)!pc = Some i -> tr_instr ctx pc i c) ->
334334
ctx.(mstk) = Z.max f.(fn_stacksize) 0 ->
335-
(min_alignment f.(fn_stacksize) | ctx.(dstk)) ->
335+
(min_safe_alignment f.(fn_stacksize) | ctx.(dstk)) ->
336336
ctx.(dstk) >= 0 -> ctx.(dstk) + ctx.(mstk) <= stacksize ->
337337
tr_funbody ctx f c.
338338

@@ -454,19 +454,12 @@ Hypothesis rec_spec:
454454
Ple (Pos.add ctx.(dreg) ctx.(mreg)) s.(st_nextreg) ->
455455
ctx.(mstk) >= 0 ->
456456
ctx.(mstk) = Z.max (fn_stacksize f) 0 ->
457-
(min_alignment (fn_stacksize f) | ctx.(dstk)) ->
457+
(min_safe_alignment (fn_stacksize f) | ctx.(dstk)) ->
458458
ctx.(dstk) >= 0 ->
459459
s'.(st_stksize) <= stacksize ->
460460
(forall pc, Ple ctx.(dpc) pc -> Plt pc s'.(st_nextnode) -> c!pc = s'.(st_code)!pc) ->
461461
tr_funbody ctx f c.
462462

463-
Remark min_alignment_pos:
464-
forall sz, min_alignment sz > 0.
465-
Proof.
466-
intros; unfold min_alignment.
467-
destruct (zle sz 1). lia. destruct (zle sz 2). lia. destruct (zle sz 4); lia.
468-
Qed.
469-
470463
Ltac inv_incr :=
471464
match goal with
472465
| [ H: sincr _ _ |- _ ] => destruct H; inv_incr
@@ -508,14 +501,14 @@ Proof.
508501
simpl. subst s2; simpl in *; extlia.
509502
simpl. subst s3; simpl in *; extlia.
510503
simpl. extlia.
511-
simpl. apply align_divides. apply min_alignment_pos.
512-
assert (dstk ctx + mstk ctx <= dstk ctx'). simpl. apply align_le. apply min_alignment_pos. lia.
504+
simpl. apply align_divides. apply min_safe_alignment_pos.
505+
assert (dstk ctx + mstk ctx <= dstk ctx'). simpl. apply align_le. apply min_safe_alignment_pos. lia.
513506
lia.
514507
intros. simpl in H. rewrite S1.
515508
transitivity (s1.(st_code)!pc0). eapply set_instr_other; eauto. unfold node in *; extlia.
516509
eapply add_moves_unchanged; eauto. unfold node in *; extlia. extlia.
517510
red; simpl. subst s2; simpl in *. extlia.
518-
red; simpl. split. auto. apply align_le. apply min_alignment_pos.
511+
red; simpl. split. auto. apply align_le. apply min_safe_alignment_pos.
519512
(* tailcall *)
520513
destruct (can_inline fe s1) as [|id f P Q].
521514
(* not inlined *)
@@ -538,8 +531,8 @@ Proof.
538531
simpl. subst s3; simpl in *. subst s2; simpl in *. extlia.
539532
simpl. subst s3; simpl in *; extlia.
540533
simpl. extlia.
541-
simpl. apply align_divides. apply min_alignment_pos.
542-
assert (dstk ctx <= dstk ctx'). simpl. apply align_le. apply min_alignment_pos. lia.
534+
simpl. apply align_divides. apply min_safe_alignment_pos.
535+
assert (dstk ctx <= dstk ctx'). simpl. apply align_le. apply min_safe_alignment_pos. lia.
543536
lia.
544537
intros. simpl in H. rewrite S1.
545538
transitivity (s1.(st_code))!pc0. eapply set_instr_other; eauto. unfold node in *; extlia.
@@ -612,7 +605,7 @@ Lemma expand_cfg_rec_spec:
612605
Ple (ctx.(dreg) + ctx.(mreg)) s.(st_nextreg) ->
613606
ctx.(mstk) >= 0 ->
614607
ctx.(mstk) = Z.max (fn_stacksize f) 0 ->
615-
(min_alignment (fn_stacksize f) | ctx.(dstk)) ->
608+
(min_safe_alignment (fn_stacksize f) | ctx.(dstk)) ->
616609
ctx.(dstk) >= 0 ->
617610
s'.(st_stksize) <= stacksize ->
618611
(forall pc', Ple ctx.(dpc) pc' -> Plt pc' s'.(st_nextnode) -> c!pc' = s'.(st_code)!pc') ->
@@ -665,7 +658,7 @@ Lemma expand_cfg_spec:
665658
Ple (ctx.(dreg) + ctx.(mreg)) s.(st_nextreg) ->
666659
ctx.(mstk) >= 0 ->
667660
ctx.(mstk) = Z.max (fn_stacksize f) 0 ->
668-
(min_alignment (fn_stacksize f) | ctx.(dstk)) ->
661+
(min_safe_alignment (fn_stacksize f) | ctx.(dstk)) ->
669662
ctx.(dstk) >= 0 ->
670663
s'.(st_stksize) <= stacksize ->
671664
(forall pc', Ple ctx.(dpc) pc' -> Plt pc' s'.(st_nextnode) -> c!pc' = s'.(st_code)!pc') ->

‎cfrontend/C2C.ml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1270,7 +1270,8 @@ let convertGlobvar loc env (sto, id, ty, optinit) =
12701270
Debug.atom_global id id';
12711271
let ty' = convertTyp env ty in
12721272
let sz = Ctypes.sizeof !comp_env ty' in
1273-
let al = Ctypes.alignof !comp_env ty' in
1273+
let al =
1274+
Z.max (Ctypes.alignof !comp_env ty') (Memdata.min_safe_alignment sz) in
12741275
let attr = Cutil.attributes_of_type env ty in
12751276
let init' =
12761277
match optinit with

‎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. eapply Z.divide_trans.
916+
apply min_safe_alignment_sound; eauto.
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_sound: forall sz chunk,
145+
size_chunk chunk <= sz -> (align_chunk chunk | min_safe_alignment sz).
146+
Proof.
147+
intros. exists (min_safe_alignment sz / align_chunk chunk).
148+
unfold size_chunk, align_chunk, min_safe_alignment in *.
149+
repeat destruct zlt; destruct chunk; reflexivity || lia.
150+
Qed.
151+
152+
Lemma min_safe_alignment_8: forall sz,
153+
(min_safe_alignment sz | 8).
154+
Proof.
155+
intros. exists (8 / min_safe_alignment sz).
156+
unfold min_safe_alignment. repeat destruct zlt; reflexivity.
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}.

‎lib/Camlcoq.ml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ module Z = struct
179179
let le x y = (Z.compare x y <> Gt)
180180
let ge x y = (Z.compare x y <> Lt)
181181
let compare x y = match Z.compare x y with Lt -> -1 | Eq -> 0 | Gt -> 1
182+
let max = Z.max
183+
let min = Z.min
182184

183185
let to_int = function
184186
| Z0 -> 0

0 commit comments

Comments
 (0)