diff --git a/AstSemantics.md b/AstSemantics.md index affcfc69..9c673b19 100644 --- a/AstSemantics.md +++ b/AstSemantics.md @@ -258,10 +258,17 @@ All control flow structures, except `case`, are statements. * `br`: branch to a given label in an enclosing construct (see below) * `br_if`: conditionally branch to a given label in an enclosing construct * `tableswitch`: a jump table transferring which may jump either to enclosed - `case` blocks or to labels in enclosing constructs (see below - for a more detailed description) - * `case`: must be an immediate child of `tableswitch`; has a label declared - in the `tableswitch`'s table and a body (as above, see below) + `case` and `default` blocks or to labels in enclosing constructs + identified by enclosed `case_br` and `default_br` nodes (see + below for a more detailed description) + * `case`: must be an immediate child of `tableswitch`; has an immediate index + value and a body (as above, see below) + * `case_br`: must be an immediate child of `tableswitch`; has an immediate index + value and a label (as above, see below) + * `default`: must be an immediate child of `tableswitch`; has a body + (as above, see below) + * `default_br`: must be an immediate child of `tableswitch`; has a a label + (as above, see below) * `return`: return zero or more values from this function References to labels must occur within an *enclosing construct* that defined @@ -272,18 +279,31 @@ one can arrange `block`s to put labels wherever one wants to jump to, except for one restriction: one can't jump into the middle of a loop from outside it. This restriction ensures the well-structured property discussed below. -`tableswitch` instructions have a zero-based array of labels, a label index, -a "default" label, an index operand, and a list of `case` nodes. A `tableswitch` -selects which label to branch to by looking up the index value in the label -array, and transferring control to that label. If the index is out of bounds, -it transfers control to the "default" label. - -`case` nodes can only appear as immediate children of `tableswitch` statements. -They have a label, which must be declared in the immediately enclosing -`tableswitch`'s array, and a body which can contain arbitrary code. Control -falls through the end of a `case` block into the following `case` block, or -the end of the `tableswitch` in the case of the last `case`. - +`tableswitch` instructions have a label index operand, and contain a sequence +of `case`, `case_br`, `default`, and `default_br` nodes. The following +restrictions apply to the sequence: + + - There must be either exactly one `default` node or exactly one + `default_br` node. + - Each `case` and `case_br` must have a unique index immediate value + among all `case` and `case_br` nodes. + - For each `case` and `case_br` with a non-zero index immediate value, + there must also be a `case` or `case_br` present with an index + immediate value of one less. + +A `tableswitch` first chooses a child node by selecting the `case` or +`case_br` node with the immediate index value equal to the `index` operand, +if there is such a `case` or `case_br` node present, or the `default` or +`default_br` node otherwise. + +If the chosen child node is a `case`, or `default`, `tableswitch` transfers +control to the node's body. If the chosen child node is a `case_br` or +`default_br`, `tableswitch` transfers control directly to the node's label. + +`case`, `case_br`, `default`, and `default_br` nodes can only appear as +immediate children of `tableswitch` statements. Control falls through the end +of `case` and `default` bodies, into the next `tableswitch` child node in AST +order, or exiting the `tableswitch` in the case of the last child node. ## Calls