Browse Source

Add OpCode.Invariants: generalized mechanism for overriding CheckInvariant

pull/1278/head
Siegfried Pammer 8 years ago
parent
commit
38b073ee9a
  1. 48
      ICSharpCode.Decompiler/IL/Instructions.cs
  2. 27
      ICSharpCode.Decompiler/IL/Instructions.tt

48
ICSharpCode.Decompiler/IL/Instructions.cs

@ -743,12 +743,6 @@ namespace ICSharpCode.Decompiler.IL
base.Disconnected(); 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); public static readonly SlotInfo InitSlot = new SlotInfo("Init", canInlineInto: true);
ILInstruction init; ILInstruction init;
public ILInstruction Init { public ILInstruction Init {
@ -851,6 +845,12 @@ namespace ICSharpCode.Decompiler.IL
var o = other as PinnedRegion; 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); 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 namespace ICSharpCode.Decompiler.IL
@ -1771,12 +1771,6 @@ namespace ICSharpCode.Decompiler.IL
base.Disconnected(); 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); public static readonly SlotInfo ResourceExpressionSlot = new SlotInfo("ResourceExpression", canInlineInto: true);
ILInstruction resourceExpression; ILInstruction resourceExpression;
public ILInstruction ResourceExpression { public ILInstruction ResourceExpression {
@ -1868,6 +1862,12 @@ namespace ICSharpCode.Decompiler.IL
var o = other as UsingInstruction; 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); 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 namespace ICSharpCode.Decompiler.IL
@ -2107,12 +2107,6 @@ namespace ICSharpCode.Decompiler.IL
base.Disconnected(); 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; } } public override StackType ResultType { get { return variable.StackType; } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
@ -2147,6 +2141,12 @@ namespace ICSharpCode.Decompiler.IL
var o = other as LdLoc; var o = other as LdLoc;
return o != null && variable == o.variable; 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 namespace ICSharpCode.Decompiler.IL
@ -2192,12 +2192,6 @@ namespace ICSharpCode.Decompiler.IL
base.Disconnected(); 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) public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{ {
ILRange.WriteTo(output, options); ILRange.WriteTo(output, options);
@ -2222,6 +2216,12 @@ namespace ICSharpCode.Decompiler.IL
var o = other as LdLoca; var o = other as LdLoca;
return o != null && variable == o.variable; 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 namespace ICSharpCode.Decompiler.IL

27
ICSharpCode.Decompiler/IL/Instructions.tt

@ -338,6 +338,15 @@ namespace <#=opCode.Namespace#>
var o = other as <#=opCode.Name#>; var o = other as <#=opCode.Name#>;
return <#=string.Join(" && ", opCode.PerformMatchConditions)#>; 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 bool GeneratePerformMatch = true;
public List<MatchParamInfo> MatchParameters = new List<MatchParamInfo>(); public List<MatchParamInfo> MatchParameters = new List<MatchParamInfo>();
public List<string> PerformMatchConditions = new List<string>() { "o != null" }; public List<string> PerformMatchConditions = new List<string>() { "o != null" };
public List<string> Invariants = new List<string>();
public string BaseClass = "ILInstruction"; public string BaseClass = "ILInstruction";
public List<string> Interfaces = new List<string>(); public List<string> Interfaces = new List<string>();
@ -680,6 +690,7 @@ namespace ICSharpCode.Decompiler.IL
public bool IsCollection; public bool IsCollection;
public bool CanInlineInto; public bool CanInlineInto;
public string[] ExpectedTypes;
public ChildInfo(string name) public ChildInfo(string name)
{ {
@ -756,6 +767,14 @@ namespace ICSharpCode.Decompiler.IL
+ "\t}" + Environment.NewLine + "\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(')');"); opCode.WriteArguments.Add("output.Write(')');");
StringBuilder b; StringBuilder b;
@ -917,12 +936,8 @@ protected override void Disconnected()
} }
".Replace("Access", accessType)); ".Replace("Access", accessType));
if (generateCheckInvariant) { if (generateCheckInvariant) {
opCode.Members.Add(@"internal override void CheckInvariant(ILPhase phase) 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);");
base.CheckInvariant(phase);
Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function));
Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable);
}");
} }
}; };
if (accessType == "Load") { if (accessType == "Load") {

Loading…
Cancel
Save