From 110d4592a6e38ce217a8dece85925e12aa4c5a51 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 9 May 2018 21:34:08 +0200 Subject: [PATCH] Add delayed type inference step for stack slots (in RemoveDeadVariableInit). --- .../IL/Transforms/RemoveDeadVariableInit.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs b/ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs index 91ed54025..52ecb6e81 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Linq; using ICSharpCode.Decompiler.FlowAnalysis; +using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms { @@ -27,6 +28,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// (=the initial value is a dead store). /// /// In yield return generators, additionally removes dead 'V = null;' assignments. + /// + /// Additionally infers IType of stack slots that have StackType.Ref /// public class RemoveDeadVariableInit : IILTransform { @@ -66,6 +69,26 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } } + + // Try to infer IType of stack slots that are of StackType.Ref: + foreach (var v in function.Variables) { + if (v.Kind == VariableKind.StackSlot && v.StackType == StackType.Ref && v.AddressCount == 0) { + IType newType = null; + // Multiple store are possible in case of (c ? ref a : ref b) += 1, for example. + foreach (var stloc in v.StoreInstructions.OfType()) { + var inferredType = stloc.Value.InferType(); + // cancel, if types of values do not match exactly + if (newType != null && !newType.Equals(inferredType)) { + newType = SpecialType.UnknownType; + break; + } + newType = inferredType; + } + // Only overwrite existing type, if a "better" type was found. + if (newType != null && newType != SpecialType.UnknownType) + v.Type = newType; + } + } } } }