This way we avoid having to extract later, as we will never inline if the `isinst` argument if this could result in it being unrepresentable in C#.
This commit also refactors inlining restrictions to avoid requiring special cases in ILInlining itself.
But when making this change, I discovered that this broke our pattern-matching tests, and that the weird IL with double `isinst` is indeed generated by the C# compiler for `if (genericParam is StringComparison.Ordinal)` style code. So instead we also allow `isinst` with a `box(expr-without-side-effects)` argument to be represented with the `expr is T ? (T)expr : null` emulation.
This makes our logic more similar to that used by the dotnet runtime. This lets us infer correct stack types in edge cases such as #2401. It also improves support for obfuscated control flow such as #2878.
This is a performance optimization: we dramatically reduce the amount of ILVariables created;
and thus need to spend less time in the first ILInlining run.
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.