Skip to content

Commit 5fde46e

Browse files
committed
Flexible control-flow operators.
This introduces `br`, `br_if`, and so on, while also preserving the high-level `if` and `if_else` operators. It also converts `switch` into `tableswitch` and generalizes it to support labels in enclosing scopes. This also embraces statements=expressions by removing the comma, conditional, and return operators.
1 parent f680241 commit 5fde46e

File tree

2 files changed

+48
-43
lines changed

2 files changed

+48
-43
lines changed

AstSemantics.md

Lines changed: 35 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -247,39 +247,41 @@ others, etc.
247247

248248
## Control flow structures
249249

250-
WebAssembly offers basic structured control flow. All control flow structures
251-
are statements.
252-
253-
* `block`: a fixed-length sequence of statements
254-
* `if`: if statement
255-
* `do_while`: do while statement, basically a loop with a conditional branch
256-
(back to the top of the loop)
257-
* `forever`: infinite loop statement (like `while (1)`), basically an
258-
unconditional branch (back to the top of the loop)
259-
* `continue`: continue to start of nested loop
260-
* `break`: break to end from nested loop or block
261-
* `return`: return zero or more values from this function
262-
* `switch`: switch statement with fallthrough
263-
264-
Loops (`do_while` and `forever`) may only be entered via fallthrough at the top.
265-
In particular, loops may not be entered directly via a `break`, `continue`, or
266-
`switch` destination. Break and continue statements can only target blocks or
267-
loops in which they are nested. These rules guarantee that all control flow
268-
graphs are well-structured.
269-
270-
Structured control flow provides simple and size-efficient binary encoding and
271-
compilation. Any control flow—even irreducible—can be transformed into structured
272-
control flow with the
273-
[Relooper](https://github.com/kripken/emscripten/raw/master/docs/paper.pdf)
274-
[algorithm](http://dl.acm.org/citation.cfm?id=2048224&CFID=670868333&CFTOKEN=46181900),
275-
with guaranteed low code size overhead, and typically minimal throughput
276-
overhead (except for pathological cases of irreducible control
277-
flow). Alternative approaches can generate reducible control flow via node
278-
splitting, which can reduce throughput overhead, at the cost of increasing
279-
code size (potentially very significantly in pathological cases).
280-
Also,
281-
[more expressive control flow constructs](FutureFeatures.md#more-expressive-control-flow)
282-
may be added in the future.
250+
WebAssembly offers basic structured control flow with the following constructs:
251+
252+
* `block`: a fixed-length sequence of statements with a label at the end
253+
* `loop`: a fixed-length sequence of statements with a label at the end
254+
and a loop header label at the top
255+
* `if`: if statement with then body
256+
* `if_else`: if statement with then and else bodies
257+
* `br`: branch to a given label in an enclosing construct (see below)
258+
* `br_if`: conditionally branch to a given label in an enclosing construct
259+
* `tableswitch`: a jump table transferring which may jump either to enclosed
260+
`case` blocks or to labels in enclosing constructs (see below
261+
for a more detailed description)
262+
* `case`: must be an immediate child of `tableswitch`; has a label declared
263+
in the `tableswitch`'s table and a body (as above, see below)
264+
265+
References to labels must occur within an *enclosing construct* that defined
266+
the label. This means that references to an AST node's label can only happen
267+
within descendents of the node in the tree. For example, references to a
268+
`block`'s label can only happen from within the `block`'s body. In practice,
269+
one can arrange `block`s to put labels wherever one wants to jump to, except
270+
for one restriction: one can't jump into the middle of a loop from outside
271+
it. This restriction ensures the well-structured property discussed below.
272+
273+
`tableswitch` instructions have a zero-based array of labels, a label index,
274+
a "default" label, an index operand, and a list of `case` nodes. A `tableswitch`
275+
selects which label to branch to by looking up the index value in the label
276+
array, and transferring control to that label. If the index is out of bounds,
277+
it transfers control to the "default" label.
278+
279+
`case` nodes can only appear as immediate children of `tableswitch` statements.
280+
They have a label, which must be declared in the immediately enclosing
281+
`tableswitch`'s array, and a body which can contain arbitrary code. Control
282+
falls through the end of a `case` block into the following `case` block, or
283+
the end of the `tableswitch` in the case of the last `case`.
284+
283285

284286
## Calls
285287

@@ -350,15 +352,6 @@ supported (including NaN values of all possible bit patterns).
350352
* `f32.const`: produce the value of an f32 immediate
351353
* `f64.const`: produce the value of an f64 immediate
352354

353-
## Expressions with Control Flow
354-
355-
* `comma`: evaluate and ignore the result of the first operand, evaluate and
356-
return the second operand
357-
* `conditional`: basically ternary `?:` operator
358-
359-
New operations may be considered which allow measurably greater
360-
expression-tree-building opportunities.
361-
362355
## 32-bit Integer operations
363356

364357
Integer operations are signed, unsigned, or sign-agnostic. Signed operations

Rationale.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,19 @@ developer.
114114

115115
## Control Flow
116116

117-
See [#299](https://github.com/WebAssembly/design/pull/299).
117+
Structured control flow provides simple and size-efficient binary encoding and
118+
compilation. Any control flow—even irreducible—can be transformed into structured
119+
control flow with the
120+
[Relooper](https://github.com/kripken/emscripten/raw/master/docs/paper.pdf)
121+
[algorithm](http://dl.acm.org/citation.cfm?id=2048224&CFID=670868333&CFTOKEN=46181900),
122+
with guaranteed low code size overhead, and typically minimal throughput
123+
overhead (except for pathological cases of irreducible control
124+
flow). Alternative approaches can generate reducible control flow via node
125+
splitting, which can reduce throughput overhead, at the cost of increasing
126+
code size (potentially very significantly in pathological cases).
127+
Also,
128+
[more expressive control flow constructs](FutureFeatures.md#more-expressive-control-flow)
129+
may be added in the future.
118130

119131

120132
## Locals

0 commit comments

Comments
 (0)