diff --git a/AstSemantics.md b/AstSemantics.md index 43d562ac..47d26f22 100644 --- a/AstSemantics.md +++ b/AstSemantics.md @@ -250,9 +250,16 @@ Branches that exit a `block`, `loop`, or `tableswitch` may take a subexpression that yields a value for the exited construct. Branches may only reference labels defined by an outer *enclosing construct*. This means that, for example, references to a `block`'s label can only occur -within the `block`'s body. In practice, outer `block`s can be used to place labels for any -given branching pattern, except for one restriction: one can't branch into the middle of a -loop from outside it. This restriction ensures all control flow graphs are well-structured. +within the `block`'s body. + +In practice, outer `block`s can be used to place labels for +[any given branching pattern](Rational.md#control-flow), +except for one restriction: one can't branch into the middle of a loop +from outside it. This restriction ensures all control flow graphs are well-structured +in the exact sense as in high-level languages like Java and JavaScript. To +further see the parallel, note that a `br` to a `block`'s label is functionally +equivalent to a labeled `break` in high-level languages in that a `br` simply +breaks out of a `block`. ### Yielding values from control constructs diff --git a/Rationale.md b/Rationale.md index c73f8993..42811cea 100644 --- a/Rationale.md +++ b/Rationale.md @@ -130,12 +130,34 @@ control flow with the [Relooper](https://github.com/kripken/emscripten/raw/master/docs/paper.pdf) [algorithm](http://dl.acm.org/citation.cfm?id=2048224&CFID=670868333&CFTOKEN=46181900), with guaranteed low code size overhead, and typically minimal throughput -overhead (except for pathological cases of irreducible control +overhead (due to using a label threading variable for irreducible control flow). Alternative approaches can generate reducible control flow via node splitting, which can reduce throughput overhead, at the cost of increasing code size (potentially very significantly in pathological cases). -Also, -[more expressive control flow constructs](FutureFeatures.md#more-expressive-control-flow) + +More specifically, control flow in WebAssembly has the same restrictions as in +high-level languages such as Java and JavaScript, which do not have arbitrary +`goto`s, but do have labeled `break`: WebAssembly's `br` control flow construct is +in fact +[functionally equivalent to a labeled `break`](AstSemantics.md#branches-and-nesting). +The main limitation that such control flow has over completely arbitrary control +flow is that it is not possible to +[jump into the middle of loops](https://en.wikipedia.org/wiki/Duff's_device) +(unless you introduce a label threading variable, of course, which allows any +CFG to be represented, as in the Relooper algorithm). And the relationship +is bidirectional, as it is in fact possible to represent any control flow having +that limitation by using just `block`s, `loop`s, and labeled `break`s: create a +`loop`s where necessary, and then you are left with sections in which control +flow can only branch forward, in which you can sort and create nested `blocks`. +Branches forward are then simply labeled `break`s, which can go as forward as +necessary in that section. + +In summary, we know that structured control flow can be represented in the +WebAssembly AST in a guaranteed manner. Arbitrary control flow can also be +represented there, with overhead that experience has shown is acceptable +especially given the rarity of irreducible control flow. + +[More expressive control flow constructs](FutureFeatures.md#more-expressive-control-flow) may be added in the future.