Browse Source

[async] Fix await decompilation when GetResult call got inlined into another instruction.

pull/850/head
Daniel Grunwald 8 years ago
parent
commit
d5e41a91e6
  1. 21
      ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs
  2. 16
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

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

@ -671,14 +671,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -671,14 +671,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return;
if (!CheckResumeBlock(resumeBlock, awaiterVar, awaitBlockData.awaiterField, completedBlock, stackField))
return;
// Check completedBlock:
ILInstruction getResultCall;
if (completedBlock.Instructions[0] is StLoc resultStore) {
getResultCall = resultStore.Value;
} else {
getResultCall = completedBlock.Instructions[0];
resultStore = null;
}
// Check completedBlock. The first instruction involves the GetResult call, but it might have
// been inlined into another instruction.
var getResultCall = ILInlining.FindFirstInlinedCall(completedBlock.Instructions[0]);
if (getResultCall == null)
return;
if (!MatchCall(getResultCall, "GetResult", out var getResultArgs) || getResultArgs.Count != 1)
return;
if (!getResultArgs[0].MatchLdLocRef(awaiterVar))
@ -691,14 +688,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -691,14 +688,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
Await awaitInst = new Await(getAwaiterCall.Arguments.Single());
awaitInst.GetResultMethod = ((CallInstruction)getResultCall).Method;
awaitInst.GetAwaiterMethod = getAwaiterCall.Method;
if (resultStore != null) {
resultStore.Value = awaitInst;
} else {
completedBlock.Instructions[0] = awaitInst;
}
getResultCall.ReplaceWith(awaitInst);
// Remove useless reset of awaiterVar.
if (completedBlock.Instructions[1] is StObj stobj) {
if (completedBlock.Instructions.ElementAtOrDefault(1) is StObj stobj) {
if (stobj.Target.MatchLdLoca(awaiterVar) && stobj.Value.OpCode == OpCode.DefaultValue) {
completedBlock.Instructions.RemoveAt(1);
}

16
ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

@ -331,5 +331,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -331,5 +331,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
return SemanticHelper.MayReorder(expressionBeingMoved, expr);
}
/// <summary>
/// Finds the first call instruction within the instructions that were inlined into inst.
/// </summary>
internal static CallInstruction FindFirstInlinedCall(ILInstruction inst)
{
foreach (var child in inst.Children) {
if (!child.SlotInfo.CanInlineInto)
break;
var call = FindFirstInlinedCall(child);
if (call != null) {
return call;
}
}
return inst as CallInstruction;
}
}
}

Loading…
Cancel
Save