@@ -24,30 +24,46 @@ let get_return ~tail i =
24
24
| Push (LocalGet y ) when tail -> Some y
25
25
| _ -> None
26
26
27
- let rewrite_tail_call ~no_tail_call ~y i =
27
+ let rewrite_tail_call ~return_exn ~ no_tail_call ~y i =
28
28
match i with
29
29
| Wasm_ast. LocalSet (x, Call (symb, l))
30
30
when Code.Var. equal x y && not (Code.Var.Hashtbl. mem no_tail_call symb) ->
31
31
Some (Wasm_ast. Return_call (symb, l))
32
32
| LocalSet (x , Call_ref (ty , e , l )) when Code.Var. equal x y ->
33
33
Some (Return_call_ref (ty, e, l))
34
+ | LocalSet (x , Br_on_null (_ , Call (symb , l ))) when return_exn && Code.Var. equal x y ->
35
+ Some (Wasm_ast. Return_call (symb, l))
36
+ | LocalSet (x, Br_on_null (_, Call_ref (ty, e, l)))
37
+ when return_exn && Code.Var. equal x y -> Some (Return_call_ref (ty, e, l))
34
38
| _ -> None
35
39
36
- let rec instruction ~no_tail_call ~tail i =
40
+ let rec instruction ~return_exn ~ no_tail_call ~tail i =
37
41
match i with
38
- | Wasm_ast. Loop (ty , l ) -> Wasm_ast. Loop (ty, instructions ~no_tail_call ~tail l)
39
- | Block (ty , l ) -> Block (ty, instructions ~no_tail_call ~tail l)
42
+ | Wasm_ast. Loop (ty , l ) ->
43
+ Wasm_ast. Loop (ty, instructions ~return_exn ~no_tail_call ~tail l)
44
+ | Block (ty , l ) -> Block (ty, instructions ~return_exn ~no_tail_call ~tail l)
40
45
| If (ty , e , l1 , l2 ) ->
41
- If (ty, e, instructions ~no_tail_call ~tail l1, instructions ~no_tail_call ~tail l2)
46
+ If
47
+ ( ty
48
+ , e
49
+ , instructions ~return_exn ~no_tail_call ~tail l1
50
+ , instructions ~return_exn ~no_tail_call ~tail l2 )
42
51
| Return (Some (Call (symb , l ))) when not (Code.Var.Hashtbl. mem no_tail_call symb) ->
43
52
Return_call (symb, l)
44
53
| Return (Some (Call_ref (ty , e , l ))) -> Return_call_ref (ty, e, l)
45
54
| Push (Call (symb , l )) when tail && not (Code.Var.Hashtbl. mem no_tail_call symb) ->
46
55
Return_call (symb, l)
47
56
| Push (Call_ref (ty , e , l )) when tail -> Return_call_ref (ty, e, l)
48
57
| Push (Call_ref _ ) -> i
58
+ | Return (Some (Br_on_null (_ , Call (symb , l )))) when return_exn -> Return_call (symb, l)
59
+ | Return (Some (Br_on_null (_ , Call_ref (ty , e , l )))) when return_exn ->
60
+ Return_call_ref (ty, e, l)
61
+ | Push (Br_on_null (_ , Call (symb , l ))) when return_exn && tail -> Return_call (symb, l)
62
+ | Push (Br_on_null (_ , Call_ref (ty , e , l ))) when return_exn && tail ->
63
+ Return_call_ref (ty, e, l)
64
+ | Push (Br_on_null (_ , Call_ref _ )) when return_exn -> i
49
65
| Drop (BlockExpr (typ , l )) ->
50
- Drop (BlockExpr (typ, instructions ~no_tail_call ~tail: false l))
66
+ Drop (BlockExpr (typ, instructions ~return_exn ~ no_tail_call ~tail: false l))
51
67
| Drop _
52
68
| LocalSet _
53
69
| GlobalSet _
@@ -67,28 +83,29 @@ let rec instruction ~no_tail_call ~tail i =
67
83
| Unreachable
68
84
| Event _ -> i
69
85
70
- and instructions ~no_tail_call ~tail l =
86
+ and instructions ~return_exn ~ no_tail_call ~tail l =
71
87
match l with
72
88
| [] -> []
73
- | [ i ] -> [ instruction ~no_tail_call ~tail i ]
74
- | i :: Nop :: rem -> instructions ~no_tail_call ~tail (i :: rem)
75
- | i :: i' :: Nop :: rem -> instructions ~no_tail_call ~tail (i :: i' :: rem)
89
+ | [ i ] -> [ instruction ~return_exn ~ no_tail_call ~tail i ]
90
+ | i :: Nop :: rem -> instructions ~return_exn ~ no_tail_call ~tail (i :: rem)
91
+ | i :: i' :: Nop :: rem -> instructions ~return_exn ~ no_tail_call ~tail (i :: i' :: rem)
76
92
| i :: i' :: (([] | [ Event _ ]) as event_opt ) -> (
77
93
(* There can be an event at the end of the function, which we
78
94
should keep. *)
79
95
match get_return ~tail i' with
80
96
| None ->
81
- instruction ~no_tail_call ~tail: false i
82
- :: instruction ~no_tail_call ~tail i'
97
+ instruction ~return_exn ~ no_tail_call ~tail: false i
98
+ :: instruction ~return_exn ~ no_tail_call ~tail i'
83
99
:: event_opt
84
100
| Some y -> (
85
- match rewrite_tail_call ~no_tail_call ~y i with
101
+ match rewrite_tail_call ~return_exn ~ no_tail_call ~y i with
86
102
| None ->
87
- instruction ~no_tail_call ~tail: false i
88
- :: instruction ~no_tail_call ~tail i'
103
+ instruction ~return_exn ~ no_tail_call ~tail: false i
104
+ :: instruction ~return_exn ~ no_tail_call ~tail i'
89
105
:: event_opt
90
106
| Some i'' -> i'' :: event_opt))
91
107
| i :: rem ->
92
- instruction ~no_tail_call ~tail: false i :: instructions ~no_tail_call ~tail rem
108
+ instruction ~return_exn ~no_tail_call ~tail: false i
109
+ :: instructions ~return_exn ~no_tail_call ~tail rem
93
110
94
- let f ~no_tail_call l = instructions ~no_tail_call ~tail: true l
111
+ let f ~return_exn ~ no_tail_call l = instructions ~return_exn ~no_tail_call ~tail: true l
0 commit comments