The C# translation of StObj will always apply delayed exceptions in these two cases, so putting an instruction with delayed exceptions in that slot would change program semantics.
or implicit sequence point without creating overlapping sequence points.
If such a location cannot be found do, nothing. Fill in the
gaps with hidden sequence points.
Also emit a sequence point for
the prolog to account for seqeunce point there emitted by the C#
compiler. Without this, the debugger can stop there on a step in
using the original pdb, then decompile resulting in a no-code at this
location failure.
Unreachable code is not part of the dominator tree, which most of our transforms are based on.
In particular, dominance-based loop detection runs into the problem where unreachable code might have jumps into two independent loops. In that case, it's impossible to place the unreachable code in a way that avoids assertions / generating invalid C#.
We establish the invariant that all blocks in a BlockContainer must be statically reachable from the entry point (-> every block is part of the dominator tree). This means transforms no longer have to deal with special cases for unreachable code.
The "Remove dead and side effect free code" option still has an effect on dead stores, but unreachable code is now always removed (previously this also was dependent on this option).
Also, assume that unknown inputs to ldfld are temporaries, not unmanaged pointers.
This avoids emitting weird pointer casts when accessing fields on unresolved value types.
For user-defined increments, there were problems with Roslyn was optimizing out one of the stores.
The new transform FixRemainingIncrements now takes increments/decrements that were not detected by TransformAssignment and introduces a temporary variable that can be incremented.
This sometimes requires un-inlining via the new ILInstruction.Extract() operation.
Extract() is not supported in all possible contexts, so it is possible but unlikely that some op_Increment calls remain.
For decimals, the situation is different: legacy csc actually was optimizing "d + 1m" to "op_Increment(d)", so we can get rid of any left-over increments by undoing this optimization. This now happens in ReplaceMethodCallsWithOperators.
This means we can get rid of the special case in TransformDisplayClassUsage, as compound.assign can now also be used with the address of a local variable.