Browse Source

Fix #1858, Fix #2188: Remove variables that contain copies of display-class variables.

pull/2426/head
Siegfried Pammer 4 years ago
parent
commit
62fc4bc1a3
  1. 26
      ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

26
ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

@ -106,6 +106,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ILTransformContext context;
ITypeResolveContext decompilationContext;
readonly Dictionary<ILVariable, DisplayClass> displayClasses = new Dictionary<ILVariable, DisplayClass>();
readonly Dictionary<ILVariable, ILVariable> displayClassCopyMap = new Dictionary<ILVariable, ILVariable>();
void IILTransform.Run(ILFunction function, ILTransformContext context)
{
@ -127,6 +128,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
void ClearState()
{
displayClasses.Clear();
displayClassCopyMap.Clear();
this.decompilationContext = null;
this.context = null;
}
@ -234,6 +236,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return declaredVar.CanPropagate;
}
return false;
case StLoc stloc when stloc.Variable.IsSingleDefinition && stloc.Value == use:
displayClassCopyMap[stloc.Variable] = v;
return true;
default:
return false;
}
@ -784,7 +789,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// in some cases (e.g. if inlining fails), there can be a reference to a display class in a stack slot,
// in that case it is necessary to resolve the reference and iff it can be propagated, replace all loads
// of the single-definition.
var referencedDisplayClass = ResolveVariableToPropagate(inst.Value);
if (!displayClassCopyMap.TryGetValue(inst.Variable, out var referencedDisplayClass))
{
referencedDisplayClass = ResolveVariableToPropagate(inst.Value);
}
if (referencedDisplayClass != null && displayClasses.TryGetValue(referencedDisplayClass, out _))
{
context.Step($"Propagate reference to {referencedDisplayClass.Name} in {inst.Variable}", inst);
@ -814,6 +822,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return;
}
}
if (inst.Value is LdLoc ldLoc && ldLoc.Variable is { IsSingleDefinition: true, CaptureScope: null }
&& ldLoc.Variable.StoreInstructions.FirstOrDefault() is StLoc stloc
&& stloc.Parent is Block block)
{
ILInlining.InlineOneIfPossible(block, stloc.ChildIndex, InliningOptions.None, context);
}
}
base.VisitStObj(inst);
EarlyExpressionTransforms.StObjToStLoc(inst, context);
@ -828,9 +842,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
private bool IsDisplayClassLoad(ILInstruction target, out ILVariable variable)
{
// We cannot use MatchLdLocRef here because local functions use ref parameters
if (target.MatchLdLoc(out variable) || target.MatchLdLoca(out variable))
return true;
return false;
if (!target.MatchLdLoc(out variable) && !target.MatchLdLoca(out variable))
return false;
if (displayClassCopyMap.TryGetValue(variable, out ILVariable other))
variable = other;
return true;
}
private bool IsDisplayClassFieldAccess(ILInstruction inst,
@ -839,7 +855,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
displayClass = null;
displayClassVar = null;
field = null;
if (!(inst is LdFlda ldflda))
if (inst is not LdFlda ldflda)
return false;
field = ldflda.Field;
return IsDisplayClassLoad(ldflda.Target, out displayClassVar)

Loading…
Cancel
Save