Browse Source

add generated Match<opCode> methods

pull/728/head
Siegfried Pammer 10 years ago
parent
commit
e0fba0c94e
  1. 4
      ICSharpCode.Decompiler/IL/ILReader.cs
  2. 650
      ICSharpCode.Decompiler/IL/Instructions.cs
  3. 54
      ICSharpCode.Decompiler/IL/Instructions.tt
  4. 2
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  5. 22
      ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
  6. 2
      ICSharpCode.Decompiler/IL/Transforms/TransformStackIntoVariables.cs
  7. 1
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  8. 91
      ICSharpCode.Decompiler/Tests/StackToVariablesTests.cs

4
ICSharpCode.Decompiler/IL/ILReader.cs

@ -733,7 +733,7 @@ namespace ICSharpCode.Decompiler.IL @@ -733,7 +733,7 @@ namespace ICSharpCode.Decompiler.IL
private ILInstruction Starg(ushort v)
{
return new Void(new StLoc(Pop(), parameterVariables[v]));
return new Void(new StLoc(parameterVariables[v], Pop()));
}
private ILInstruction Ldloc(ushort v)
@ -748,7 +748,7 @@ namespace ICSharpCode.Decompiler.IL @@ -748,7 +748,7 @@ namespace ICSharpCode.Decompiler.IL
private ILInstruction Stloc(ushort v)
{
return new Void(new StLoc(Pop(), localVariables[v]));
return new Void(new StLoc(localVariables[v], Pop()));
}
private ILInstruction LdElem(ILInstruction array, ILInstruction index, IType type)

650
ICSharpCode.Decompiler/IL/Instructions.cs

