Browse Source

[async] Fix await decompiler for pre-roslyn csc, at least in cases where the stack is empty during the await.

pull/850/head
Daniel Grunwald 8 years ago
parent
commit
6c7e2efa6c
  1. 2
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 28
      ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs
  3. 2
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  4. 10
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

2
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1760,7 +1760,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1760,7 +1760,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
return new UnaryOperatorExpression(UnaryOperatorType.Await, value.Expression)
.WithILInstruction(inst)
.WithRR(new ResolveResult(inst?.GetResultMethod.ReturnType ?? SpecialType.UnknownType));
.WithRR(new ResolveResult(inst.GetResultMethod?.ReturnType ?? SpecialType.UnknownType));
}
protected internal override TranslatedExpression VisitInvalidBranch(InvalidBranch inst, TranslationContext context)

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

@ -81,11 +81,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -81,11 +81,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
InlineBodyOfMoveNext(function);
// Copy-propagate temporaries holding a copy of 'this'.
foreach (var stloc in function.Descendants.OfType<StLoc>().Where(s => s.Variable.IsSingleDefinition && s.Value.MatchLdThis()).ToList()) {
CopyPropagation.Propagate(stloc, context);
}
CleanUpBodyOfMoveNext(function);
AnalyzeStateMachine(function);
DetectAwaitPattern(function);
@ -101,6 +97,26 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -101,6 +97,26 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
function.RunTransforms(CSharpDecompiler.EarlyILTransforms(), context);
}
private void CleanUpBodyOfMoveNext(ILFunction function)
{
context.StepStartGroup("CleanUpBodyOfMoveNext", function);
// Simplify stobj(ldloca) -> stloc
foreach (var stobj in function.Descendants.OfType<StObj>()) {
ExpressionTransforms.StObjToStLoc(stobj, context);
}
// Copy-propagate temporaries holding a copy of 'this'.
foreach (var stloc in function.Descendants.OfType<StLoc>().Where(s => s.Variable.IsSingleDefinition && s.Value.MatchLdThis()).ToList()) {
CopyPropagation.Propagate(stloc, context);
}
new RemoveDeadVariableInit().Run(function, context);
// Run inlining, but don't remove dead variables (they might get revived by TranslateFieldsToLocalAccess)
foreach (var block in function.Descendants.OfType<Block>()) {
ILInlining.InlineAllInBlock(block, context);
}
context.StepEndGroup();
}
#region MatchTaskCreationPattern
bool MatchTaskCreationPattern(ILFunction function)
{
@ -717,7 +733,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -717,7 +733,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
pos++;
}
if (block.Instructions[pos] is StLoc stlocCachedState) {
if (stlocCachedState.Variable.Kind == VariableKind.Local && stlocCachedState.Variable.Index == cachedStateVar.Index) {
if (stlocCachedState.Variable.Kind == VariableKind.Local && stlocCachedState.Variable.Index == cachedStateVar?.Index) {
if (stlocCachedState.Value.MatchLdLoc(m1Var) || stlocCachedState.Value.MatchLdcI4(initialState))
pos++;
}

2
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

@ -237,7 +237,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -237,7 +237,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
&& TypeUtils.IsCompatibleTypeForMemoryAccess(new ByReferenceType(v.Type), inst.Type)
&& inst.UnalignedPrefix == 0
&& !inst.IsVolatile) {
context.Step("stobj(ldloca(v), ...) => stloc(v, ...)", inst);
context.Step($"stobj(ldloca {v.Name}, ...) => stloc {v.Name}(...)", inst);
inst.ReplaceWith(new StLoc(v, inst.Value));
return true;
}

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

@ -28,24 +28,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -28,24 +28,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary>
public class ILInlining : IILTransform, IBlockTransform
{
ILTransformContext context;
public void Run(ILFunction function, ILTransformContext context)
{
this.context = context;
foreach (var block in function.Descendants.OfType<Block>()) {
InlineAllInBlock(block);
InlineAllInBlock(block, context);
}
function.Variables.RemoveDead();
}
public void Run(Block block, BlockTransformContext context)
{
this.context = context;
InlineAllInBlock(block);
InlineAllInBlock(block, context);
}
public bool InlineAllInBlock(Block block)
public static bool InlineAllInBlock(Block block, ILTransformContext context)
{
bool modified = false;
int i = 0;

Loading…
Cancel
Save