@@ -24,25 +24,30 @@ let get_return ~tail i =
2424 | Push (LocalGet y ) when tail -> Some y
2525 | _ -> None
2626
27- let rewrite_tail_call ~y i =
27+ let rewrite_tail_call ~no_tail_call ~ y i =
2828 match i with
29- | Wasm_ast. LocalSet (x , Call (symb , l )) when Code.Var. equal x y ->
29+ | Wasm_ast. LocalSet (x, Call (symb, l))
30+ when Code.Var. equal x y && not (Code.Var.Hashtbl. mem no_tail_call symb) ->
3031 Some (Wasm_ast. Return_call (symb, l))
3132 | LocalSet (x , Call_ref (ty , e , l )) when Code.Var. equal x y ->
3233 Some (Return_call_ref (ty, e, l))
3334 | _ -> None
3435
35- let rec instruction ~tail i =
36+ let rec instruction ~no_tail_call ~ tail i =
3637 match i with
37- | Wasm_ast. Loop (ty , l ) -> Wasm_ast. Loop (ty, instructions ~tail l)
38- | Block (ty , l ) -> Block (ty, instructions ~tail l)
39- | If (ty , e , l1 , l2 ) -> If (ty, e, instructions ~tail l1, instructions ~tail l2)
40- | Return (Some (Call (symb , l ))) -> Return_call (symb, l)
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)
40+ | If (ty , e , l1 , l2 ) ->
41+ If (ty, e, instructions ~no_tail_call ~tail l1, instructions ~no_tail_call ~tail l2)
42+ | Return (Some (Call (symb , l ))) when not (Code.Var.Hashtbl. mem no_tail_call symb) ->
43+ Return_call (symb, l)
4144 | Return (Some (Call_ref (ty , e , l ))) -> Return_call_ref (ty, e, l)
42- | Push (Call (symb , l )) when tail -> Return_call (symb, l)
45+ | Push (Call (symb , l )) when tail && not (Code.Var.Hashtbl. mem no_tail_call symb) ->
46+ Return_call (symb, l)
4347 | Push (Call_ref (ty , e , l )) when tail -> Return_call_ref (ty, e, l)
4448 | Push (Call_ref _ ) -> i
45- | Drop (BlockExpr (typ , l )) -> Drop (BlockExpr (typ, instructions ~tail: false l))
49+ | Drop (BlockExpr (typ , l )) ->
50+ Drop (BlockExpr (typ, instructions ~no_tail_call ~tail: false l))
4651 | Drop _
4752 | LocalSet _
4853 | GlobalSet _
@@ -62,21 +67,28 @@ let rec instruction ~tail i =
6267 | Unreachable
6368 | Event _ -> i
6469
65- and instructions ~tail l =
70+ and instructions ~no_tail_call ~ tail l =
6671 match l with
6772 | [] -> []
68- | [ i ] -> [ instruction ~tail i ]
69- | i :: Nop :: rem -> instructions ~tail (i :: rem)
70- | i :: i' :: Nop :: rem -> instructions ~tail (i :: i' :: rem)
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)
7176 | i :: i' :: (([] | [ Event _ ]) as event_opt ) -> (
7277 (* There can be an event at the end of the function, which we
7378 should keep. *)
7479 match get_return ~tail i' with
75- | None -> instruction ~tail: false i :: instruction ~tail i' :: event_opt
80+ | None ->
81+ instruction ~no_tail_call ~tail: false i
82+ :: instruction ~no_tail_call ~tail i'
83+ :: event_opt
7684 | Some y -> (
77- match rewrite_tail_call ~y i with
78- | None -> instruction ~tail: false i :: instruction ~tail i' :: event_opt
85+ match rewrite_tail_call ~no_tail_call ~y i with
86+ | None ->
87+ instruction ~no_tail_call ~tail: false i
88+ :: instruction ~no_tail_call ~tail i'
89+ :: event_opt
7990 | Some i'' -> i'' :: event_opt))
80- | i :: rem -> instruction ~tail: false i :: instructions ~tail rem
91+ | i :: rem ->
92+ instruction ~no_tail_call ~tail: false i :: instructions ~no_tail_call ~tail rem
8193
82- let f l = instructions ~tail: true l
94+ let f ~ no_tail_call l = instructions ~no_tail_call ~tail: true l
0 commit comments