Browse Source

Fix #750: Missing recognizer for ?? when rhs is an assignment expression

pull/1360/head
Siegfried Pammer 7 years ago
parent
commit
875af13934
  1. 26
      ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs

26
ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs

@ -55,11 +55,29 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -55,11 +55,29 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!block.Instructions[pos + 1].MatchIfInstruction(out var condition, out var trueInst))
return false;
if (!(condition.MatchCompEquals(out var left, out var right) && left.MatchLdLoc(stloc.Variable) && right.MatchLdNull()))
return false;
trueInst = Block.Unwrap(trueInst);
if (condition.MatchCompEquals(out var left, out var right) && left.MatchLdLoc(stloc.Variable) && right.MatchLdNull()
&& trueInst.MatchStLoc(stloc.Variable, out var fallbackValue)
) {
context.Step("NullCoalescingTransform (reference types)", stloc);
if (trueInst.MatchStLoc(stloc.Variable, out var fallbackValue)) {
context.Step("NullCoalescingTransform: simple (reference types)", stloc);
stloc.Value = new NullCoalescingInstruction(NullCoalescingKind.Ref, stloc.Value, fallbackValue);
block.Instructions.RemoveAt(pos + 1); // remove if instruction
ILInlining.InlineOneIfPossible(block, pos, InliningOptions.None, context);
return true;
}
// sometimes the compiler generates:
// stloc s(valueInst)
// if (comp(ldloc s == ldnull)) {
// stloc v(fallbackInst)
// stloc s(ldloc v)
// }
// v must be single-assign and single-use.
if (trueInst is Block trueBlock && trueBlock.Instructions.Count == 2
&& trueBlock.Instructions[0].MatchStLoc(out var temporary, out fallbackValue)
&& temporary.IsSingleDefinition && temporary.LoadCount == 1
&& trueBlock.Instructions[1].MatchStLoc(stloc.Variable, out var useOfTemporary)
&& useOfTemporary.MatchLdLoc(temporary)) {
context.Step("NullCoalescingTransform: with temporary variable (reference types)", stloc);
stloc.Value = new NullCoalescingInstruction(NullCoalescingKind.Ref, stloc.Value, fallbackValue);
block.Instructions.RemoveAt(pos + 1); // remove if instruction
ILInlining.InlineOneIfPossible(block, pos, InliningOptions.None, context);

Loading…
Cancel
Save