Skip to content

Commit b0e1527

Browse files
authored
More assertions for local alloc and letrec (#1081)
1 parent bb5c55d commit b0e1527

File tree

3 files changed

+77
-45
lines changed

3 files changed

+77
-45
lines changed

backend/cmmgen.ml

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -148,18 +148,22 @@ let get_field env ptr n dbg =
148148
get_field_gen mut ptr n dbg
149149

150150
type rhs_kind =
151-
| RHS_block of int
152-
| RHS_infix of { blocksize : int; offset : int }
153-
| RHS_floatblock of int
151+
| RHS_block of Lambda.alloc_mode * int
152+
| RHS_infix of { blocksize : int; offset : int; blockmode: Lambda.alloc_mode }
153+
| RHS_floatblock of Lambda.alloc_mode * int
154154
| RHS_nonrec
155155
;;
156156

157157
let rec expr_size env = function
158158
| Uvar id ->
159159
begin try V.find_same id env with Not_found -> RHS_nonrec end
160160
| Uclosure { functions ; not_scanned_slots ; scanned_slots } ->
161-
RHS_block (fundecls_size functions + List.length not_scanned_slots
162-
+ List.length scanned_slots)
161+
(* should all have the same mode *)
162+
let fn_mode = (List.hd functions).mode in
163+
List.iter (fun f -> assert (Lambda.eq_mode fn_mode f.mode)) functions;
164+
RHS_block (fn_mode,
165+
fundecls_size functions + List.length not_scanned_slots
166+
+ List.length scanned_slots)
163167
| Ulet(_str, _kind, id, exp, body) ->
164168
expr_size (V.add (VP.var id) (expr_size env exp) env) body
165169
| Uletrec(bindings, body) ->
@@ -169,24 +173,24 @@ let rec expr_size env = function
169173
bindings env
170174
in
171175
expr_size env body
172-
| Uprim(Pmakeblock _, args, _) ->
173-
RHS_block (List.length args)
174-
| Uprim(Pmakearray((Paddrarray | Pintarray), _, _), args, _) ->
175-
RHS_block (List.length args)
176-
| Uprim(Pmakearray(Pfloatarray, _, _), args, _) ->
177-
RHS_floatblock (List.length args)
178-
| Uprim(Pmakearray(Pgenarray, _, _), _, _) ->
176+
| Uprim(Pmakeblock (_, _, _, mode), args, _) ->
177+
RHS_block (mode, List.length args)
178+
| Uprim(Pmakearray((Paddrarray | Pintarray), _, mode), args, _) ->
179+
RHS_block (mode, List.length args)
180+
| Uprim(Pmakearray(Pfloatarray, _, mode), args, _) ->
181+
RHS_floatblock (mode, List.length args)
182+
| Uprim(Pmakearray(Pgenarray, _, _mode), _, _) ->
179183
(* Pgenarray is excluded from recursive bindings by the
180184
check in Translcore.check_recursive_lambda *)
181185
RHS_nonrec
182186
| Uprim (Pduprecord ((Record_regular | Record_inlined _), sz), _, _) ->
183-
RHS_block sz
187+
RHS_block (Lambda.alloc_heap, sz)
184188
| Uprim (Pduprecord (Record_unboxed _, _), _, _) ->
185189
assert false
186190
| Uprim (Pduprecord (Record_extension _, sz), _, _) ->
187-
RHS_block (sz + 1)
191+
RHS_block (Lambda.alloc_heap, sz + 1)
188192
| Uprim (Pduprecord (Record_float, sz), _, _) ->
189-
RHS_floatblock sz
193+
RHS_floatblock (Lambda.alloc_heap, sz)
190194
| Uprim (Pccall { prim_name; _ }, closure::_, _)
191195
when prim_name = "caml_check_value_is_closure" ->
192196
(* Used for "-clambda-checks". *)
@@ -195,7 +199,8 @@ let rec expr_size env = function
195199
expr_size env exp'
196200
| Uoffset (exp, offset) ->
197201
(match expr_size env exp with
198-
| RHS_block blocksize -> RHS_infix { blocksize; offset }
202+
| RHS_block (blockmode, blocksize) ->
203+
RHS_infix { blocksize; offset; blockmode }
199204
| RHS_nonrec -> RHS_nonrec
200205
| _ -> assert false)
201206
| Uregion exp ->
@@ -1437,14 +1442,19 @@ and transl_letrec env bindings cont =
14371442
args, dbg) in
14381443
let rec init_blocks = function
14391444
| [] -> fill_nonrec bsz
1440-
| (id, _exp, RHS_block sz) :: rem ->
1445+
| (_, _,
1446+
(RHS_block (Alloc_local, _) |
1447+
RHS_infix {blockmode=Alloc_local; _} |
1448+
RHS_floatblock (Alloc_local, _))) :: _ ->
1449+
Misc.fatal_error "Invalid stack allocation found"
1450+
| (id, _exp, RHS_block (Alloc_heap, sz)) :: rem ->
14411451
Clet(id, op_alloc "caml_alloc_dummy" [int_const dbg sz],
14421452
init_blocks rem)
1443-
| (id, _exp, RHS_infix { blocksize; offset}) :: rem ->
1453+
| (id, _exp, RHS_infix { blocksize; offset; blockmode=Alloc_heap }) :: rem ->
14441454
Clet(id, op_alloc "caml_alloc_dummy_infix"
14451455
[int_const dbg blocksize; int_const dbg offset],
14461456
init_blocks rem)
1447-
| (id, _exp, RHS_floatblock sz) :: rem ->
1457+
| (id, _exp, RHS_floatblock (Alloc_heap, sz)) :: rem ->
14481458
Clet(id, op_alloc "caml_alloc_dummy_float" [int_const dbg sz],
14491459
init_blocks rem)
14501460
| (id, _exp, RHS_nonrec) :: rem ->

