@@ -232,54 +232,66 @@ Since all AST nodes are expressions in WebAssembly, control constructs may yield
232
232
a value and may appear as children of other expressions.
233
233
234
234
* ` nop ` : an empty operator that does not yield a value
235
- * ` block ` : a fixed-length sequence of expressions with a label at the end
235
+ * ` block ` : a sequence of expressions with a label at the end
236
236
* ` loop ` : a block with an additional label at the beginning which may be used to form loops
237
+ * ` multiblock ` : a mixed sequence of expressions and ` label ` nodes, with a label at the end
238
+ * ` label ` : a node which defines a label and must be an immediate child of ` multiblock `
237
239
* ` if ` : if expression with a * then* expression
238
240
* ` if_else ` : if expression with * then* and * else* expressions
239
- * ` br ` : branch to a given label in an enclosing construct
240
- * ` br_if ` : conditionally branch to a given label in an enclosing construct
241
- * ` tableswitch ` : a jump table which may jump either to an immediate ` case `
242
- child or to a label in an enclosing construct
243
- * ` case ` : a case which must be an immediate child of ` tableswitch `
241
+ * ` br ` : branch to a given in-scope label
242
+ * ` br_if ` : conditionally branch to a given in-scope label
243
+ * ` tableswitch ` : branch using a "jump table" of in-scope labels
244
244
* ` return ` : return zero or more values from this function
245
245
246
246
### Branches and nesting
247
247
248
- The ` br ` and ` br_if ` constructs express low-level branching.
249
- Branches that exit a ` block ` , ` loop ` , or ` tableswitch ` may take a subexpression
250
- that yields a value for the exited construct.
251
- Branches may only reference labels defined by an outer * enclosing construct* .
252
- This means that, for example, references to a ` block ` 's label can only occur
253
- within the ` block ` 's body.
254
-
255
- In practice, outer ` block ` s can be used to place labels for any given branching
256
- pattern, except for one restriction: one can't branch into the middle of a loop
257
- from outside it. This restriction ensures all control flow graphs are well-structured
248
+ The ` br ` , ` br_if ` , and ` tableswitch ` constructs express low-level branching. The
249
+ ` block ` , ` loop ` , and ` multiblock ` constructs provide labels that may be branched
250
+ to.
251
+
252
+ Branches may only reference labels that are * in scope* . The labels in ` block `
253
+ and ` loop ` nodes are in scope only within their subtrees. The labels in
254
+ ` multiblock ` nodes are only in scope only within their subtrees, and only in
255
+ subtrees earlier in the ` multiblock ` than their definition. This restriction
256
+ ensures all control flow graphs are
257
+ [ reducible] ( http://dl.acm.org/citation.cfm?id=804919 ) .
258
+
259
+ In terms of control flow graphs, the reducible requirement imposes
260
+ only one effective restriction: loops can only be entered from the
261
+ top, and not from a branch into the middle. This restriction ensures
262
+ all control flow graphs are well-structured
258
263
in the exact sense as in high-level languages like Java, JavaScript, Rust and Go. To
259
264
further see the parallel, note that a ` br ` to a ` block ` 's label is functionally
260
265
equivalent to a labeled ` break ` in high-level languages in that a ` br ` simply
261
266
breaks out of a ` block ` .
262
267
268
+ Branches may take a subexpression as an optional first operand (before any
269
+ other operands). When a ` block ` , ` multiblock ` , or ` loop ` is exited by a branch,
270
+ or when a ` label ` is branched to by a branch, this operand of the branch is
271
+ yielded as the result. When ` br_if ` 's condition is false, this operand is
272
+ yielded as ` br_if ` 's result.
273
+
263
274
### Yielding values from control constructs
264
275
265
- The ` nop ` , ` if ` , ` br ` , ` br_if ` , ` case ` , and ` return ` constructs do not yield values.
276
+ The ` nop ` and ` if ` constructs do not yield values.
266
277
Other control constructs may yield values if their subexpressions yield values:
267
278
268
- * ` block ` : yields either the value of the last expression in the block or the result of an inner ` br ` that targeted the label of the block
269
- * ` loop ` : yields either the value of the last expression in the loop or the result of an inner ` br ` that targeted the end label of the loop
279
+ * ` block ` : yields either the value of the last expression in the block or the
280
+ result of an inner branch that branched to the label of the ` block `
281
+ * ` loop ` : yields either the value of the last expression in the loop or the
282
+ result of an inner branch that branched to the end label of the ` loop `
283
+ * ` multiblock ` : yields either the value of the last expression in the
284
+ ` multiblock ` or the result of an inner branch that branched to the end label
285
+ of the ` multiblock `
286
+ * ` label ` : yields either the value of the prior expression in the parent ` multiblock ` or the result of a branch that branched to the ` label `
270
287
* ` if_else ` : yields either the value of the true expression or the false expression
271
- * ` tableswitch ` : yields either the value of the last case or the result of an inner ` br ` that targeted the tableswitch
272
288
273
289
274
290
### Tableswitch
275
291
276
- A ` tableswitch ` consists of a zero-based array of targets, a * default* target, an index
277
- operand, and a list of ` case ` nodes. Targets may be either labels or ` case ` nodes.
278
- A ` tableswitch ` jumps to the target indexed in the array or the default target if the index is out of bounds.
279
-
280
- A ` case ` node consists of an expression and may be referenced multiple times
281
- by the parent ` tableswitch ` . Unless exited explicitly, control falls through a ` case `
282
- to the next ` case ` or the end of the ` tableswitch ` .
292
+ A ` tableswitch ` consists of a zero-based array of labels, a * default* label, and an
293
+ index operand. A ` tableswitch ` branches to the label indexed in the array or the
294
+ default label if the index is out of bounds.
283
295
284
296
285
297
## Calls
0 commit comments