@@ -281,36 +281,41 @@ module Type = struct
281
281
})
282
282
env_type
283
283
284
- let env_type ~cps ~arity ~env_type_id ~env_type =
284
+ let env_type ~cps ~arity ~no_code_pointer ~ env_type_id ~env_type =
285
285
register_type
286
286
(if cps
287
287
then Printf. sprintf " cps_env_%d_%d" arity env_type_id
288
288
else Printf. sprintf " env_%d_%d" arity env_type_id)
289
289
(fun () ->
290
- let * cl_typ = closure_type ~usage: `Alloc ~cps arity in
291
- let * common = closure_common_fields ~cps in
292
- let * fun_ty' = function_type ~cps arity in
293
- return
294
- { supertype = Some cl_typ
295
- ; final = true
296
- ; typ =
297
- W. Struct
298
- ((if arity = 1
299
- then common
300
- else if arity = 0
301
- then
302
- [ { mut = false
303
- ; typ = Value (Ref { nullable = false ; typ = Type fun_ty' })
304
- }
305
- ]
306
- else
307
- common
308
- @ [ { mut = false
290
+ if no_code_pointer
291
+ then
292
+ return
293
+ { supertype = None ; final = true ; typ = W. Struct (make_env_type env_type) }
294
+ else
295
+ let * cl_typ = closure_type ~usage: `Alloc ~cps arity in
296
+ let * common = closure_common_fields ~cps in
297
+ let * fun_ty' = function_type ~cps arity in
298
+ return
299
+ { supertype = Some cl_typ
300
+ ; final = true
301
+ ; typ =
302
+ W. Struct
303
+ ((if arity = 1
304
+ then common
305
+ else if arity = 0
306
+ then
307
+ [ { mut = false
309
308
; typ = Value (Ref { nullable = false ; typ = Type fun_ty' })
310
309
}
311
- ])
312
- @ make_env_type env_type)
313
- })
310
+ ]
311
+ else
312
+ common
313
+ @ [ { mut = false
314
+ ; typ = Value (Ref { nullable = false ; typ = Type fun_ty' })
315
+ }
316
+ ])
317
+ @ make_env_type env_type)
318
+ })
314
319
315
320
let rec_env_type ~function_count ~env_type_id ~env_type =
316
321
register_type (Printf. sprintf " rec_env_%d_%d" function_count env_type_id) (fun () ->
@@ -328,34 +333,48 @@ module Type = struct
328
333
@ make_env_type env_type)
329
334
})
330
335
331
- let rec_closure_type ~cps ~arity ~function_count ~env_type_id ~env_type =
336
+ let rec_closure_type ~cps ~arity ~no_code_pointer ~function_count ~env_type_id ~env_type
337
+ =
332
338
register_type
333
339
(if cps
334
340
then Printf. sprintf " cps_closure_rec_%d_%d_%d" arity function_count env_type_id
335
341
else Printf. sprintf " closure_rec_%d_%d_%d" arity function_count env_type_id)
336
342
(fun () ->
337
- let * cl_typ = closure_type ~usage: `Alloc ~cps arity in
338
- let * common = closure_common_fields ~cps in
339
- let * fun_ty' = function_type ~cps arity in
340
343
let * env_ty = rec_env_type ~function_count ~env_type_id ~env_type in
341
- return
342
- { supertype = Some cl_typ
343
- ; final = true
344
- ; typ =
345
- W. Struct
346
- ((if arity = 1
347
- then common
348
- else
349
- common
350
- @ [ { mut = false
351
- ; typ = Value (Ref { nullable = false ; typ = Type fun_ty' })
352
- }
353
- ])
354
- @ [ { W. mut = false
344
+ if no_code_pointer
345
+ then
346
+ return
347
+ { supertype = None
348
+ ; final = true
349
+ ; typ =
350
+ W. Struct
351
+ [ { W. mut = false
355
352
; typ = W. Value (Ref { nullable = false ; typ = Type env_ty })
356
353
}
357
- ])
358
- })
354
+ ]
355
+ }
356
+ else
357
+ let * cl_typ = closure_type ~usage: `Alloc ~cps arity in
358
+ let * common = closure_common_fields ~cps in
359
+ let * fun_ty' = function_type ~cps arity in
360
+ return
361
+ { supertype = Some cl_typ
362
+ ; final = true
363
+ ; typ =
364
+ W. Struct
365
+ ((if arity = 1
366
+ then common
367
+ else
368
+ common
369
+ @ [ { mut = false
370
+ ; typ = Value (Ref { nullable = false ; typ = Type fun_ty' })
371
+ }
372
+ ])
373
+ @ [ { W. mut = false
374
+ ; typ = W. Value (Ref { nullable = false ; typ = Type env_ty })
375
+ }
376
+ ])
377
+ })
359
378
360
379
let rec curry_type ~cps arity m =
361
380
register_type
@@ -798,25 +817,35 @@ module Memory = struct
798
817
799
818
let set_field e idx e' = wasm_array_set e (Arith. const (Int32. of_int (idx + 1 ))) e'
800
819
801
- let env_start arity =
802
- match arity with
803
- | 0 | 1 -> 1
804
- | _ -> 2
820
+ let env_start ~no_code_pointer arity =
821
+ if no_code_pointer
822
+ then 0
823
+ else
824
+ match arity with
825
+ | 0 | 1 -> 1
826
+ | _ -> 2
805
827
806
828
let load_function_pointer ~cps ~arity ?(skip_cast = false ) closure =
807
829
let arity = if cps then arity - 1 else arity in
808
830
let * ty = Type. closure_type ~usage: `Access ~cps arity in
809
831
let * fun_ty = Type. function_type ~cps arity in
810
832
let casted_closure = if skip_cast then closure else wasm_cast ty closure in
811
- let * e = wasm_struct_get ty casted_closure (env_start arity - 1 ) in
833
+ let * e =
834
+ wasm_struct_get ty casted_closure (env_start ~no_code_pointer: false arity - 1 )
835
+ in
812
836
return (fun_ty, e)
813
837
814
838
let load_real_closure ~cps ~arity closure =
815
839
let arity = if cps then arity - 1 else arity in
816
840
let * ty = Type. dummy_closure_type ~cps ~arity in
817
841
let * cl_typ = Type. closure_type ~usage: `Access ~cps arity in
818
842
let * e =
819
- wasm_cast cl_typ (wasm_struct_get ty (wasm_cast ty closure) (env_start arity))
843
+ wasm_cast
844
+ cl_typ
845
+ (wasm_struct_get
846
+ ty
847
+ (wasm_cast ty closure)
848
+ (env_start ~no_code_pointer: false arity))
820
849
in
821
850
return (cl_typ, e)
822
851
@@ -1053,7 +1082,7 @@ module Closure = struct
1053
1082
| [ (g, _) ] -> Code.Var. equal f g
1054
1083
| _ :: r -> is_last_fun r f
1055
1084
1056
- let translate ~context ~closures ~cps f =
1085
+ let translate ~context ~closures ~cps ~ no_code_pointer f =
1057
1086
let info = Code.Var.Map. find f closures in
1058
1087
let free_variables = get_free_variables ~context info in
1059
1088
assert (
@@ -1062,23 +1091,29 @@ module Closure = struct
1062
1091
~f: (fun x -> Code.Var.Set. mem x context.globalized_variables)
1063
1092
free_variables));
1064
1093
let _, arity = List. find ~f: (fun (f' , _ ) -> Code.Var. equal f f') info.functions in
1065
- let arity = if cps then arity - 1 else arity in
1094
+ let arity = if no_code_pointer then 0 else if cps then arity - 1 else arity in
1066
1095
let * curry_fun = if arity > 1 then need_curry_fun ~cps ~arity else return f in
1067
1096
if List. is_empty free_variables
1068
1097
then
1069
- let * typ = Type. closure_type ~usage: `Alloc ~cps arity in
1070
- let name = Code.Var. fork f in
1071
- let * () =
1072
- register_global
1073
- name
1074
- { mut = false ; typ = Type. value }
1075
- (W. StructNew
1076
- ( typ
1077
- , match arity with
1078
- | 0 | 1 -> [ W. RefFunc f ]
1079
- | _ -> [ RefFunc curry_fun; RefFunc f ] ))
1080
- in
1081
- return (W. GlobalGet name)
1098
+ if no_code_pointer
1099
+ then Value. unit
1100
+ else
1101
+ let * typ = Type. closure_type ~usage: `Alloc ~cps arity in
1102
+ let name = Code.Var. fork f in
1103
+ let * () =
1104
+ register_global
1105
+ name
1106
+ { mut = false ; typ = Type. value }
1107
+ (W. StructNew
1108
+ ( typ
1109
+ , if no_code_pointer
1110
+ then []
1111
+ else
1112
+ match arity with
1113
+ | 0 | 1 -> [ W. RefFunc f ]
1114
+ | _ -> [ RefFunc curry_fun; RefFunc f ] ))
1115
+ in
1116
+ return (W. GlobalGet name)
1082
1117
else
1083
1118
let * env_type = expression_list variable_type free_variables in
1084
1119
let env_type_id =
@@ -1092,14 +1127,17 @@ module Closure = struct
1092
1127
match info.Closure_conversion. functions with
1093
1128
| [] -> assert false
1094
1129
| [ _ ] ->
1095
- let * typ = Type. env_type ~cps ~arity ~env_type_id ~env_type in
1130
+ let * typ = Type. env_type ~cps ~arity ~no_code_pointer ~ env_type_id ~env_type in
1096
1131
let * l = expression_list load free_variables in
1097
1132
return
1098
1133
(W. StructNew
1099
1134
( typ
1100
- , (match arity with
1101
- | 0 | 1 -> [ W. RefFunc f ]
1102
- | _ -> [ RefFunc curry_fun; RefFunc f ])
1135
+ , (if no_code_pointer
1136
+ then []
1137
+ else
1138
+ match arity with
1139
+ | 0 | 1 -> [ W. RefFunc f ]
1140
+ | _ -> [ RefFunc curry_fun; RefFunc f ])
1103
1141
@ l ))
1104
1142
| (g , _ ) :: _ as functions ->
1105
1143
let function_count = List. length functions in
@@ -1125,16 +1163,25 @@ module Closure = struct
1125
1163
load env
1126
1164
in
1127
1165
let * typ =
1128
- Type. rec_closure_type ~cps ~arity ~function_count ~env_type_id ~env_type
1166
+ Type. rec_closure_type
1167
+ ~cps
1168
+ ~arity
1169
+ ~no_code_pointer
1170
+ ~function_count
1171
+ ~env_type_id
1172
+ ~env_type
1129
1173
in
1130
1174
let res =
1131
1175
let * env = env in
1132
1176
return
1133
1177
(W. StructNew
1134
1178
( typ
1135
- , (if arity = 1
1136
- then [ W. RefFunc f ]
1137
- else [ RefFunc curry_fun; RefFunc f ])
1179
+ , (if no_code_pointer
1180
+ then []
1181
+ else
1182
+ match arity with
1183
+ | 0 | 1 -> [ W. RefFunc f ]
1184
+ | _ -> [ RefFunc curry_fun; RefFunc f ])
1138
1185
@ [ env ] ))
1139
1186
in
1140
1187
if is_last_fun functions f
@@ -1155,23 +1202,24 @@ module Closure = struct
1155
1202
(load f)
1156
1203
else res
1157
1204
1158
- let bind_environment ~context ~closures ~cps f =
1205
+ let bind_environment ~context ~closures ~cps ~ no_code_pointer f =
1159
1206
let info = Code.Var.Map. find f closures in
1160
1207
let free_variables = get_free_variables ~context info in
1161
- let free_variable_count = List. length free_variables in
1162
- if free_variable_count = 0
1208
+ if List. is_empty free_variables
1163
1209
then
1164
1210
(* The closures are all constants and the environment is empty. *)
1165
1211
let * _ = add_var (Code.Var. fresh () ) in
1166
1212
return ()
1167
1213
else
1168
1214
let env_type_id = Option. value ~default: (- 1 ) info.id in
1169
1215
let _, arity = List. find ~f: (fun (f' , _ ) -> Code.Var. equal f f') info.functions in
1170
- let arity = if cps then arity - 1 else arity in
1171
- let offset = Memory. env_start arity in
1216
+ let arity = if no_code_pointer then 0 else if cps then arity - 1 else arity in
1217
+ let offset = Memory. env_start ~no_code_pointer arity in
1172
1218
match info.Closure_conversion. functions with
1173
1219
| [ _ ] ->
1174
- let * typ = Type. env_type ~cps ~arity ~env_type_id ~env_type: [] in
1220
+ let * typ =
1221
+ Type. env_type ~cps ~arity ~no_code_pointer ~env_type_id ~env_type: []
1222
+ in
1175
1223
let * _ = add_var f in
1176
1224
let env = Code.Var. fresh_n " env" in
1177
1225
let * () =
@@ -1191,7 +1239,13 @@ module Closure = struct
1191
1239
| functions ->
1192
1240
let function_count = List. length functions in
1193
1241
let * typ =
1194
- Type. rec_closure_type ~cps ~arity ~function_count ~env_type_id ~env_type: []
1242
+ Type. rec_closure_type
1243
+ ~cps
1244
+ ~arity
1245
+ ~no_code_pointer
1246
+ ~function_count
1247
+ ~env_type_id
1248
+ ~env_type: []
1195
1249
in
1196
1250
let * _ = add_var f in
1197
1251
let env = Code.Var. fresh_n " env" in
@@ -1231,7 +1285,7 @@ module Closure = struct
1231
1285
else Type. curry_type ~cps arity (m + 1 )
1232
1286
in
1233
1287
let cast e = if m = 2 then Memory. wasm_cast ty e else e in
1234
- let offset = Memory. env_start 1 in
1288
+ let offset = Memory. env_start ~no_code_pointer: false 1 in
1235
1289
return
1236
1290
( Memory. wasm_struct_get ty (cast (load closure)) (offset + 1 )
1237
1291
, Memory. wasm_struct_get ty (cast (load closure)) offset
0 commit comments