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
)
(mSILLinearizer: StringAdd).self
(mSILLinearizer: StringFormat).self
(mSILLinearizer: ArrowAssoc[ICodes.MSILLinearizer]).x
(Since version 2.10.0) Use leftOfArrow
instead
(mSILLinearizer: Ensuring[ICodes.MSILLinearizer]).x
(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.