@ -1196,12 +1196,15 @@ namespace ICSharpCode.Decompiler.IL @@ -1196,12 +1196,15 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Stores a value into a local variable. (starg/stloc)</summary>
public sealed partial class StLoc : ILInstruction
{
public StLoc(ILInstruction value, ILVariable variable) : base(OpCode.StLoc)
public StLoc(ILVariable variable, ILInstruction value) : base(OpCode.StLoc)
{
this.Value = value;
Debug.Assert(variable != null);
this.variable = variable;
this.Value = value;
}
readonly ILVariable variable;
/// <summary>Returns the variable operand.</summary>
public ILVariable Variable { get { return variable; } }
ILInstruction value;
public ILInstruction Value {
get { return this.value; }
@ -1248,9 +1251,6 @@ namespace ICSharpCode.Decompiler.IL @@ -1248,9 +1251,6 @@ namespace ICSharpCode.Decompiler.IL
{
Value.TransformStackIntoVariables(state);
}
readonly ILVariable variable;
/// <summary>Returns the variable operand.</summary>
public ILVariable Variable { get { return variable; } }
public override StackType ResultType { get { return variable.Type.GetStackType(); } }
protected override InstructionFlags ComputeFlags()
{
@ -3489,5 +3489,645 @@ namespace ICSharpCode.Decompiler.IL @@ -3489,5 +3489,645 @@ namespace ICSharpCode.Decompiler.IL
"ldelema",
};
}
partial class ILInstruction
{
public bool MatchNop()
{
var inst = this as Nop;
if (inst != null) {
return true;
}
return false;
}
public bool MatchPop()
{
var inst = this as Pop;
if (inst != null) {
return true;
}
return false;
}
public bool MatchPeek()
{
var inst = this as Peek;
if (inst != null) {
return true;
}
return false;
}
public bool MatchVoid(out ILInstruction argument)
{
var inst = this as Void;
if (inst != null) {
argument = inst.Argument;
return true;
}
argument = default(ILInstruction);
return false;
}
public bool MatchLogicNot(out ILInstruction argument)
{
var inst = this as LogicNot;
if (inst != null) {
argument = inst.Argument;
return true;
}
argument = default(ILInstruction);
return false;
}
public bool MatchAdd(out ILInstruction left, out ILInstruction right)
{
var inst = this as Add;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchSub(out ILInstruction left, out ILInstruction right)
{
var inst = this as Sub;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchMul(out ILInstruction left, out ILInstruction right)
{
var inst = this as Mul;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchDiv(out ILInstruction left, out ILInstruction right)
{
var inst = this as Div;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchRem(out ILInstruction left, out ILInstruction right)
{
var inst = this as Rem;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchBitAnd(out ILInstruction left, out ILInstruction right)
{
var inst = this as BitAnd;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchBitOr(out ILInstruction left, out ILInstruction right)
{
var inst = this as BitOr;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchBitXor(out ILInstruction left, out ILInstruction right)
{
var inst = this as BitXor;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchBitNot(out ILInstruction argument)
{
var inst = this as BitNot;
if (inst != null) {
argument = inst.Argument;
return true;
}
argument = default(ILInstruction);
return false;
}
public bool MatchArglist()
{
var inst = this as Arglist;
if (inst != null) {
return true;
}
return false;
}
public bool MatchTryCatchHandler(out ILInstruction filter, out ILInstruction body, out ILVariable variable)
{
var inst = this as TryCatchHandler;
if (inst != null) {
filter = inst.Filter;
body = inst.Body;
variable = inst.Variable;
return true;
}
filter = default(ILInstruction);
body = default(ILInstruction);
variable = default(ILVariable);
return false;
}
public bool MatchDebugBreak()
{
var inst = this as DebugBreak;
if (inst != null) {
return true;
}
return false;
}
public bool MatchCeq(out ILInstruction left, out ILInstruction right)
{
var inst = this as Ceq;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchCgt(out ILInstruction left, out ILInstruction right)
{
var inst = this as Cgt;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchCgt_Un(out ILInstruction left, out ILInstruction right)
{
var inst = this as Cgt_Un;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchClt(out ILInstruction left, out ILInstruction right)
{
var inst = this as Clt;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchClt_Un(out ILInstruction left, out ILInstruction right)
{
var inst = this as Clt_Un;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchCkfinite(out ILInstruction argument)
{
var inst = this as Ckfinite;
if (inst != null) {
argument = inst.Argument;
return true;
}
argument = default(ILInstruction);
return false;
}
public bool MatchLdLoc(out ILVariable variable)
{
var inst = this as LdLoc;
if (inst != null) {
variable = inst.Variable;
return true;
}
variable = default(ILVariable);
return false;
}
public bool MatchLdLoca(out ILVariable variable)
{
var inst = this as LdLoca;
if (inst != null) {
variable = inst.Variable;
return true;
}
variable = default(ILVariable);
return false;
}
public bool MatchStLoc(out ILVariable variable, out ILInstruction value)
{
var inst = this as StLoc;
if (inst != null) {
variable = inst.Variable;
value = inst.Value;
return true;
}
variable = default(ILVariable);
value = default(ILInstruction);
return false;
}
public bool MatchLdStr(out string value)
{
var inst = this as LdStr;
if (inst != null) {
value = inst.Value;
return true;
}
value = default(string);
return false;
}
public bool MatchLdcI4(out int value)
{
var inst = this as LdcI4;
if (inst != null) {
value = inst.Value;
return true;
}
value = default(int);
return false;
}
public bool MatchLdcI8(out long value)
{
var inst = this as LdcI8;
if (inst != null) {
value = inst.Value;
return true;
}
value = default(long);
return false;
}
public bool MatchLdcF(out double value)
{
var inst = this as LdcF;
if (inst != null) {
value = inst.Value;
return true;
}
value = default(double);
return false;
}
public bool MatchLdNull()
{
var inst = this as LdNull;
if (inst != null) {
return true;
}
return false;
}
public bool MatchLdFtn(out IMethod method)
{
var inst = this as LdFtn;
if (inst != null) {
method = inst.Method;
return true;
}
method = default(IMethod);
return false;
}
public bool MatchLdVirtFtn(out ILInstruction argument, out IMethod method)
{
var inst = this as LdVirtFtn;
if (inst != null) {
argument = inst.Argument;
method = inst.Method;
return true;
}
argument = default(ILInstruction);
method = default(IMethod);
return false;
}
public bool MatchLdTypeToken(out IType type)
{
var inst = this as LdTypeToken;
if (inst != null) {
type = inst.Type;
return true;
}
type = default(IType);
return false;
}
public bool MatchLdMemberToken(out IMember member)
{
var inst = this as LdMemberToken;
if (inst != null) {
member = inst.Member;
return true;
}
member = default(IMember);
return false;
}
public bool MatchLocAlloc(out ILInstruction argument)
{
var inst = this as LocAlloc;
if (inst != null) {
argument = inst.Argument;
return true;
}
argument = default(ILInstruction);
return false;
}
public bool MatchShl(out ILInstruction left, out ILInstruction right)
{
var inst = this as Shl;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchShr(out ILInstruction left, out ILInstruction right)
{
var inst = this as Shr;
if (inst != null) {
left = inst.Left;
right = inst.Right;
return true;
}
left = default(ILInstruction);
right = default(ILInstruction);
return false;
}
public bool MatchLdFld(out ILInstruction target, out IField field)
{
var inst = this as LdFld;
if (inst != null) {
target = inst.Target;
field = inst.Field;
return true;
}
target = default(ILInstruction);
field = default(IField);
return false;
}
public bool MatchLdFlda(out ILInstruction target, out IField field)
{
var inst = this as LdFlda;
if (inst != null) {
target = inst.Target;
field = inst.Field;
return true;
}
target = default(ILInstruction);
field = default(IField);
return false;
}
public bool MatchStFld(out ILInstruction target, out ILInstruction value, out IField field)
{
var inst = this as StFld;
if (inst != null) {
target = inst.Target;
value = inst.Value;
field = inst.Field;
return true;
}
target = default(ILInstruction);
value = default(ILInstruction);
field = default(IField);
return false;
}
public bool MatchLdsFld(out IField field)
{
var inst = this as LdsFld;
if (inst != null) {
field = inst.Field;
return true;
}
field = default(IField);
return false;
}
public bool MatchLdsFlda(out IField field)
{
var inst = this as LdsFlda;
if (inst != null) {
field = inst.Field;
return true;
}
field = default(IField);
return false;
}
public bool MatchStsFld(out ILInstruction value, out IField field)
{
var inst = this as StsFld;
if (inst != null) {
value = inst.Value;
field = inst.Field;
return true;
}
value = default(ILInstruction);
field = default(IField);
return false;
}
public bool MatchCastClass(out ILInstruction argument, out IType type)
{
var inst = this as CastClass;
if (inst != null) {
argument = inst.Argument;
type = inst.Type;
return true;
}
argument = default(ILInstruction);
type = default(IType);
return false;
}
public bool MatchIsInst(out ILInstruction argument, out IType type)
{
var inst = this as IsInst;
if (inst != null) {
argument = inst.Argument;
type = inst.Type;
return true;
}
argument = default(ILInstruction);
type = default(IType);
return false;
}
public bool MatchLdObj(out ILInstruction target, out IType type)
{
var inst = this as LdObj;
if (inst != null) {
target = inst.Target;
type = inst.Type;
return true;
}
target = default(ILInstruction);
type = default(IType);
return false;
}
public bool MatchStObj(out ILInstruction target, out ILInstruction value, out IType type)
{
var inst = this as StObj;
if (inst != null) {
target = inst.Target;
value = inst.Value;
type = inst.Type;
return true;
}
target = default(ILInstruction);
value = default(ILInstruction);
type = default(IType);
return false;
}
public bool MatchBox(out ILInstruction argument, out IType type)
{
var inst = this as Box;
if (inst != null) {
argument = inst.Argument;
type = inst.Type;
return true;
}
argument = default(ILInstruction);
type = default(IType);
return false;
}
public bool MatchUnbox(out ILInstruction argument, out IType type)
{
var inst = this as Unbox;
if (inst != null) {
argument = inst.Argument;
type = inst.Type;
return true;
}
argument = default(ILInstruction);
type = default(IType);
return false;
}
public bool MatchUnboxAny(out ILInstruction argument, out IType type)
{
var inst = this as UnboxAny;
if (inst != null) {
argument = inst.Argument;
type = inst.Type;
return true;
}
argument = default(ILInstruction);
type = default(IType);
return false;
}
public bool MatchNewArr(out IType type, out ILInstruction size)
{
var inst = this as NewArr;
if (inst != null) {
type = inst.Type;
size = inst.Size;
return true;
}
type = default(IType);
size = default(ILInstruction);
return false;
}
public bool MatchDefaultValue(out IType type)
{
var inst = this as DefaultValue;
if (inst != null) {
type = inst.Type;
return true;
}
type = default(IType);
return false;
}
public bool MatchThrow(out ILInstruction argument)
{
var inst = this as Throw;
if (inst != null) {
argument = inst.Argument;
return true;
}
argument = default(ILInstruction);
return false;
}
public bool MatchRethrow()
{
var inst = this as Rethrow;
if (inst != null) {
return true;
}
return false;
}
public bool MatchSizeOf(out IType type)
{
var inst = this as SizeOf;
if (inst != null) {
type = inst.Type;
return true;
}
type = default(IType);
return false;
}
public bool MatchLdLen(out ILInstruction array)
{
var inst = this as LdLen;
if (inst != null) {
array = inst.Array;
return true;
}
array = default(ILInstruction);
return false;
}
public bool MatchLdElema(out ILInstruction array, out ILInstruction index, out IType type)
{
var inst = this as LdElema;
if (inst != null) {
array = inst.Array;
index = inst.Index;
type = inst.Type;
return true;
}
array = default(ILInstruction);
index = default(ILInstruction);
type = default(IType);
return false;
}
}
}

54
ICSharpCode.Decompiler/IL/Instructions.tt

@ -110,7 +110,7 @@ @@ -110,7 +110,7 @@
new OpCode("ldloca", "Loads the address of a local variable. (ldarga/ldloca)",
CustomClassName("LdLoca"), NoArguments, ResultType("Ref"), HasVariableOperand),
new OpCode("stloc", "Stores a value into a local variable. (starg/stloc)",
CustomClassName("StLoc"), CustomArguments("value"), HasVariableOperand,
CustomClassName("StLoc"), HasVariableOperand, CustomArguments("value"),
ResultType("variable.Type.GetStackType()")),
new OpCode("ldstr", "Loads a constant string.",
CustomClassName("LdStr"), LoadConstant("string"), ResultType("O")),
@ -314,6 +314,28 @@ namespace ICSharpCode.Decompiler.IL @@ -314,6 +314,28 @@ namespace ICSharpCode.Decompiler.IL
<# } #>
};
}
partial class ILInstruction
{
<# foreach (OpCode opCode in opCodes) { #>
<# if (opCode.GenerateMatch) { #>
public bool Match<#=opCode.Name#>(<#=string.Join(", ", opCode.MatchParameters)#>)
{
var inst = this as <#=opCode.Name#>;
if (inst != null) {
<# foreach (var parameter in opCode.MatchParameters) {#>
<#=parameter.Name#> = inst.<#=parameter.FieldName#>;
<# }#>
return true;
}
<# foreach (var parameter in opCode.MatchParameters) {#>
<#=parameter.Name#> = default(<#=parameter.TypeName#>);
<# }#>
return false;
}
<# }
} #>
}
}
<#+
@ -370,6 +392,9 @@ namespace ICSharpCode.Decompiler.IL @@ -370,6 +392,9 @@ namespace ICSharpCode.Decompiler.IL
public string ConstructorModifier = "public";
public List<string> ConstructorParameters = new List<string>();
public List<string> ConstructorBody = new List<string>();
public bool GenerateMatch = true;
public List<MatchParamInfo> MatchParameters = new List<MatchParamInfo>();
public string BaseClass = "ILInstruction";
public List<string> Interfaces = new List<string>();
@ -378,7 +403,7 @@ namespace ICSharpCode.Decompiler.IL @@ -378,7 +403,7 @@ namespace ICSharpCode.Decompiler.IL
public List<string> Flags = new List<string>();
public bool GenerateComputeFlags = true;
public bool GenerateAcceptVisitor = true;
public bool GenerateWriteTo = false;
@ -398,6 +423,18 @@ namespace ICSharpCode.Decompiler.IL @@ -398,6 +423,18 @@ namespace ICSharpCode.Decompiler.IL
}
}
class MatchParamInfo
{
public string TypeName;
public string Name;
public string FieldName;
public override string ToString()
{
return "out " + TypeName + " " + Name;
}
}
static Action<OpCode> CustomClassName(string name)
{
return opCode => {
@ -414,6 +451,7 @@ namespace ICSharpCode.Decompiler.IL @@ -414,6 +451,7 @@ namespace ICSharpCode.Decompiler.IL
static Action<OpCode> CustomConstructor = opCode => {
opCode.GenerateConstructor = false;
opCode.GenerateMatch = false;
};
static Action<OpCode> CustomWriteTo = opCode => {
@ -479,6 +517,7 @@ namespace ICSharpCode.Decompiler.IL @@ -479,6 +517,7 @@ namespace ICSharpCode.Decompiler.IL
opCode.BaseClass = "UnaryInstruction";
opCode.Flags.Add("base.ComputeFlags()");
opCode.ConstructorParameters.Add("ILInstruction argument");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "ILInstruction", Name = "argument", FieldName = "Argument" });
opCode.BaseConstructorArguments.Add("argument");
opCode.WriteArguments.Add("output.Write('(');");
opCode.WriteArguments.Add("Argument.WriteTo(output);");
@ -493,6 +532,8 @@ namespace ICSharpCode.Decompiler.IL @@ -493,6 +532,8 @@ namespace ICSharpCode.Decompiler.IL
opCode.ConstructorParameters.Add("ILInstruction right");
opCode.BaseConstructorArguments.Add("left");
opCode.BaseConstructorArguments.Add("right");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "ILInstruction", Name = "left", FieldName = "Left" });
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "ILInstruction", Name = "right", FieldName = "Right" });
opCode.WriteArguments.Add("output.Write('(');");
opCode.WriteArguments.Add("Left.WriteTo(output);");
opCode.WriteArguments.Add("output.Write(\", \");");
@ -550,6 +591,7 @@ namespace ICSharpCode.Decompiler.IL @@ -550,6 +591,7 @@ namespace ICSharpCode.Decompiler.IL
opCode.Flags.Add(arg + ".Flags");
opCode.ConstructorParameters.Add("ILInstruction " + arg);
opCode.ConstructorBody.Add("this." + argProp + " = " + arg + ";");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "ILInstruction", Name = arg, FieldName = argProp });
if (i > 0)
opCode.WriteArguments.Add("output.Write(\", \");");
opCode.WriteArguments.Add("this." + arg + ".WriteTo(output);");
@ -647,6 +689,7 @@ namespace ICSharpCode.Decompiler.IL @@ -647,6 +689,7 @@ namespace ICSharpCode.Decompiler.IL
opCode.ConstructorModifier = "protected";
opCode.ConstructorParameters.Add("OpCode opCode");
opCode.BaseConstructorArguments.Add("opCode");
opCode.GenerateMatch = false;
};
// SideEffect trait: the instruction has a non-local side effect
@ -658,6 +701,7 @@ namespace ICSharpCode.Decompiler.IL @@ -658,6 +701,7 @@ namespace ICSharpCode.Decompiler.IL
opCode.BaseClass = "CallInstruction";
opCode.ConstructorParameters.Add("IMethod method");
opCode.BaseConstructorArguments.Add("method");
opCode.GenerateMatch = false;
};
// HasVariableOperand trait: the instruction refers to a local variable
@ -666,6 +710,7 @@ namespace ICSharpCode.Decompiler.IL @@ -666,6 +710,7 @@ namespace ICSharpCode.Decompiler.IL
opCode.Members.Add("readonly ILVariable variable;");
opCode.ConstructorBody.Add("Debug.Assert(variable != null);");
opCode.ConstructorBody.Add("this.variable = variable;");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "ILVariable", Name = "variable", FieldName = "Variable" });
opCode.Members.Add("/// <summary>Returns the variable operand.</summary>" + Environment.NewLine
+ "public ILVariable Variable { get { return variable; } }");
opCode.GenerateWriteTo = true;
@ -677,6 +722,7 @@ namespace ICSharpCode.Decompiler.IL @@ -677,6 +722,7 @@ namespace ICSharpCode.Decompiler.IL
opCode.ConstructorParameters.Add("IField field");
opCode.Members.Add("readonly IField field;");
opCode.ConstructorBody.Add("this.field = field;");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "IField", Name = "field", FieldName = "Field" });
opCode.Members.Add("/// <summary>Returns the field operand.</summary>" + Environment.NewLine
+ "public IField Field { get { return field; } }");
opCode.GenerateWriteTo = true;
@ -688,6 +734,7 @@ namespace ICSharpCode.Decompiler.IL @@ -688,6 +734,7 @@ namespace ICSharpCode.Decompiler.IL
opCode.ConstructorParameters.Add("IType type");
opCode.Members.Add("readonly IType type;");
opCode.ConstructorBody.Add("this.type = type;");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "IType", Name = "type", FieldName = "Type" });
opCode.Members.Add("/// <summary>Returns the type operand.</summary>" + Environment.NewLine
+ "public IType Type { get { return type; } }");
opCode.GenerateWriteTo = true;
@ -699,6 +746,7 @@ namespace ICSharpCode.Decompiler.IL @@ -699,6 +746,7 @@ namespace ICSharpCode.Decompiler.IL
opCode.ConstructorParameters.Add("IMethod method");
opCode.Members.Add("readonly IMethod method;");
opCode.ConstructorBody.Add("this.method = method;");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "IMethod", Name = "method", FieldName = "Method" });
opCode.Members.Add("/// <summary>Returns the method operand.</summary>" + Environment.NewLine
+ "public IMethod Method { get { return method; } }");
opCode.GenerateWriteTo = true;
@ -710,6 +758,7 @@ namespace ICSharpCode.Decompiler.IL @@ -710,6 +758,7 @@ namespace ICSharpCode.Decompiler.IL
opCode.ConstructorParameters.Add("IMember member");
opCode.Members.Add("readonly IMember member;");
opCode.ConstructorBody.Add("this.member = member;");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "IMember", Name = "member", FieldName = "Member" });
opCode.Members.Add("/// <summary>Returns the token operand.</summary>" + Environment.NewLine
+ "public IMember Member { get { return member; } }");
opCode.GenerateWriteTo = true;
@ -723,6 +772,7 @@ namespace ICSharpCode.Decompiler.IL @@ -723,6 +772,7 @@ namespace ICSharpCode.Decompiler.IL
return opCode => {
NoArguments(opCode);
opCode.ConstructorParameters.Add(operandType + " value");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = operandType, Name = "value", FieldName = "Value" });
opCode.Members.Add("public readonly " + operandType + " Value;");
opCode.ConstructorBody.Add("this.Value = value;");
opCode.GenerateWriteTo = true;

