From 8533eda92b9d4d0ab7986e78ed00de451491a917 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 3 Oct 2017 00:28:24 +0200 Subject: [PATCH] Use unary negation '-a' instead of '0 - a'. --- .../CSharp/ExpressionBuilder.cs | 16 ++++++++++++++++ .../IL/Instructions/PatternMatching.cs | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index d05684283..2ecd43d1a 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -655,6 +655,22 @@ namespace ICSharpCode.Decompiler.CSharp left = PrepareArithmeticArgument(left, inst.LeftInputType, inst.Sign, inst.IsLifted); right = PrepareArithmeticArgument(right, inst.RightInputType, inst.Sign, inst.IsLifted); + if (op == BinaryOperatorType.Subtract && inst.Left.MatchLdcI(0)) { + IType rightUType = NullableType.GetUnderlyingType(right.Type); + if (rightUType.IsKnownType(KnownTypeCode.Int32) || rightUType.IsKnownType(KnownTypeCode.Int64) || rightUType.IsCSharpSmallIntegerType()) { + // unary minus is supported on signed int and long, and on the small integer types (since they promote to int) + var uoe = new UnaryOperatorExpression(UnaryOperatorType.Minus, right.Expression); + uoe.AddAnnotation(inst.CheckForOverflow ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation); + var resultType = rightUType.IsKnownType(KnownTypeCode.Int64) ? rightUType : compilation.FindType(KnownTypeCode.Int32); + if (inst.IsLifted) + resultType = NullableType.Create(compilation, resultType); + return uoe.WithILInstruction(inst).WithRR(new OperatorResolveResult( + resultType, + inst.CheckForOverflow ? ExpressionType.NegateChecked : ExpressionType.Negate, + right.ResolveResult)); + } + } + var rr = resolverWithOverflowCheck.ResolveBinaryOperator(op, left.ResolveResult, right.ResolveResult); if (rr.IsError || NullableType.GetUnderlyingType(rr.Type).GetStackType() != inst.UnderlyingResultType || !IsCompatibleWithSign(left.Type, inst.Sign) || !IsCompatibleWithSign(right.Type, inst.Sign)) diff --git a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs index 0a92d33ea..26b33c0f6 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs @@ -41,6 +41,11 @@ namespace ICSharpCode.Decompiler.IL return false; } + public bool MatchLdcI(long val) + { + return MatchLdcI(out long v) && v == val; + } + public bool MatchLdLoc(ILVariable variable) { var inst = this as LdLoc;