Skip to content

Commit 60677af

Browse files
committed
Reflect spec changes in delegate immediate operand
This adds the changes decided in WebAssembly#176 and adds a modified version from WebAssembly#146 (comment) for clarification. (The example is not the same by the way; the `catch` from the outermost `try` has been moved) Closes WebAssembly#176.
1 parent 7fcfe17 commit 60677af

File tree

1 file changed

+96
-20
lines changed

1 file changed

+96
-20
lines changed

proposals/exception-handling/Exceptions.md

+96-20
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,10 @@ try label and delegates exception handling to a `catch`/`catch_all`/`delegate`
274274
specified by the `try` label. For example, consider this code:
275275

276276
```
277-
try $l1
277+
try $l0
278278
try
279279
call $foo
280-
delegate $l1 ;; (= delegate 0)
280+
delegate $l0 (= delegate 0)
281281
catch
282282
...
283283
catch_all
@@ -288,28 +288,104 @@ end
288288
If `call $foo` throws, searching for a catching block first finds `delegate`,
289289
and because it delegates exception handling to catching instructions associated
290290
with `$l1`, it will be next checked by the outer `catch` and then `catch_all`
291-
instructions. When the specified label within a `delegate` instruction does not
292-
correspond to a `try` instruction, it is a validation failure.
291+
instructions.
292+
293+
`delegate` can also target `catch`-less `try`s or non-`try` block constructs
294+
like `block`s or `loop`s, in which case the delegated exception is assumed to
295+
propagate to the outer scope and will be caught by the next matching
296+
try-catches. In the examples, catches are annotated with `($label_name)` to
297+
clarify which `try` it belongs to for clarification; it is not the official
298+
syntax.
299+
```
300+
try $l0
301+
block $l1
302+
try
303+
call $foo
304+
delegate $l1 ;; delegates to 'catch ($l0)'
305+
end
306+
catch ($l0)
307+
end
308+
```
293309

294-
Note that the example below is a validation failure:
310+
`delegate` can only target `catch`/`catch_all`s that are below the current
311+
instruction, i.e., it can only delegate downwards. It also targets all
312+
`catch`/`catch_all`s of a `try` as a whole and does not target individual
313+
`catch`/`catch_all` within a `try`. Here is another example:
295314
```
296-
try $l1
297-
catch
315+
try $l0
316+
try $l1
317+
catch ($l1)
318+
try
319+
call $foo
320+
delegate $l1 ;; delegates to 'catch ($l0)'
321+
catch_all
322+
...
323+
end
324+
catch ($l0)
325+
```
326+
327+
Here the `delegate` is targeting `catch ($l1)`, which exists before the
328+
`delegate`. So in case an exception occurs, it propagates out and ends up
329+
targetting `catch ($l0)`, if the catch has a matching tag. If not, it will
330+
propagate further out. Even if the `catch_all` is below the `delegate`,
331+
`delegate` targets catches of a `try` as a whole and does not target an
332+
individual `catch`/`catch_all`, so it doesn't apply.
333+
334+
If `delegate`'s immediate argument is (the depth of the outermost block + 1), it
335+
is considered to target the function-level block, so it in effect delegates the
336+
exception to the caller of the current function. For example:
337+
```
338+
(func $test
298339
try
299-
call $foo
300-
delegate $l1 ;; (= delegate 0)
301-
catch_all
302-
...
303-
end
340+
try
341+
call $foo
342+
delegate 1 ;; delegates to the caller
343+
catch
344+
...
345+
catch_all
346+
...
347+
end
348+
)
349+
```
350+
In case `foo` throws, `delegate 1` here delegates the exception handling to the
351+
caller, i.e., the exception escapes the current function. If the immediate is
352+
greater than the depth of the outermost block + 1, it is a validation failure.
353+
354+
The below is an example that includes all the cases explained. The numbers
355+
within `()` after `delegate`s are the label operands in immediate values.
356+
```
357+
(func $test
358+
try $lA
359+
block $lB
360+
try $lC
361+
try
362+
delegate $lC (0) ;; delegates to 'catch ($lC)'
363+
try
364+
delegate $lB (1) ;; $lB is a block, so delegates to 'catch ($lA)'
365+
try
366+
delegate $lA (2) ;; delegates to 'catch ($lA)'
367+
try
368+
delegate 3 ;; propagates to the caller
369+
try
370+
delegate 4 ;; validation failure
371+
catch ($lC)
372+
try
373+
delegate $lC (0) ;; 'catch ($lC)' is above this instruction,
374+
;; so delegates to 'catch ($lA)'
375+
try
376+
delegate $lB (1) ;; $lB is a block, so delegates to 'catch ($lA)'
377+
try
378+
delegate $lA (2) ;; delegates to 'catch ($lA)'
379+
try
380+
delegate 3 ;; propagates to the caller
381+
try
382+
delegate 4 ;; validation failure
383+
end ;; try $lC
384+
end ;; block $lB
385+
catch ($lA)
386+
end ;; try $lA
387+
)
304388
```
305-
Here `delegate` is trying to delegate to `catch`, which exists before the
306-
`delegate`. The `delegate` instruction can only target `try` label whose
307-
catching instructions (`catch`/`catch_all`/`delegate`) come after the
308-
`delegate` instruction.
309-
310-
`delegate` can also target `catch`-less `try`, in which case the effect is the
311-
same as if the `try` has catches but none of the catches are able to handle the
312-
exception.
313389

314390
### JS API
315391

0 commit comments

Comments
 (0)