@@ -782,6 +782,8 @@ module Generate (Target : Target_sig.S) = struct
782782 in
783783 Memory. allocate ~tag: 0 ~deadcode_sentinal: ctx.deadcode_sentinal ~load l)
784784
785+ let exception_handler_pc = - 3
786+
785787 let rec translate_expr ctx context x e =
786788 match e with
787789 | Apply { f; args; exact }
@@ -799,17 +801,21 @@ module Generate (Target : Target_sig.S) = struct
799801 (load funct)
800802 in
801803 let * b = is_closure f in
804+ let label = label_index context exception_handler_pc in
802805 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) )))
804807 else
805808 match funct with
806809 | W. RefFunc g ->
807810 (* Functions with constant closures ignore their
808811 environment. In case of partial application, we
809812 still need the closure. *)
810813 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)))))
813819 | x :: r ->
814820 let * x = load_and_box ctx x in
815821 loop (x :: acc) r
@@ -821,7 +827,9 @@ module Generate (Target : Target_sig.S) = struct
821827 in
822828 let * args = expression_list (fun x -> load_and_box ctx x) args in
823829 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 ])))
825833 | Block (tag , a , _ , _ ) ->
826834 Memory. allocate
827835 ~deadcode_sentinal: ctx.deadcode_sentinal
@@ -1075,32 +1083,55 @@ module Generate (Target : Target_sig.S) = struct
10751083 { params = [] ; result = [] }
10761084 (body ~result_typ: [] ~fall_through: (`Block pc) ~context: (`Block pc :: context))
10771085 in
1078- if List. is_empty result_typ
1086+ if true && List. is_empty result_typ
10791087 then handler
10801088 else
10811089 let * () = handler in
1082- instr (W. Return (Some (RefI31 (Const (I32 0l )))))
1090+ let * u = Value. unit in
1091+ instr (W. Return (Some u))
10831092 else body ~result_typ ~fall_through ~context
10841093
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 =
10861095 let need_zero_divide_handler, need_bound_error_handler = needed_handlers p pc in
10871096 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 ))))
10941118 (wrap_with_handler
1095- need_zero_divide_handler
1096- zero_divide_pc
1119+ need_bound_error_handler
1120+ bound_error_pc
10971121 (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 = [] })
11011123 in
11021124 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))
11041135 ~result_typ
11051136 ~fall_through
11061137 ~context
@@ -1208,19 +1239,34 @@ module Generate (Target : Target_sig.S) = struct
12081239 instr (Br_table (e, List. map ~f: dest l, dest a.(len - 1 )))
12091240 | Raise (x , _ ) -> (
12101241 let * e = load x in
1211- let * tag = register_import ~name: exception_name (Tag Type. value) in
12121242 match fall_through with
12131243 | `Catch -> instr (Push e)
12141244 | `Block _ | `Return | `Skip -> (
12151245 match catch_index context with
12161246 | 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))))
12181263 | Pushtrap (cont , x , cont' ) ->
12191264 handle_exceptions
12201265 ~result_typ
12211266 ~fall_through
12221267 ~context: (extend_context fall_through context)
12231268 (wrap_with_handlers
1269+ ~location: `Exception_handler
12241270 p
12251271 (fst cont)
12261272 (fun ~result_typ ~fall_through ~context ->
@@ -1291,6 +1337,10 @@ module Generate (Target : Target_sig.S) = struct
12911337 let * () = build_initial_env in
12921338 let * () =
12931339 wrap_with_handlers
1340+ ~location:
1341+ (match name_opt with
1342+ | None -> `Toplevel
1343+ | Some _ -> `Function )
12941344 p
12951345 pc
12961346 ~result_typ: [ Type. value ]
@@ -1342,7 +1392,9 @@ module Generate (Target : Target_sig.S) = struct
13421392 in
13431393 let * () = instr (Drop (Call (f, [] ))) in
13441394 cont)
1345- ~init: (instr (Push (RefI31 (Const (I32 0l )))))
1395+ ~init:
1396+ (let * u = Value. unit in
1397+ instr (Push u))
13461398 to_link)
13471399 in
13481400 context.other_fields < -
0 commit comments