diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index 51f32fa88..bab4c163a 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -743,12 +743,6 @@ namespace ICSharpCode.Decompiler.IL base.Disconnected(); } - internal override void CheckInvariant(ILPhase phase) - { - base.CheckInvariant(phase); - Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function)); - Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable); - } public static readonly SlotInfo InitSlot = new SlotInfo("Init", canInlineInto: true); ILInstruction init; public ILInstruction Init { @@ -851,6 +845,12 @@ namespace ICSharpCode.Decompiler.IL var o = other as PinnedRegion; return o != null && variable == o.variable && this.init.PerformMatch(o.init, ref match) && this.body.PerformMatch(o.body, ref match); } + internal override void CheckInvariant(ILPhase phase) + { + base.CheckInvariant(phase); + Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function)); + Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable); + } } } namespace ICSharpCode.Decompiler.IL @@ -1771,12 +1771,6 @@ namespace ICSharpCode.Decompiler.IL base.Disconnected(); } - internal override void CheckInvariant(ILPhase phase) - { - base.CheckInvariant(phase); - Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function)); - Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable); - } public static readonly SlotInfo ResourceExpressionSlot = new SlotInfo("ResourceExpression", canInlineInto: true); ILInstruction resourceExpression; public ILInstruction ResourceExpression { @@ -1868,6 +1862,12 @@ namespace ICSharpCode.Decompiler.IL var o = other as UsingInstruction; return o != null && variable == o.variable && this.resourceExpression.PerformMatch(o.resourceExpression, ref match) && this.body.PerformMatch(o.body, ref match); } + internal override void CheckInvariant(ILPhase phase) + { + base.CheckInvariant(phase); + Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function)); + Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable); + } } } namespace ICSharpCode.Decompiler.IL @@ -2107,12 +2107,6 @@ namespace ICSharpCode.Decompiler.IL base.Disconnected(); } - internal override void CheckInvariant(ILPhase phase) - { - base.CheckInvariant(phase); - Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function)); - Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable); - } public override StackType ResultType { get { return variable.StackType; } } protected override InstructionFlags ComputeFlags() { @@ -2147,6 +2141,12 @@ namespace ICSharpCode.Decompiler.IL var o = other as LdLoc; return o != null && variable == o.variable; } + internal override void CheckInvariant(ILPhase phase) + { + base.CheckInvariant(phase); + Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function)); + Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable); + } } } namespace ICSharpCode.Decompiler.IL @@ -2192,12 +2192,6 @@ namespace ICSharpCode.Decompiler.IL base.Disconnected(); } - internal override void CheckInvariant(ILPhase phase) - { - base.CheckInvariant(phase); - Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function)); - Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable); - } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { ILRange.WriteTo(output, options); @@ -2222,6 +2216,12 @@ namespace ICSharpCode.Decompiler.IL var o = other as LdLoca; return o != null && variable == o.variable; } + internal override void CheckInvariant(ILPhase phase) + { + base.CheckInvariant(phase); + Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function)); + Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable); + } } } namespace ICSharpCode.Decompiler.IL diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index 35246b94b..f6b1ea55b 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -338,6 +338,15 @@ namespace <#=opCode.Namespace#> var o = other as <#=opCode.Name#>; return <#=string.Join(" && ", opCode.PerformMatchConditions)#>; } +<# } #> +<# if (opCode.Invariants.Count > 0) { #> + internal override void CheckInvariant(ILPhase phase) + { + base.CheckInvariant(phase); +<# foreach (var invariant in opCode.Invariants) {#> + <#=invariant#> +<# } #> + } <# } #> } } @@ -485,6 +494,7 @@ namespace ICSharpCode.Decompiler.IL public bool GeneratePerformMatch = true; public List MatchParameters = new List(); public List PerformMatchConditions = new List() { "o != null" }; + public List Invariants = new List(); public string BaseClass = "ILInstruction"; public List Interfaces = new List(); @@ -680,6 +690,7 @@ namespace ICSharpCode.Decompiler.IL public bool IsCollection; public bool CanInlineInto; + public string[] ExpectedTypes; public ChildInfo(string name) { @@ -756,6 +767,14 @@ namespace ICSharpCode.Decompiler.IL + "\t}" + Environment.NewLine + "}"); } + if (children[i].ExpectedTypes?.Length > 0) { + foreach (var expectedType in children[i].ExpectedTypes) { + var expectedTypeCode = expectedType; + if (!expectedType.Contains(".")) + expectedTypeCode = "StackType." + expectedTypeCode; + opCode.Invariants.Add("Debug.Assert(" + arg + ".ResultType == " + expectedTypeCode + ");"); + } + } } opCode.WriteArguments.Add("output.Write(')');"); StringBuilder b; @@ -917,12 +936,8 @@ protected override void Disconnected() } ".Replace("Access", accessType)); if (generateCheckInvariant) { - opCode.Members.Add(@"internal override void CheckInvariant(ILPhase phase) -{ - base.CheckInvariant(phase); - Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function)); - Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable); -}"); + opCode.Invariants.Add("Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function));"); + opCode.Invariants.Add("Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable);"); } }; if (accessType == "Load") {