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