diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index e7033ad32..74414c2e5 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -879,7 +879,7 @@ namespace ICSharpCode.Decompiler.IL protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match) { var o = other as CompoundAssignmentInstruction; - return o != null && this.target.PerformMatch(o.target, ref match) && this.value.PerformMatch(o.value, ref match) && type.Equals(o.type); + return o != null && this.target.PerformMatch(o.target, ref match) && this.value.PerformMatch(o.value, ref match) && type.Equals(o.type) && CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator; } } @@ -977,7 +977,7 @@ namespace ICSharpCode.Decompiler.IL protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match) { var o = other as Leave; - return o != null; + return o != null && this.TargetContainer == o.TargetContainer; } } @@ -1103,7 +1103,7 @@ namespace ICSharpCode.Decompiler.IL protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match) { var o = other as SwitchInstruction; - return o != null; + return o != null && Value.PerformMatch(o.Value, ref match) && Patterns.ListMatch.DoMatch(this.Sections, o.Sections, ref match); } } @@ -1173,7 +1173,7 @@ namespace ICSharpCode.Decompiler.IL protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match) { var o = other as SwitchSection; - return o != null && this.body.PerformMatch(o.body, ref match); + return o != null && this.body.PerformMatch(o.body, ref match) && this.Labels.Intervals.SequenceEqual(o.Labels.Intervals); } } @@ -1196,7 +1196,7 @@ namespace ICSharpCode.Decompiler.IL protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match) { var o = other as TryCatch; - return o != null; + return o != null && TryBlock.PerformMatch(o.TryBlock, ref match) && Patterns.ListMatch.DoMatch(Handlers, o.Handlers, ref match); } } @@ -1336,7 +1336,7 @@ namespace ICSharpCode.Decompiler.IL protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match) { var o = other as TryFinally; - return o != null; + return o != null && TryBlock.PerformMatch(o.TryBlock, ref match) && finallyBlock.PerformMatch(o.finallyBlock, ref match); } } @@ -1359,7 +1359,7 @@ namespace ICSharpCode.Decompiler.IL protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match) { var o = other as TryFault; - return o != null; + return o != null && TryBlock.PerformMatch(o.TryBlock, ref match) && faultBlock.PerformMatch(o.faultBlock, ref match); } } @@ -1417,7 +1417,7 @@ namespace ICSharpCode.Decompiler.IL protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match) { var o = other as Comp; - return o != null && this.Left.PerformMatch(o.Left, ref match) && this.Right.PerformMatch(o.Right, ref match) && this.Kind == o.Kind; + return o != null && this.Left.PerformMatch(o.Left, ref match) && this.Right.PerformMatch(o.Right, ref match) && this.Kind == o.Kind && this.Sign == o.Sign; } } @@ -1517,7 +1517,7 @@ namespace ICSharpCode.Decompiler.IL protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match) { var o = other as Conv; - return o != null && this.Argument.PerformMatch(o.Argument, ref match); + return o != null && this.Argument.PerformMatch(o.Argument, ref match) && CheckForOverflow == o.CheckForOverflow && Kind == o.Kind && InputSign == o.InputSign && TargetType == o.TargetType; } } @@ -2275,7 +2275,7 @@ namespace ICSharpCode.Decompiler.IL protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match) { var o = other as Return; - return o != null; + return o != null && this.hasArgument == o.hasArgument && (!hasArgument || this.ReturnValue.PerformMatch(o.ReturnValue, ref match)); } } diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index ce516e286..768c60961 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -67,14 +67,16 @@ MatchCondition("CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator")), new OpCode("compound", "Common instruction for compound assignments.", CustomClassName("CompoundAssignmentInstruction"), CustomConstructor, CustomComputeFlags, - MayThrow, CustomArguments("target", "value"), HasTypeOperand, ResultType("type.GetStackType()"), CustomWriteTo), + MayThrow, CustomArguments("target", "value"), HasTypeOperand, ResultType("type.GetStackType()"), CustomWriteTo, + MatchCondition("CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator")), new OpCode("bit.not", "Bitwise NOT", Unary), new OpCode("arglist", "Retrieves the RuntimeArgumentHandle.", NoArguments, ResultType("O")), new OpCode("br", "Unconditional branch. goto target;", CustomClassName("Branch"), NoArguments, CustomConstructor, UnconditionalBranch, MayBranch, CustomComputeFlags, MatchCondition("this.TargetBlock == o.TargetBlock")), new OpCode("leave", "Unconditional branch to end of block container. goto container_end;, often break;", - NoArguments, CustomConstructor, UnconditionalBranch, MayBranch, CustomComputeFlags), + NoArguments, CustomConstructor, UnconditionalBranch, MayBranch, CustomComputeFlags, + MatchCondition("this.TargetContainer == o.TargetContainer")), new OpCode("if", "If statement / conditional expression. if (condition) trueExpr else falseExpr", CustomClassName("IfInstruction"), CustomChildren(new []{ @@ -83,21 +85,28 @@ new ChildInfo("falseInst"), }), CustomConstructor, CustomComputeFlags, CustomWriteTo), new OpCode("switch", "Switch statement", - CustomClassName("SwitchInstruction"), CustomConstructor, CustomComputeFlags, CustomWriteTo, ResultType("Void")), + CustomClassName("SwitchInstruction"), CustomConstructor, CustomComputeFlags, CustomWriteTo, ResultType("Void"), + MatchCondition("Value.PerformMatch(o.Value, ref match) && Patterns.ListMatch.DoMatch(this.Sections, o.Sections, ref match)")), new OpCode("switch.section", "Switch section within a switch statement", CustomClassName("SwitchSection"), CustomChildren(new [] { new ChildInfo("body") }), - CustomConstructor, CustomComputeFlags, CustomWriteTo, ResultType("Void")), + CustomConstructor, CustomComputeFlags, CustomWriteTo, ResultType("Void"), + MatchCondition("this.Labels.Intervals.SequenceEqual(o.Labels.Intervals)")), new OpCode("try.catch", "Try-catch statement.", - BaseClass("TryInstruction"), CustomConstructor, CustomComputeFlags, CustomWriteTo), + BaseClass("TryInstruction"), CustomConstructor, CustomComputeFlags, CustomWriteTo, + MatchCondition("TryBlock.PerformMatch(o.TryBlock, ref match)"), + MatchCondition("Patterns.ListMatch.DoMatch(Handlers, o.Handlers, ref match)")), new OpCode("try.catch.handler", "Catch handler within a try-catch statement.", CustomChildren(new [] { new ChildInfo("filter"), new ChildInfo("body"), }), HasVariableOperand("Store", generateCheckInvariant: false), CustomWriteTo, CustomComputeFlags), new OpCode("try.finally", "Try-finally statement", - BaseClass("TryInstruction"), CustomConstructor, CustomWriteTo, CustomComputeFlags), + BaseClass("TryInstruction"), CustomConstructor, CustomWriteTo, CustomComputeFlags, + MatchCondition("TryBlock.PerformMatch(o.TryBlock, ref match) && finallyBlock.PerformMatch(o.finallyBlock, ref match)")), new OpCode("try.fault", "Try-fault statement", - BaseClass("TryInstruction"), CustomConstructor, CustomWriteTo, CustomComputeFlags), + BaseClass("TryInstruction"), CustomConstructor, CustomWriteTo, CustomComputeFlags, + MatchCondition("TryBlock.PerformMatch(o.TryBlock, ref match)"), + MatchCondition("faultBlock.PerformMatch(o.faultBlock, ref match)")), new OpCode("debug.break", "Breakpoint instruction", NoArguments, VoidResult, SideEffect), new OpCode("comp", "Comparison. The inputs must be both integers; or both floats; or both object references. " @@ -105,14 +114,15 @@ + "Floating-point comparisons evaluate to 0 (false) when an input is NaN, except for 'NaN != NaN' which " + "evaluates to 1 (true).", Binary, CustomConstructor, CustomWriteTo, ResultType("I4"), - MatchCondition("this.Kind == o.Kind")), + MatchCondition("this.Kind == o.Kind && this.Sign == o.Sign")), new OpCode("call", "Non-virtual method call.", Call), new OpCode("callvirt", "Virtual method call.", CustomClassName("CallVirt"), Call), new OpCode("ckfinite", "Checks that the input float is not NaN or infinite.", Unary, MayThrow, VoidResult), new OpCode("conv", "Numeric cast.", - Unary, CustomConstructor), + Unary, CustomConstructor, + MatchCondition("CheckForOverflow == o.CheckForOverflow && Kind == o.Kind && InputSign == o.InputSign && TargetType == o.TargetType")), new OpCode("ldloc", "Loads the value of a local variable. (ldarg/ldloc)", CustomClassName("LdLoc"), NoArguments, HasVariableOperand("Load"), ResultType("variable.StackType")), new OpCode("ldloca", "Loads the address of a local variable. (ldarga/ldloca)", @@ -146,7 +156,8 @@ new OpCode("localloc", "Allocates space in the stack frame", CustomClassName("LocAlloc"), Unary, ResultType("I"), MayThrow), new OpCode("ret", "Returns from the current method or lambda.", - CustomClassName("Return"), CustomConstructor, CustomComputeFlags, MayBranch, UnconditionalBranch), + CustomClassName("Return"), CustomConstructor, CustomComputeFlags, MayBranch, UnconditionalBranch, + MatchCondition("this.hasArgument == o.hasArgument && (!hasArgument || this.ReturnValue.PerformMatch(o.ReturnValue, ref match))")), new OpCode("ldflda", "Load address of instance field", CustomClassName("LdFlda"), CustomArguments("target"), MayThrowIfNotDelayed, HasFieldOperand, ResultType("Ref")),