2
ICSharpCode.Decompiler/IL/Instructions/Block.cs

@ -214,7 +214,7 @@ namespace ICSharpCode.Decompiler.IL @@ -214,7 +214,7 @@ namespace ICSharpCode.Decompiler.IL
var type = state.TypeSystem.Compilation.FindType(inst.ResultType.ToKnownTypeCode());
ILVariable variable = new ILVariable(VariableKind.StackSlot, type, state.Variables.Count);
state.Variables.Push(variable);
inst = new Void(new StLoc(inst, variable));
inst = new Void(new StLoc(variable, inst));
}
Instructions[i] = inst;
if (inst.HasFlag(InstructionFlags.EndPointUnreachable))

22
ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs

@ -27,34 +27,12 @@ namespace ICSharpCode.Decompiler.IL @@ -27,34 +27,12 @@ namespace ICSharpCode.Decompiler.IL
return OpCode == OpCode.LdcI4 && ((LdcI4)this).Value == val;
}
public bool MatchLdcI4(out int val)
{
var inst = this as LdcI4;
if (inst != null) {
val = inst.Value;
return true;
}
val = 0;
return false;
}
public bool MatchLdLoc(ILVariable variable)
{
var inst = this as LdLoc;
return inst != null && inst.Variable == variable;
}
public bool MatchLdLoc(out ILVariable variable)
{
var inst = this as LdLoc;
if (inst != null) {
variable = inst.Variable;
return true;
}
variable = null;
return false;
}
public bool MatchLdThis()
{
var inst = this as LdLoc;

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

@ -86,7 +86,7 @@ namespace ICSharpCode.Decompiler.IL @@ -86,7 +86,7 @@ namespace ICSharpCode.Decompiler.IL
var variable = state.UnionFind.Find(inst.Variable);
if (variables.Add(variable))
variable.Name = "S_" + (variables.Count - 1);
inst.ReplaceWith(new StLoc(inst.Value, variable));
inst.ReplaceWith(new StLoc(variable, inst.Value));
}
}
}

