@@ -181,6 +181,8 @@ module Generate (Target : Target_sig.S) = struct
181
181
182
182
let zero_divide_pc = - 2
183
183
184
+ let exception_handler_pc = - 3
185
+
184
186
let rec translate_expr ctx context x e =
185
187
match e with
186
188
| Apply { f; args; exact }
@@ -198,17 +200,21 @@ module Generate (Target : Target_sig.S) = struct
198
200
(load funct)
199
201
in
200
202
let * b = is_closure f in
203
+ let label = label_index context exception_handler_pc in
201
204
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) )))
203
206
else
204
207
match funct with
205
208
| W. RefFunc g ->
206
209
(* Functions with constant closures ignore their
207
210
environment. In case of partial application, we
208
211
still need the closure. *)
209
212
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)))))
212
218
| x :: r ->
213
219
let * x = load x in
214
220
loop (x :: acc) r
@@ -220,7 +226,9 @@ module Generate (Target : Target_sig.S) = struct
220
226
in
221
227
let * args = expression_list load args in
222
228
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 ])))
224
232
| Block (tag , a , _ , _ ) ->
225
233
Memory. allocate
226
234
~deadcode_sentinal: ctx.deadcode_sentinal
@@ -822,32 +830,55 @@ module Generate (Target : Target_sig.S) = struct
822
830
{ params = [] ; result = [] }
823
831
(body ~result_typ: [] ~fall_through: (`Block pc) ~context: (`Block pc :: context))
824
832
in
825
- if List. is_empty result_typ
833
+ if true && List. is_empty result_typ
826
834
then handler
827
835
else
828
836
let * () = handler in
829
- instr (W. Return (Some (RefI31 (Const (I32 0l )))))
837
+ let * u = Value. unit in
838
+ instr (W. Return (Some u))
830
839
else body ~result_typ ~fall_through ~context
831
840
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 =
833
842
let need_zero_divide_handler, need_bound_error_handler = needed_handlers p pc in
834
843
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 ))))
841
865
(wrap_with_handler
842
- need_zero_divide_handler
843
- zero_divide_pc
866
+ need_bound_error_handler
867
+ bound_error_pc
844
868
(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 = [] })
848
870
in
849
871
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))
851
882
~result_typ
852
883
~fall_through
853
884
~context
@@ -948,19 +979,34 @@ module Generate (Target : Target_sig.S) = struct
948
979
instr (Br_table (e, List. map ~f: dest l, dest a.(len - 1 )))
949
980
| Raise (x , _ ) -> (
950
981
let * e = load x in
951
- let * tag = register_import ~name: exception_name (Tag Type. value) in
952
982
match fall_through with
953
983
| `Catch -> instr (Push e)
954
984
| `Block _ | `Return | `Skip -> (
955
985
match catch_index context with
956
986
| 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))))
958
1003
| Pushtrap (cont , x , cont' ) ->
959
1004
handle_exceptions
960
1005
~result_typ
961
1006
~fall_through
962
1007
~context: (extend_context fall_through context)
963
1008
(wrap_with_handlers
1009
+ ~location: `Exception_handler
964
1010
p
965
1011
(fst cont)
966
1012
(fun ~result_typ ~fall_through ~context ->
@@ -1031,6 +1077,10 @@ module Generate (Target : Target_sig.S) = struct
1031
1077
let * () = build_initial_env in
1032
1078
let * () =
1033
1079
wrap_with_handlers
1080
+ ~location:
1081
+ (match name_opt with
1082
+ | None -> `Toplevel
1083
+ | Some _ -> `Function )
1034
1084
p
1035
1085
pc
1036
1086
~result_typ: [ Type. value ]
@@ -1079,7 +1129,9 @@ module Generate (Target : Target_sig.S) = struct
1079
1129
in
1080
1130
let * () = instr (Drop (Call (f, [] ))) in
1081
1131
cont)
1082
- ~init: (instr (Push (RefI31 (Const (I32 0l )))))
1132
+ ~init:
1133
+ (let * u = Value. unit in
1134
+ instr (Push u))
1083
1135
to_link)
1084
1136
in
1085
1137
context.other_fields < -
0 commit comments