@@ -181,6 +181,8 @@ module Generate (Target : Target_sig.S) = struct
181181
182182 let zero_divide_pc = - 2
183183
184+ let exception_handler_pc = - 3
185+
184186 let rec translate_expr ctx context x e =
185187 match e with
186188 | Apply { f; args; exact }
@@ -198,17 +200,21 @@ module Generate (Target : Target_sig.S) = struct
198200 (load funct)
199201 in
200202 let * b = is_closure f in
203+ let label = label_index context exception_handler_pc in
201204 if b
202- then return (W. Call (f, List. rev (closure :: acc)))
205+ then return (W. Br_on_null (label, W. Call (f, List. rev (closure :: acc) )))
203206 else
204207 match funct with
205208 | W. RefFunc g ->
206209 (* Functions with constant closures ignore their
207210 environment. In case of partial application, we
208211 still need the closure. *)
209212 let * cl = if exact then Value. unit else return closure in
210- return (W. Call (g, List. rev (cl :: acc)))
211- | _ -> return (W. Call_ref (ty, funct, List. rev (closure :: acc))))
213+ return (W. Br_on_null (label, W. Call (g, List. rev (cl :: acc))))
214+ | _ ->
215+ return
216+ (W. Br_on_null
217+ (label, W. Call_ref (ty, funct, List. rev (closure :: acc)))))
212218 | x :: r ->
213219 let * x = load x in
214220 loop (x :: acc) r
@@ -220,7 +226,9 @@ module Generate (Target : Target_sig.S) = struct
220226 in
221227 let * args = expression_list load args in
222228 let * closure = load f in
223- return (W. Call (apply, args @ [ closure ]))
229+ return
230+ (W. Br_on_null
231+ (label_index context exception_handler_pc, W. Call (apply, args @ [ closure ])))
224232 | Block (tag , a , _ , _ ) ->
225233 Memory. allocate
226234 ~deadcode_sentinal: ctx.deadcode_sentinal
@@ -822,32 +830,55 @@ module Generate (Target : Target_sig.S) = struct
822830 { params = [] ; result = [] }
823831 (body ~result_typ: [] ~fall_through: (`Block pc) ~context: (`Block pc :: context))
824832 in
825- if List. is_empty result_typ
833+ if true && List. is_empty result_typ
826834 then handler
827835 else
828836 let * () = handler in
829- instr (W. Return (Some (RefI31 (Const (I32 0l )))))
837+ let * u = Value. unit in
838+ instr (W. Return (Some u))
830839 else body ~result_typ ~fall_through ~context
831840
832- let wrap_with_handlers p pc ~result_typ ~fall_through ~context body =
841+ let wrap_with_handlers ~ location p pc ~result_typ ~fall_through ~context body =
833842 let need_zero_divide_handler, need_bound_error_handler = needed_handlers p pc in
834843 wrap_with_handler
835- need_bound_error_handler
836- bound_error_pc
837- (let * f =
838- register_import ~name: " caml_bound_error" (Fun { params = [] ; result = [] })
839- in
840- instr (CallInstr (f, [] )))
844+ true
845+ exception_handler_pc
846+ (match location with
847+ | `Toplevel ->
848+ let * exn =
849+ register_import
850+ ~import_module: " env"
851+ ~name: " caml_exception"
852+ (Global { mut = true ; typ = Type. value })
853+ in
854+ let * tag = register_import ~name: exception_name (Tag Type. value) in
855+ instr (Throw (tag, GlobalGet exn ))
856+ | `Exception_handler ->
857+ let * exn =
858+ register_import
859+ ~import_module: " env"
860+ ~name: " caml_exception"
861+ (Global { mut = true ; typ = Type. value })
862+ in
863+ instr (Br (2 , Some (GlobalGet exn )))
864+ | `Function -> instr (Return (Some (RefNull Any ))))
841865 (wrap_with_handler
842- need_zero_divide_handler
843- zero_divide_pc
866+ need_bound_error_handler
867+ bound_error_pc
844868 (let * f =
845- register_import
846- ~name: " caml_raise_zero_divide"
847- (Fun { params = [] ; result = [] })
869+ register_import ~name: " caml_bound_error" (Fun { params = [] ; result = [] })
848870 in
849871 instr (CallInstr (f, [] )))
850- body)
872+ (wrap_with_handler
873+ need_zero_divide_handler
874+ zero_divide_pc
875+ (let * f =
876+ register_import
877+ ~name: " caml_raise_zero_divide"
878+ (Fun { params = [] ; result = [] })
879+ in
880+ instr (CallInstr (f, [] )))
881+ body))
851882 ~result_typ
852883 ~fall_through
853884 ~context
@@ -948,19 +979,34 @@ module Generate (Target : Target_sig.S) = struct
948979 instr (Br_table (e, List. map ~f: dest l, dest a.(len - 1 )))
949980 | Raise (x , _ ) -> (
950981 let * e = load x in
951- let * tag = register_import ~name: exception_name (Tag Type. value) in
952982 match fall_through with
953983 | `Catch -> instr (Push e)
954984 | `Block _ | `Return | `Skip -> (
955985 match catch_index context with
956986 | Some i -> instr (Br (i, Some e))
957- | None -> instr (Throw (tag, e))))
987+ | None ->
988+ if Option. is_some name_opt
989+ then
990+ let * exn =
991+ register_import
992+ ~import_module: " env"
993+ ~name: " caml_exception"
994+ (Global { mut = true ; typ = Type. value })
995+ in
996+ let * () = instr (GlobalSet (exn , e)) in
997+ instr (Return (Some (RefNull Any )))
998+ else
999+ let * tag =
1000+ register_import ~name: exception_name (Tag Type. value)
1001+ in
1002+ instr (Throw (tag, e))))
9581003 | Pushtrap (cont , x , cont' ) ->
9591004 handle_exceptions
9601005 ~result_typ
9611006 ~fall_through
9621007 ~context: (extend_context fall_through context)
9631008 (wrap_with_handlers
1009+ ~location: `Exception_handler
9641010 p
9651011 (fst cont)
9661012 (fun ~result_typ ~fall_through ~context ->
@@ -1031,6 +1077,10 @@ module Generate (Target : Target_sig.S) = struct
10311077 let * () = build_initial_env in
10321078 let * () =
10331079 wrap_with_handlers
1080+ ~location:
1081+ (match name_opt with
1082+ | None -> `Toplevel
1083+ | Some _ -> `Function )
10341084 p
10351085 pc
10361086 ~result_typ: [ Type. value ]
@@ -1079,7 +1129,9 @@ module Generate (Target : Target_sig.S) = struct
10791129 in
10801130 let * () = instr (Drop (Call (f, [] ))) in
10811131 cont)
1082- ~init: (instr (Push (RefI31 (Const (I32 0l )))))
1132+ ~init:
1133+ (let * u = Value. unit in
1134+ instr (Push u))
10831135 to_link)
10841136 in
10851137 context.other_fields < -
0 commit comments