@@ -782,6 +782,8 @@ module Generate (Target : Target_sig.S) = struct
782
782
in
783
783
Memory. allocate ~tag: 0 ~deadcode_sentinal: ctx.deadcode_sentinal ~load l)
784
784
785
+ let exception_handler_pc = - 3
786
+
785
787
let rec translate_expr ctx context x e =
786
788
match e with
787
789
| Apply { f; args; exact }
@@ -799,17 +801,21 @@ module Generate (Target : Target_sig.S) = struct
799
801
(load funct)
800
802
in
801
803
let * b = is_closure f in
804
+ let label = label_index context exception_handler_pc in
802
805
if b
803
- then return (W. Call (f, List. rev (closure :: acc)))
806
+ then return (W. Br_on_null (label, W. Call (f, List. rev (closure :: acc) )))
804
807
else
805
808
match funct with
806
809
| W. RefFunc g ->
807
810
(* Functions with constant closures ignore their
808
811
environment. In case of partial application, we
809
812
still need the closure. *)
810
813
let * cl = if exact then Value. unit else return closure in
811
- return (W. Call (g, List. rev (cl :: acc)))
812
- | _ -> return (W. Call_ref (ty, funct, List. rev (closure :: acc))))
814
+ return (W. Br_on_null (label, W. Call (g, List. rev (cl :: acc))))
815
+ | _ ->
816
+ return
817
+ (W. Br_on_null
818
+ (label, W. Call_ref (ty, funct, List. rev (closure :: acc)))))
813
819
| x :: r ->
814
820
let * x = load_and_box ctx x in
815
821
loop (x :: acc) r
@@ -821,7 +827,9 @@ module Generate (Target : Target_sig.S) = struct
821
827
in
822
828
let * args = expression_list (fun x -> load_and_box ctx x) args in
823
829
let * closure = load f in
824
- return (W. Call (apply, args @ [ closure ]))
830
+ return
831
+ (W. Br_on_null
832
+ (label_index context exception_handler_pc, W. Call (apply, args @ [ closure ])))
825
833
| Block (tag , a , _ , _ ) ->
826
834
Memory. allocate
827
835
~deadcode_sentinal: ctx.deadcode_sentinal
@@ -1075,32 +1083,55 @@ module Generate (Target : Target_sig.S) = struct
1075
1083
{ params = [] ; result = [] }
1076
1084
(body ~result_typ: [] ~fall_through: (`Block pc) ~context: (`Block pc :: context))
1077
1085
in
1078
- if List. is_empty result_typ
1086
+ if true && List. is_empty result_typ
1079
1087
then handler
1080
1088
else
1081
1089
let * () = handler in
1082
- instr (W. Return (Some (RefI31 (Const (I32 0l )))))
1090
+ let * u = Value. unit in
1091
+ instr (W. Return (Some u))
1083
1092
else body ~result_typ ~fall_through ~context
1084
1093
1085
- let wrap_with_handlers p pc ~result_typ ~fall_through ~context body =
1094
+ let wrap_with_handlers ~ location p pc ~result_typ ~fall_through ~context body =
1086
1095
let need_zero_divide_handler, need_bound_error_handler = needed_handlers p pc in
1087
1096
wrap_with_handler
1088
- need_bound_error_handler
1089
- bound_error_pc
1090
- (let * f =
1091
- register_import ~name: " caml_bound_error" (Fun { params = [] ; result = [] })
1092
- in
1093
- instr (CallInstr (f, [] )))
1097
+ true
1098
+ exception_handler_pc
1099
+ (match location with
1100
+ | `Toplevel ->
1101
+ let * exn =
1102
+ register_import
1103
+ ~import_module: " env"
1104
+ ~name: " caml_exception"
1105
+ (Global { mut = true ; typ = Type. value })
1106
+ in
1107
+ let * tag = register_import ~name: exception_name (Tag Type. value) in
1108
+ instr (Throw (tag, GlobalGet exn ))
1109
+ | `Exception_handler ->
1110
+ let * exn =
1111
+ register_import
1112
+ ~import_module: " env"
1113
+ ~name: " caml_exception"
1114
+ (Global { mut = true ; typ = Type. value })
1115
+ in
1116
+ instr (Br (2 , Some (GlobalGet exn )))
1117
+ | `Function -> instr (Return (Some (RefNull Any ))))
1094
1118
(wrap_with_handler
1095
- need_zero_divide_handler
1096
- zero_divide_pc
1119
+ need_bound_error_handler
1120
+ bound_error_pc
1097
1121
(let * f =
1098
- register_import
1099
- ~name: " caml_raise_zero_divide"
1100
- (Fun { params = [] ; result = [] })
1122
+ register_import ~name: " caml_bound_error" (Fun { params = [] ; result = [] })
1101
1123
in
1102
1124
instr (CallInstr (f, [] )))
1103
- body)
1125
+ (wrap_with_handler
1126
+ need_zero_divide_handler
1127
+ zero_divide_pc
1128
+ (let * f =
1129
+ register_import
1130
+ ~name: " caml_raise_zero_divide"
1131
+ (Fun { params = [] ; result = [] })
1132
+ in
1133
+ instr (CallInstr (f, [] )))
1134
+ body))
1104
1135
~result_typ
1105
1136
~fall_through
1106
1137
~context
@@ -1208,19 +1239,34 @@ module Generate (Target : Target_sig.S) = struct
1208
1239
instr (Br_table (e, List. map ~f: dest l, dest a.(len - 1 )))
1209
1240
| Raise (x , _ ) -> (
1210
1241
let * e = load x in
1211
- let * tag = register_import ~name: exception_name (Tag Type. value) in
1212
1242
match fall_through with
1213
1243
| `Catch -> instr (Push e)
1214
1244
| `Block _ | `Return | `Skip -> (
1215
1245
match catch_index context with
1216
1246
| Some i -> instr (Br (i, Some e))
1217
- | None -> instr (Throw (tag, e))))
1247
+ | None ->
1248
+ if Option. is_some name_opt
1249
+ then
1250
+ let * exn =
1251
+ register_import
1252
+ ~import_module: " env"
1253
+ ~name: " caml_exception"
1254
+ (Global { mut = true ; typ = Type. value })
1255
+ in
1256
+ let * () = instr (GlobalSet (exn , e)) in
1257
+ instr (Return (Some (RefNull Any )))
1258
+ else
1259
+ let * tag =
1260
+ register_import ~name: exception_name (Tag Type. value)
1261
+ in
1262
+ instr (Throw (tag, e))))
1218
1263
| Pushtrap (cont , x , cont' ) ->
1219
1264
handle_exceptions
1220
1265
~result_typ
1221
1266
~fall_through
1222
1267
~context: (extend_context fall_through context)
1223
1268
(wrap_with_handlers
1269
+ ~location: `Exception_handler
1224
1270
p
1225
1271
(fst cont)
1226
1272
(fun ~result_typ ~fall_through ~context ->
@@ -1291,6 +1337,10 @@ module Generate (Target : Target_sig.S) = struct
1291
1337
let * () = build_initial_env in
1292
1338
let * () =
1293
1339
wrap_with_handlers
1340
+ ~location:
1341
+ (match name_opt with
1342
+ | None -> `Toplevel
1343
+ | Some _ -> `Function )
1294
1344
p
1295
1345
pc
1296
1346
~result_typ: [ Type. value ]
@@ -1342,7 +1392,9 @@ module Generate (Target : Target_sig.S) = struct
1342
1392
in
1343
1393
let * () = instr (Drop (Call (f, [] ))) in
1344
1394
cont)
1345
- ~init: (instr (Push (RefI31 (Const (I32 0l )))))
1395
+ ~init:
1396
+ (let * u = Value. unit in
1397
+ instr (Push u))
1346
1398
to_link)
1347
1399
in
1348
1400
context.other_fields < -
0 commit comments