middle_end/flambda2/from_lambda/dissect_letrec.ml

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ let is_simple (lam : Lambda.lambda) =
187187
match lam with Lvar _ | Lconst _ -> true | _ -> false
188188
[@@ocaml.warning "-fragile-match"]
189189

190+
let assert_not_local ~lam : Lambda.alloc_mode -> unit = function
191+
| Alloc_heap -> ()
192+
| Alloc_local ->
193+
Misc.fatal_errorf "Invalid stack allocation found in %a" Printlambda.lambda
194+
lam
195+
190196
let dead_code lam letrec =
191197
(* Some cases generate code without effects, and bound to nothing. We use this
192198
function to insert it as [Lsequence] in [effects], for documentation. It
@@ -203,6 +209,7 @@ let rec prepare_letrec (recursive_set : Ident.Set.t)
203209
(lam : Lambda.lambda) (letrec : letrec) =
204210
match lam with
205211
| Lfunction funct -> (
212+
assert_not_local ~lam funct.mode;
206213
match current_let with
207214
| Some current_let when Ident.Set.mem current_let.ident recursive_set ->
208215
{ letrec with functions = (current_let.ident, funct) :: letrec.functions }
@@ -221,6 +228,10 @@ let rec prepare_letrec (recursive_set : Ident.Set.t)
221228
| None -> dead_code lam letrec)
222229
| Lprim (((Pmakeblock _ | Pmakearray _ | Pduprecord _) as prim), args, dbg)
223230
when not (List.for_all is_simple args) ->
231+
(match prim with
232+
| Pmakeblock (_, _, _, mode) | Pmakearray (_, _, mode) ->
233+
assert_not_local ~lam mode
234+
| _ -> ());
224235
(* If there are some non-trivial expressions as arguments, we first extract
225236
the arguments (to let-bound variables) before deconstructing. Arguments
226237
could contain side effects and other blocks declarations. *)
@@ -246,15 +257,16 @@ let rec prepare_letrec (recursive_set : Ident.Set.t)
246257
defs
247258
in
248259
prepare_letrec recursive_set current_let lam letrec
249-
| Lprim (Pmakeblock _, args, _)
250-
| Lprim (Pmakearray ((Paddrarray | Pintarray), _, _), args, _) -> (
260+
| Lprim (Pmakeblock (_, _, _, mode), args, _)
261+
| Lprim (Pmakearray ((Paddrarray | Pintarray), _, mode), args, _) -> (
262+
assert_not_local ~lam mode;
251263
match current_let with
252264
| Some cl -> build_block cl (List.length args) (Normal 0) lam letrec
253-
| None ->
254-
dead_code lam letrec
255-
(* We know that [args] are all "simple" at this point, so no effects *))
256-
| Lprim (Pmakearray (Pfloatarray, _, _), args, _)
257-
| Lprim (Pmakefloatblock _, args, _) -> (
265+
| None -> dead_code lam letrec
266+
(* We know that [args] are all "simple" at this point, so no effects *))
267+
| Lprim (Pmakearray (Pfloatarray, _, mode), args, _)
268+
| Lprim (Pmakefloatblock (_, mode), args, _) -> (
269+
assert_not_local ~lam mode;
258270
match current_let with
259271
| Some cl -> build_block cl (List.length args) Boxed_float lam letrec
260272
| None -> dead_code lam letrec)

ocaml/asmcomp/cmmgen.ml

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -122,18 +122,22 @@ let get_field env ptr n dbg =
122122
get_field_gen mut ptr n dbg
123123

124124
type rhs_kind =
125-
| RHS_block of int
126-
| RHS_infix of { blocksize : int; offset : int }
127-
| RHS_floatblock of int
125+
| RHS_block of Lambda.alloc_mode * int
126+
| RHS_infix of { blocksize : int; offset : int; blockmode: Lambda.alloc_mode }
127+
| RHS_floatblock of Lambda.alloc_mode * int
128128
| RHS_nonrec
129129
;;
130130

131131
let rec expr_size env = function
132132
| Uvar id ->
133133
begin try V.find_same id env with Not_found -> RHS_nonrec end
134134
| Uclosure { functions ; not_scanned_slots ; scanned_slots } ->
135-
RHS_block (fundecls_size functions + List.length not_scanned_slots
136-
+ List.length scanned_slots)
135+
(* should all have the same mode *)
136+
let fn_mode = (List.hd functions).mode in
137+
List.iter (fun f -> assert (Lambda.eq_mode fn_mode f.mode)) functions;
138+
RHS_block (fn_mode,
139+
fundecls_size functions + List.length not_scanned_slots
140+
+ List.length scanned_slots)
137141
| Ulet(_str, _kind, id, exp, body) ->
138142
expr_size (V.add (VP.var id) (expr_size env exp) env) body
139143
| Uletrec(bindings, body) ->
@@ -143,24 +147,24 @@ let rec expr_size env = function
143147
bindings env
144148
in
145149
expr_size env body
146-
| Uprim(Pmakeblock _, args, _) ->
147-
RHS_block (List.length args)
148-
| Uprim(Pmakearray((Paddrarray | Pintarray), _, _), args, _) ->
149-
RHS_block (List.length args)
150-
| Uprim(Pmakearray(Pfloatarray, _, _), args, _) ->
151-
RHS_floatblock (List.length args)
152-
| Uprim(Pmakearray(Pgenarray, _, _), _, _) ->
150+
| Uprim(Pmakeblock (_, _, _, mode), args, _) ->
151+
RHS_block (mode, List.length args)
152+
| Uprim(Pmakearray((Paddrarray | Pintarray), _, mode), args, _) ->
153+
RHS_block (mode, List.length args)
154+
| Uprim(Pmakearray(Pfloatarray, _, mode), args, _) ->
155+
RHS_floatblock (mode, List.length args)
156+
| Uprim(Pmakearray(Pgenarray, _, _mode), _, _) ->
153157
(* Pgenarray is excluded from recursive bindings by the
154158
check in Translcore.check_recursive_lambda *)
155159
RHS_nonrec
156160
| Uprim (Pduprecord ((Record_regular | Record_inlined _), sz), _, _) ->
157-
RHS_block sz
161+
RHS_block (Lambda.alloc_heap, sz)
158162
| Uprim (Pduprecord (Record_unboxed _, _), _, _) ->
159163
assert false
160164
| Uprim (Pduprecord (Record_extension _, sz), _, _) ->
161-
RHS_block (sz + 1)
165+
RHS_block (Lambda.alloc_heap, sz + 1)
162166
| Uprim (Pduprecord (Record_float, sz), _, _) ->
163-
RHS_floatblock sz
167+
RHS_floatblock (Lambda.alloc_heap, sz)
164168
| Uprim (Pccall { prim_name; _ }, closure::_, _)
165169
when prim_name = "caml_check_value_is_closure" ->
166170
(* Used for "-clambda-checks". *)
@@ -169,7 +173,8 @@ let rec expr_size env = function
169173
expr_size env exp'
170174
| Uoffset (exp, offset) ->
171175
(match expr_size env exp with
172-
| RHS_block blocksize -> RHS_infix { blocksize; offset }
176+
| RHS_block (blockmode, blocksize) ->
177+
RHS_infix { blocksize; offset; blockmode }
173178
| RHS_nonrec -> RHS_nonrec
174179
| _ -> assert false)
175180
| Uregion exp ->
@@ -1388,14 +1393,19 @@ and transl_letrec env bindings cont =
13881393
Cop(Cextcall(prim, typ_val, [], true), args, dbg) in
13891394
let rec init_blocks = function
13901395
| [] -> fill_nonrec bsz
1391-
| (id, _exp, RHS_block sz) :: rem ->
1396+
| (_, _,
1397+
(RHS_block (Alloc_local, _) |
1398+
RHS_infix {blockmode=Alloc_local; _} |
1399+
RHS_floatblock (Alloc_local, _))) :: _ ->
1400+
Misc.fatal_error "Invalid stack allocation found"
1401+
| (id, _exp, RHS_block (Alloc_heap, sz)) :: rem ->
13921402
Clet(id, op_alloc "caml_alloc_dummy" [int_const dbg sz],
13931403
init_blocks rem)
1394-
| (id, _exp, RHS_infix { blocksize; offset}) :: rem ->
1404+
| (id, _exp, RHS_infix { blocksize; offset; blockmode=Alloc_heap }) :: rem ->
13951405
Clet(id, op_alloc "caml_alloc_dummy_infix"
13961406
[int_const dbg blocksize; int_const dbg offset],
13971407
init_blocks rem)
1398-
| (id, _exp, RHS_floatblock sz) :: rem ->
1408+
| (id, _exp, RHS_floatblock (Alloc_heap, sz)) :: rem ->
13991409
Clet(id, op_alloc "caml_alloc_dummy_float" [int_const dbg sz],
14001410
init_blocks rem)
14011411
| (id, _exp, RHS_nonrec) :: rem ->

0 commit comments

Comments
 (0)