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 @@ -725,6 +725,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
throw new SymbolicAnalysisFailedException();
finalStateKnown = true;
pos++;
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))
@ -807,7 +808,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -807,7 +808,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// https://github.com/dotnet/roslyn/pull/39735 hoisted local cleanup
if (!target.MatchLdThis())
throw new SymbolicAnalysisFailedException();
if (!(value.MatchLdNull() || value is DefaultValue))
if (!value.MatchDefaultOrNullOrZero())
throw new SymbolicAnalysisFailedException();
pos++;
}
@ -1441,13 +1442,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1441,13 +1442,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
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;
if (!StackSlotValue(target).MatchLdThis())
return false;
// TODO: check that we are accessing the current field (compare with get_Current)
block.Instructions.RemoveRange(pos, block.Instructions.Count - pos);
return true;
}
#endregion

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

@ -553,6 +553,23 @@ namespace ICSharpCode.Decompiler.IL @@ -553,6 +553,23 @@ namespace ICSharpCode.Decompiler.IL
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>
/// If this instruction is a conversion of the specified kind, return its argument.
/// Otherwise, return the instruction itself.

Loading…
Cancel
Save