Browse Source

Improve async/await decompilation when reference assemblies are missing

pull/1730/head
Daniel Grunwald 6 years ago
parent
commit
67fa24b09f
  1. 2
      BuildTools/update-assemblyinfo.ps1
  2. 16
      ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs

2
BuildTools/update-assemblyinfo.ps1

@ -53,7 +53,7 @@ function gitCommitHash() {
} }
function gitBranch() { function gitBranch() {
if (-not ((Test-Dir ".git") -and (Find-Git))) { if (-not ((Test-Dir ".git" -or Test-File ".git") -and (Find-Git))) {
return "no-branch"; return "no-branch";
} }

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

@ -998,7 +998,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// continue matching call get_IsCompleted(ldloca awaiterVar) // continue matching call get_IsCompleted(ldloca awaiterVar)
if (!MatchCall(condition, "get_IsCompleted", out var isCompletedArgs) || isCompletedArgs.Count != 1) if (!MatchCall(condition, "get_IsCompleted", out var isCompletedArgs) || isCompletedArgs.Count != 1)
return; return;
if (!isCompletedArgs[0].MatchLdLocRef(awaiterVar)) if (!UnwrapConvUnknown(isCompletedArgs[0]).MatchLdLocRef(awaiterVar))
return; return;
// Check awaitBlock and resumeBlock: // Check awaitBlock and resumeBlock:
if (!awaitBlocks.TryGetValue(awaitBlock, out var awaitBlockData)) if (!awaitBlocks.TryGetValue(awaitBlock, out var awaitBlockData))
@ -1016,14 +1016,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return; return;
if (!MatchCall(getResultCall, "GetResult", out var getResultArgs) || getResultArgs.Count != 1) if (!MatchCall(getResultCall, "GetResult", out var getResultArgs) || getResultArgs.Count != 1)
return; return;
if (!getResultArgs[0].MatchLdLocRef(awaiterVar)) if (!UnwrapConvUnknown(getResultArgs[0]).MatchLdLocRef(awaiterVar))
return; return;
// All checks successful, let's transform. // All checks successful, let's transform.
context.Step("Transform await pattern", block); context.Step("Transform await pattern", block);
block.Instructions.RemoveAt(block.Instructions.Count - 3); // remove getAwaiter call block.Instructions.RemoveAt(block.Instructions.Count - 3); // remove getAwaiter call
block.Instructions.RemoveAt(block.Instructions.Count - 2); // remove if (isCompleted) block.Instructions.RemoveAt(block.Instructions.Count - 2); // remove if (isCompleted)
((Branch)block.Instructions.Last()).TargetBlock = completedBlock; // instead, directly jump to completed block ((Branch)block.Instructions.Last()).TargetBlock = completedBlock; // instead, directly jump to completed block
Await awaitInst = new Await(getAwaiterCall.Arguments.Single()); Await awaitInst = new Await(UnwrapConvUnknown(getAwaiterCall.Arguments.Single()));
awaitInst.GetResultMethod = getResultCall.Method; awaitInst.GetResultMethod = getResultCall.Method;
awaitInst.GetAwaiterMethod = getAwaiterCall.Method; awaitInst.GetAwaiterMethod = getAwaiterCall.Method;
getResultCall.ReplaceWith(awaitInst); getResultCall.ReplaceWith(awaitInst);
@ -1035,7 +1035,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
} }
} }
} }
static ILInstruction UnwrapConvUnknown(ILInstruction inst)
{
if (inst is Conv conv && conv.TargetType == PrimitiveType.Unknown) {
return conv.Argument;
}
return inst;
}
bool CheckAwaitBlock(Block block, out Block resumeBlock, out IField stackField) bool CheckAwaitBlock(Block block, out Block resumeBlock, out IField stackField)
{ {
// awaitBlock: // awaitBlock:

Loading…
Cancel
Save