diff --git a/AstSemantics.md b/AstSemantics.md index c559e0c6..5c422e31 100644 --- a/AstSemantics.md +++ b/AstSemantics.md @@ -258,22 +258,22 @@ others, etc. WebAssembly offers basic structured control flow. All control flow structures are statements. - * `block`: a fixed-length sequence of statements - * `if`: if statement - * `do_while`: do while statement, basically a loop with a conditional branch - (back to the top of the loop) - * `forever`: infinite loop statement (like `while (1)`), basically an - unconditional branch (back to the top of the loop) - * `continue`: continue to start of nested loop - * `break`: break to end from nested loop or block + * `block`: a fixed-length sequence of statements with a branch target at the end + * `loop`: a fixed-length sequence of statements with a branch target at the beginning + * `br`: branch to the branch target of a lexically enclosing `block` or `loop` + * `br_if`: like `br`, but has a `bool` operand and does nothing if the operand is false + * `br_unless`: like `br`, but has a `bool` operand and does nothing if the operand is true * `return`: return zero or more values from this function - * `switch`: switch statement with fallthrough + * `switch`: like `br_if` but has an integer operand, an arbitrary number of possible + branch targets, and a default branch target. -Loops (`do_while` and `forever`) may only be entered via fallthrough at the top. -In particular, loops may not be entered directly via a `break`, `continue`, or -`switch` destination. Break and continue statements can only target blocks or -loops in which they are nested. These rules guarantee that all control flow -graphs are well-structured. +`br`, `br_if`, `br_unless`, and `switch` specify branch targets of lexically +enclosing `block` and `loop` constructs, which need not be the innermost `block` +or `loop`. + +As a consequence of these rules and the nesting structure of the AST, `block` +and `loop` nodes may only be entered via fallthrough at the top. These rules +guarantee that all control flow graphs are well-structured. Structured control flow provides simple and size-efficient binary encoding and compilation. Any control flow—even irreducible—can be transformed into structured @@ -403,6 +403,7 @@ results into the result type. * `i32.clz`: sign-agnostic count leading zero bits (defined for all values, including zero) * `i32.ctz`: sign-agnostic count trailing zero bits (defined for all values, including zero) * `i32.popcnt`: sign-agnostic count number of one bits + * `int32.select`: select between two values with a condition (not short-circuiting) Shifts interpret their shift count operand as an unsigned value. When the shift count is at least the bitwidth of the shift, `shl` and `shr_u` produce `0`, and @@ -421,8 +422,8 @@ The same operations are available on 64-bit integers as the those available for Floating point arithmetic follows the IEEE 754-2008 standard, except that: - The sign bit and significand bit pattern of any NaN value returned from a - floating point arithmetic operation other than `neg`, `abs`, and `copysign` - are not specified. In particular, the "NaN propagation" + floating point arithmetic operation other than `neg`, `abs`, `copysign`, + and `select` are not specified. In particular, the "NaN propagation" section of IEEE 754-2008 is not required. NaNs do propagate through arithmetic operations according to IEEE 754-2008 rules, the difference here is that they do so without necessarily preserving the specific bit patterns @@ -467,6 +468,7 @@ implementations of the remaining required operations. * `f32.sqrt`: square root * `f32.min`: minimum (binary operator); if either operand is NaN, returns NaN * `f32.max`: maximum (binary operator); if either operand is NaN, returns NaN + * `float32.select`: select between two values with a condition (not short-circuiting) * `f64.add`: addition * `f64.sub`: subtraction @@ -488,6 +490,7 @@ implementations of the remaining required operations. * `f64.sqrt`: square root * `f64.min`: minimum (binary operator); if either operand is NaN, returns NaN * `f64.max`: maximum (binary operator); if either operand is NaN, returns NaN + * `float64.select`: select between two values with a condition (not short-circuiting) `min` and `max` operations treat `-0.0` as being effectively less than `0.0`.