Skip to content

Commit b3380e3

Browse files
authored
Update Overview
1 parent 125201c commit b3380e3

File tree

1 file changed

+30
-36
lines changed

1 file changed

+30
-36
lines changed

proposals/tail-call/Overview.md

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ This can be applied to any form of call, that is:
2727

2828
### Instructions
2929

30-
* Tail calls should be separate, explicit call instructions (current instructions explicitly disallow TCE)
30+
* Tail calls are performed via separate, explicit call instructions (existing call instructions explicitly disallow TCE)
3131

32-
* Two possible schemes:
33-
1. introduce tail version of every call instruction
34-
2. introduce single prefix instruction that can be applied to every call instruction
32+
* The proposal thus introduces a tail version of every call instruction
3533

36-
* Consideration: WebAssembly will likely get more call instructions in the future, e.g., `call_ref`
34+
* An alternative scheme introducing a single instruction prefix applicable to every call instruction was considered but rejected by the CG
35+
- considerations: WebAssembly will likely get a few more call instructions in the future, e.g., `call_ref`
36+
- but instruction prefixes as modifiers re not used anywhere else in Wasm
3737

3838

3939
### Execution
@@ -44,61 +44,64 @@ This can be applied to any form of call, that is:
4444

4545
* Only keeps the necessary call arguments
4646

47+
* Tail calls to host functions cannot guarantee tail behaviour (outside the scope of the spec)
48+
4749

4850
### Typing
4951

50-
* Because tail calls transfer control and unwind the stack they are stack-polymorphic:
52+
* Typing rule for tail call instruction is derived by their nature of merging call and return
53+
54+
* Because tail calls transfer control and unwind the stack they are stack-polymorphic
5155

52-
* Open question: distinguish tail-calls in function type? Possibilities:
56+
* Previously open question: should tail calls induce different function types? Possibilities:
5357
1. Distinguish tail-callees by type
5458
2. Distinguish tail-callers by type
5559
3. Both
5660
4. Neither
5761

5862
* Considerations:
59-
- Option 1 (and 3) allows different calling conventions for non-tail-callable functions, which may be reduce constraints on ABIs.
63+
- Option 1 (and 3) allows different calling conventions for non-tail-callable functions, which may reduce constraints on ABIs.
6064
- On the other hand, it creates a bifurcated function space, which can lead to difficulties e.g. when using function tables or other forms of dynamic indirection.
61-
- Benefit of option 2 (and 3) unclear.
65+
- Benefit of option 2 (and thus 3) unclear.
66+
- Experimental validation revealed that there isn't a notable performance benefit to option 1 either.
67+
68+
* CG resolution was to go with option 4 as the conceptually simplest.
6269

6370

6471
## Examples
6572

6673
A simple boring example of a tail-recursive factorial funciton.
6774
```
6875
(func $fac (param $x i64) (result i64)
69-
(return_call $fac-aux (get_local $x) (i64.const 1))
76+
(return_call $fac-aux (get_local $x) (i64.const 1))
7077
)
7178
7279
(func $fac-aux (param $x i64) (param $r i64) (result i64)
73-
(if (i64.eqz (get_local $x))
74-
(then (return (get_local $r)))
75-
(else
76-
(return_call $fac-aux
77-
(i64.sub (get_local $x) (i64.const 1))
78-
(i64.mul (get_local $x) (get_local $r))
79-
)
80-
)
81-
)
80+
(if (i64.eqz (get_local $x))
81+
(then (return (get_local $r)))
82+
(else
83+
(return_call $fac-aux
84+
(i64.sub (get_local $x) (i64.const 1))
85+
(i64.mul (get_local $x) (get_local $r))
86+
)
87+
)
88+
)
8289
)
8390
8491
```
8592

8693

8794
## Spec Changes
8895

89-
For now, we assume that separate instructions are introduced.
90-
It is not difficult to adapt the rules to an alternative design with instruction prefixes.
91-
92-
The details of possible typing refinements to distinguish tail-callers/callees are to be discussed and not yet included.
93-
94-
9596
### Structure
9697

97-
Add two instructions (for now):
98+
Add two instructions:
9899

99100
* `return_call <funcidx>`, the tail-call version of `call`
100101
* `return_call_indirect <tableidx> <typeidx>`, the tail-call version of `call_indirect`
101102

103+
Other language extensions like [typed function refereces](https://github.com/WebAssembly/function-references/blob/master/proposals/function-references/Overview.md) that introduce new call instructions will also introduce tail versions of these new instructions.
104+
102105

103106
### Validation
104107

@@ -142,13 +145,4 @@ The text format is extended with two new instructions in the obvious manner.
142145

143146
## Open Questions
144147

145-
* Which instruction scheme should be picked?
146-
147-
* Differentiate tail-callers or callees by type?
148-
149-
* What about tail calls to host functions?
150-
- treat as tail-calling a wrapper, use type distinction, or trap?
151-
- note: cannot distinguish statically without type system support, e.g. with indirect calls
152-
153-
* Instruction name bikeshedding
154-
148+
* Can tail calls across module boundaries guarantee tail behaviour?

0 commit comments

Comments
 (0)