@@ -183,6 +183,8 @@ module Generate (Target : Target_sig.S) = struct
183183
184184 let zero_divide_pc = - 2
185185
186+ let exception_handler_pc = - 3
187+
186188 let rec translate_expr ctx context x e =
187189 match e with
188190 | Apply { f; args; exact }
@@ -200,17 +202,21 @@ module Generate (Target : Target_sig.S) = struct
200202 (load funct)
201203 in
202204 let * b = is_closure f in
205+ let label = label_index context exception_handler_pc in
203206 if b
204- then return (W. Call (f, List. rev (closure :: acc)))
207+ then return (W. Br_on_null (label, W. Call (f, List. rev (closure :: acc) )))
205208 else
206209 match funct with
207210 | W. RefFunc g ->
208211 (* Functions with constant closures ignore their
209212 environment. In case of partial application, we
210213 still need the closure. *)
211214 let * cl = if exact then Value. unit else return closure in
212- return (W. Call (g, List. rev (cl :: acc)))
213- | _ -> return (W. Call_ref (ty, funct, List. rev (closure :: acc))))
215+ return (W. Br_on_null (label, W. Call (g, List. rev (cl :: acc))))
216+ | _ ->
217+ return
218+ (W. Br_on_null
219+ (label, W. Call_ref (ty, funct, List. rev (closure :: acc)))))
214220 | x :: r ->
215221 let * x = load x in
216222 loop (x :: acc) r
@@ -222,7 +228,9 @@ module Generate (Target : Target_sig.S) = struct
222228 in
223229 let * args = expression_list load args in
224230 let * closure = load f in
225- return (W. Call (apply, args @ [ closure ]))
231+ return
232+ (W. Br_on_null
233+ (label_index context exception_handler_pc, W. Call (apply, args @ [ closure ])))
226234 | Block (tag , a , _ , _ ) ->
227235 Memory. allocate
228236 ~deadcode_sentinal: ctx.deadcode_sentinal
@@ -824,32 +832,55 @@ module Generate (Target : Target_sig.S) = struct
824832 { params = [] ; result = [] }
825833 (body ~result_typ: [] ~fall_through: (`Block pc) ~context: (`Block pc :: context))
826834 in
827- if List. is_empty result_typ
835+ if true && List. is_empty result_typ
828836 then handler
829837 else
830838 let * () = handler in
831- instr (W. Return (Some (RefI31 (Const (I32 0l )))))
839+ let * u = Value. unit in
840+ instr (W. Return (Some u))
832841 else body ~result_typ ~fall_through ~context
833842
834- let wrap_with_handlers p pc ~result_typ ~fall_through ~context body =
843+ let wrap_with_handlers ~ location p pc ~result_typ ~fall_through ~context body =
835844 let need_zero_divide_handler, need_bound_error_handler = needed_handlers p pc in
836845 wrap_with_handler
837- need_bound_error_handler
838- bound_error_pc
839- (let * f =
840- register_import ~name: " caml_bound_error" (Fun { params = [] ; result = [] })
841- in
842- instr (CallInstr (f, [] )))
846+ true
847+ exception_handler_pc
848+ (match location with
849+ | `Toplevel ->
850+ let * exn =
851+ register_import
852+ ~import_module: " env"
853+ ~name: " caml_exception"
854+ (Global { mut = true ; typ = Type. value })
855+ in
856+ let * tag = register_import ~name: exception_name (Tag Type. value) in
857+ instr (Throw (tag, GlobalGet exn ))
858+ | `Exception_handler ->
859+ let * exn =
860+ register_import
861+ ~import_module: " env"
862+ ~name: " caml_exception"
863+ (Global { mut = true ; typ = Type. value })
864+ in
865+ instr (Br (2 , Some (GlobalGet exn )))
866+ | `Function -> instr (Return (Some (RefNull Any ))))
843867 (wrap_with_handler
844- need_zero_divide_handler
845- zero_divide_pc
868+ need_bound_error_handler
869+ bound_error_pc
846870 (let * f =
847- register_import
848- ~name: " caml_raise_zero_divide"
849- (Fun { params = [] ; result = [] })
871+ register_import ~name: " caml_bound_error" (Fun { params = [] ; result = [] })
850872 in
851873 instr (CallInstr (f, [] )))
852- body)
874+ (wrap_with_handler
875+ need_zero_divide_handler
876+ zero_divide_pc
877+ (let * f =
878+ register_import
879+ ~name: " caml_raise_zero_divide"
880+ (Fun { params = [] ; result = [] })
881+ in
882+ instr (CallInstr (f, [] )))
883+ body))
853884 ~result_typ
854885 ~fall_through
855886 ~context
@@ -950,19 +981,34 @@ module Generate (Target : Target_sig.S) = struct
950981 instr (Br_table (e, List. map ~f: dest l, dest a.(len - 1 )))
951982 | Raise (x , _ ) -> (
952983 let * e = load x in
953- let * tag = register_import ~name: exception_name (Tag Type. value) in
954984 match fall_through with
955985 | `Catch -> instr (Push e)
956986 | `Block _ | `Return | `Skip -> (
957987 match catch_index context with
958988 | Some i -> instr (Br (i, Some e))
959- | None -> instr (Throw (tag, e))))
989+ | None ->
990+ if Option. is_some name_opt
991+ then
992+ let * exn =
993+ register_import
994+ ~import_module: " env"
995+ ~name: " caml_exception"
996+ (Global { mut = true ; typ = Type. value })
997+ in
998+ let * () = instr (GlobalSet (exn , e)) in
999+ instr (Return (Some (RefNull Any )))
1000+ else
1001+ let * tag =
1002+ register_import ~name: exception_name (Tag Type. value)
1003+ in
1004+ instr (Throw (tag, e))))
9601005 | Pushtrap (cont , x , cont' ) ->
9611006 handle_exceptions
9621007 ~result_typ
9631008 ~fall_through
9641009 ~context: (extend_context fall_through context)
9651010 (wrap_with_handlers
1011+ ~location: `Exception_handler
9661012 p
9671013 (fst cont)
9681014 (fun ~result_typ ~fall_through ~context ->
@@ -1033,6 +1079,10 @@ module Generate (Target : Target_sig.S) = struct
10331079 let * () = build_initial_env in
10341080 let * () =
10351081 wrap_with_handlers
1082+ ~location:
1083+ (match name_opt with
1084+ | None -> `Toplevel
1085+ | Some _ -> `Function )
10361086 p
10371087 pc
10381088 ~result_typ: [ Type. value ]
@@ -1081,7 +1131,9 @@ module Generate (Target : Target_sig.S) = struct
10811131 in
10821132 let * () = instr (Drop (Call (f, [] ))) in
10831133 cont)
1084- ~init: (instr (Push (RefI31 (Const (I32 0l )))))
1134+ ~init:
1135+ (let * u = Value. unit in
1136+ instr (Push u))
10851137 to_link)
10861138 in
10871139 context.other_fields < -
0 commit comments