Browse Source

Fix decompilation of async streams compiled with Roslyn 4.2

pull/2749/head
Daniel Grunwald 3 years ago
parent
commit
3c847b56a2
  1. 16
      ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs
  2. 17
      ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs

16
ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs

@ -725,6 +725,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
finalStateKnown = true; finalStateKnown = true;
pos++; pos++;
if (pos + 2 == block.Instructions.Count && block.MatchIfAtEndOfBlock(out var condition, out var trueInst, out var falseInst)) if (pos + 2 == block.Instructions.Count && block.MatchIfAtEndOfBlock(out var condition, out var trueInst, out var falseInst))
{ {
if (MatchDisposeCombinedTokens(blockContainer, condition, trueInst, falseInst, blocksAnalyzed, out var setResultAndExitBlock)) if (MatchDisposeCombinedTokens(blockContainer, condition, trueInst, falseInst, blocksAnalyzed, out var setResultAndExitBlock))
@ -807,7 +808,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// https://github.com/dotnet/roslyn/pull/39735 hoisted local cleanup // https://github.com/dotnet/roslyn/pull/39735 hoisted local cleanup
if (!target.MatchLdThis()) if (!target.MatchLdThis())
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
if (!(value.MatchLdNull() || value is DefaultValue)) if (!value.MatchDefaultOrNullOrZero())
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
pos++; pos++;
} }
@ -1441,13 +1442,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
pos--; pos--;
} }
if (pos < 0 || !block.Instructions[pos].MatchStFld(out var target, out var field, out yieldValue)) if (pos < 0 || !MatchCurrentAssignment(block.Instructions[pos], out yieldValue))
return false;
block.Instructions.RemoveRange(pos, block.Instructions.Count - pos);
return true;
}
bool MatchCurrentAssignment(ILInstruction inst, out ILInstruction value)
{
if (!inst.MatchStFld(out var target, out var field, out value))
return false; return false;
if (!StackSlotValue(target).MatchLdThis()) if (!StackSlotValue(target).MatchLdThis())
return false; return false;
// TODO: check that we are accessing the current field (compare with get_Current) // TODO: check that we are accessing the current field (compare with get_Current)
block.Instructions.RemoveRange(pos, block.Instructions.Count - pos);
return true; return true;
} }
#endregion #endregion

17
ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs

@ -553,6 +553,23 @@ namespace ICSharpCode.Decompiler.IL
return false; return false;
} }
public bool MatchDefaultOrNullOrZero()
{
switch (this)
{
case LdNull _:
case LdcF4 { Value: 0 }:
case LdcF8 { Value: 0 }:
case LdcI4 { Value: 0 }:
case LdcI8 { Value: 0 }:
case DefaultValue _:
return true;
default:
return false;
}
}
/// <summary> /// <summary>
/// If this instruction is a conversion of the specified kind, return its argument. /// If this instruction is a conversion of the specified kind, return its argument.
/// Otherwise, return the instruction itself. /// Otherwise, return the instruction itself.

Loading…
Cancel
Save