Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit 3c7f11a

Browse files
authored
Simplify exception dispatch to branches (#71)
This proposes to use the idea suggested by #58 on using `br_on_exn` instead of `if_except`.
1 parent 2bbeec2 commit 3c7f11a

File tree

1 file changed

+56
-37
lines changed

1 file changed

+56
-37
lines changed

proposals/Exceptions.md

Lines changed: 56 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,10 @@ Exception indices are used by:
133133
1. The `throw` instruction which creates a WebAssembly exception with the
134134
corresponding exception tag, and then throws it.
135135

136-
2. The `if_except` instruction queries an exception to see if the corresponding
137-
exception tag denoted by the exception index. If true it pushes the
138-
corresponding values of the exception onto the stack.
136+
2. The `br_on_exn` instruction queries an exception to see if it matches the
137+
corresponding exception tag denoted by the exception index. If true it
138+
branches to the given label and pushes the corresponding argument values of
139+
the exception onto the stack.
139140

140141
### The exception reference data type
141142

@@ -220,39 +221,58 @@ exception on top of the stack is popped and then thrown.
220221

221222
### Exception data extraction
222223

223-
The `if_except` block begins with an `if_except` instruction, and has two
224-
instruction blocks,
225-
226-
That is, the forms of an if_except block is:
224+
The `br_on_exn` instruction is a conditional branch that checks the exception
225+
tag of an exception on top of the stack, in the form of:
227226

228227
```
229-
if_except block_type except_index
230-
Instruction*
231-
end
228+
br_on_exn label except_index
229+
```
230+
231+
The `br_on_exn` instruction checks the exception tag of an `except_ref` on top
232+
of the stack if it matches the given exception index. If it does, it branches
233+
out to the label referenced by the instruction (In the binary form, the label
234+
will be converted to a relative depth immediate, like other branch
235+
instructions), and while doing that, pops the `except_ref` value from the stack
236+
and instead pushes the exception's argument values on top of the stack. In order
237+
to use these popped values, the block signature of the branch target has to
238+
match the exception types - because it receives the exception arguments as
239+
branch operands. If the exception tag does not match, the `except_ref` value
240+
remains on the stack. For example, when an `except_ref` contains an exception of
241+
type (i32 i64), the target block signature should be (i32 i64) as well, as in
242+
the following example:
232243

233-
if_except block_type except_index
234-
Instruction*
235-
else
236-
Instruction*
244+
```
245+
block $l (result i32 i64)
246+
...
247+
;; except_ref $e is on the stack at this point
248+
br_on_exn $l ;; branch to $l with $e's arguments
249+
...
237250
end
238251
```
239252

240-
In the first form, the instructions between the `if_except` and 'end' define the
241-
`then block`. In the second form, the instructions between the `if_except` and
242-
`else` define the `then block`, while the instructions between the `else` and
243-
the `end` define the `else block`.
244-
245-
The conditional query of an exception checks the exception tag of exception on
246-
top of the stack. It succeeds only if the exception index of the instruction
247-
matches the corresponding exception tag. Once the query completes, the exception
248-
is popped off the stack.
253+
This can now be used to construct handler switches in the same way `br_table`
254+
is used to construct regular switch:
249255

250-
If the query succeeds the values (associated with the popped exception) are
251-
extracted and pushed onto the stack, and control transfers to the instructions
252-
in the then block.
256+
```
257+
block $end
258+
block $l1
259+
...
260+
block $lN
261+
br_on_exn $l1
262+
...
263+
br_on_exn $lN
264+
rethrow
265+
end $lN
266+
;; handler for $eN here
267+
br $end
268+
...
269+
end $l1
270+
;; handler for $e1
271+
end $end
272+
```
253273

254-
If the query fails, it either enters the else block, or transfer control to the
255-
end of the if_except block if there is no else block.
274+
If the query fails, the control flow falls through, and no values are pushed
275+
onto the stack.
256276

257277
### Stack traces
258278

@@ -274,15 +294,14 @@ The following rules are added to *instructions*:
274294
try resulttype instruction* catch instruction* end |
275295
throw except_index |
276296
rethrow |
277-
if_except resulttype except_index then instruction* end |
278-
if_except resulttype except_index then instruction* else instruction* end
297+
br_on_exn label except_index
279298
```
280299

281-
Like the `block`, `loop`, and `if` instructions, the `try` and `if_except`
282-
instructions are *structured* control flow instructions, and can be labeled.
283-
This allows branch instructions to exit try and `if_except` blocks.
300+
Like the `block`, `loop`, and `if` instructions, the `try` instruction is
301+
*structured* control flow instruction, and can be labeled. This allows branch
302+
instructions to exit try blocks.
284303

285-
The `except_index` of the `throw` and `if_except` instructions defines the
304+
The `except_index` of the `throw` and `br_on_exn` instructions defines the
286305
exception (and hence, exception tag) to create/extract from. See [exception
287306
index space](#exception-index-space) for further clarification of exception
288307
tags.
@@ -447,7 +466,7 @@ throws, and rethrows as follows:
447466
| `catch` | `0x07` | | begins the catch block of the try block |
448467
| `throw` | `0x08` | index : `varint32` | Creates an exception defined by the exception `index`and then throws it |
449468
| `rethrow` | `0x09` | | Pops the `except_ref` on top of the stack and throws it |
450-
| `if_except` | `0x0a` | index : `varuint32`, sig : `block_type` | Begin exception data extraction if exception on stack was created using the corresponding exception `index` |
469+
| `br_on_exn` | `0x0a` | relative_depth : `varuint32`, index : `varuint32` | Branches to the given label and extracts data within `except_ref` on top of stack if it was created using the corresponding exception `index` |
451470

452-
The *sig* fields of `block`, `if`, `try` and `if_except` operators are block
453-
signatures which describe their use of the operand stack.
471+
The *sig* fields of `block`, `if`, and `try` operators are block signatures
472+
which describe their use of the operand stack.

0 commit comments

Comments
 (0)