1
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -102,7 +102,6 @@ @@ -102,7 +102,6 @@
<Compile Include="Helpers\TypeSystemHelper.cs" />
<Compile Include="ILTransforms\InliningTests.cs" />
<Compile Include="Loops.cs" />
<Compile Include="StackToVariablesTests.cs" />
<Compile Include="TestCases\CompoundAssignment.cs" />
<Compile Include="TestCases\ControlFlow.cs" />
<Compile Include="TestCases\Generics.cs" />

91
ICSharpCode.Decompiler/Tests/StackToVariablesTests.cs

@ -1,91 +0,0 @@ @@ -1,91 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework;
using ICSharpCode.Decompiler.Tests.Helpers;
namespace ICSharpCode.Decompiler.Tests
{
[TestFixture]
public class StackToVariablesTests
{
ILVariable StackSlot<T>(int index)
{
return new ILVariable(VariableKind.StackSlot, TypeSystem.FromReflection(typeof(T)), index) {
Name = "S_" + index
};
}
[Test]
public void Test1()
{
Block input = new Block {
Instructions = {
new LdcI4(1),
new LdcI4(2),
new LdcI4(3),
new LdcI4(4),
new Call(TypeSystem.Action<int, int, int, int>()) {
Arguments = {
new Pop(StackType.I4),
new Block { FinalInstruction = new Pop(StackType.I4) },
new Block { FinalInstruction = new Pop(StackType.I4) },
new Pop(StackType.I4)
}
}
}
};
// F(3, 2, 1, 4)
Block expected = new Block {
Instructions = {
new Void(new StLoc(new LdcI4(1), StackSlot<int>(0))),
new Void(new StLoc(new LdcI4(2), StackSlot<int>(1))),
new Void(new StLoc(new LdcI4(3), StackSlot<int>(2))),
new Void(new StLoc(new LdcI4(4), StackSlot<int>(3))),
new Call(TypeSystem.Action<int, int, int, int>()) {
Arguments = {
new LdLoc(StackSlot<int>(2)),
new Block { FinalInstruction = new LdLoc(StackSlot<int>(1)) },
new Block { FinalInstruction = new LdLoc(StackSlot<int>(0)) },
new LdLoc(StackSlot<int>(3))
}
}
}
};
TestStackIntoVariablesTransform(input, expected);
}
[Test]
public void Test2()
{
Block input = new Block {
Instructions = {
new LdcI4(1),
new LdcI4(2),
new Add(new Pop(StackType.I4), new Pop(StackType.I4), false, Sign.Signed)
}
};
Block expected = new Block {
Instructions = {
new Void(new StLoc(new LdcI4(1), StackSlot<int>(0))),
new Void(new StLoc(new LdcI4(2), StackSlot<int>(1))),
new Void(new StLoc(new Add(new LdLoc(StackSlot<int>(0)), new LdLoc(StackSlot<int>(1)), false, Sign.Signed), StackSlot<int>(2)))
}
};
TestStackIntoVariablesTransform(input, expected);
}
void TestStackIntoVariablesTransform(Block input, Block expected)
{
input.AddRef();
ILFunction function = new ILFunction(null, input);
var context = new ILTransformContext { TypeSystem = TypeSystem.Instance };
new TransformStackIntoVariables().Run(function, context);
Assert.AreEqual(expected.ToString(), input.ToString());
}
}
}
Loading…
Cancel
Save