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. 14
      ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs

2
BuildTools/update-assemblyinfo.ps1

@ -53,7 +53,7 @@ function gitCommitHash() { @@ -53,7 +53,7 @@ function gitCommitHash() {
}
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";
}

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

@ -998,7 +998,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -998,7 +998,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// continue matching call get_IsCompleted(ldloca awaiterVar)
if (!MatchCall(condition, "get_IsCompleted", out var isCompletedArgs) || isCompletedArgs.Count != 1)
return;
if (!isCompletedArgs[0].MatchLdLocRef(awaiterVar))
if (!UnwrapConvUnknown(isCompletedArgs[0]).MatchLdLocRef(awaiterVar))
return;
// Check awaitBlock and resumeBlock:
if (!awaitBlocks.TryGetValue(awaitBlock, out var awaitBlockData))
@ -1016,14 +1016,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1016,14 +1016,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return;
if (!MatchCall(getResultCall, "GetResult", out var getResultArgs) || getResultArgs.Count != 1)
return;
if (!getResultArgs[0].MatchLdLocRef(awaiterVar))
if (!UnwrapConvUnknown(getResultArgs[0]).MatchLdLocRef(awaiterVar))
return;
// All checks successful, let's transform.
context.Step("Transform await pattern", block);
block.Instructions.RemoveAt(block.Instructions.Count - 3); // remove getAwaiter call
block.Instructions.RemoveAt(block.Instructions.Count - 2); // remove if (isCompleted)
((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.GetAwaiterMethod = getAwaiterCall.Method;
getResultCall.ReplaceWith(awaitInst);
@ -1036,6 +1036,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -1036,6 +1036,14 @@ 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)
{
// awaitBlock:

Loading…
Cancel
Save