a list of handlers covering the same blocks (same try, multiple catches)
blocks can't be moved (fist block of a method, blocks directly following a try-catch)
The MSIL linearizer first calls a NormalLInearizer.
The MSIL linearizer first calls a NormalLInearizer. This is because the ILGenerator checks
the stack size before emitting instructions. For instance, to emit a store
, there needs
to be some value on the stack. This can blow up in situations like this:
...
jump 3
4: store_local 0
jump 5
3: load_value
jump 4
5: ...
here, 3 must be scheduled first.
The NormalLinearizer also removes dead blocks (blocks without predecessor). This is important
in the following example:
try { throw new Exception }
catch { case e => throw e }
which adds a dead block containing just a "throw" (which, again, would blow up code generation
because of the stack size; there's no value on the stack when emitting that throw
)
(Since version 2.10.0) Use leftOfArrow instead
(Since version 2.10.0) Use resultOfEnsuring instead
The MSIL linearizer is used only for methods with at least one exception handler. It makes sure that all the blocks belonging to a
try
,catch
orfinally
block are emitted in an order that allows the lexical nesting of try-catch-finally, just like in the source code.