diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs index 331cb7b4a..6b2b83a2f 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs @@ -83,6 +83,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine((nuint)i + u); } + public void Shifts() + { + Console.WriteLine(i << i32); + Console.WriteLine(i >> i32); + Console.WriteLine(u >> i32); + Console.WriteLine(u << i32); + } + + public void Comparisons() + { + Console.WriteLine(i < i32); + Console.WriteLine(i <= i32); + Console.WriteLine(i > i32); + Console.WriteLine(i >= i32); + Console.WriteLine(i == (nint)u); + Console.WriteLine(i < (nint)u); + Console.WriteLine((nuint)i < u); + } + public object[] Boxing() { return new object[10] { diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 658320030..b98ab1317 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -795,7 +795,7 @@ namespace ICSharpCode.Decompiler.CSharp } else if (rightUType.GetStackType() == inst.InputType && !rightUType.IsSmallIntegerType()) { targetType = rightUType; } else { - targetType = compilation.FindType(inst.InputType.ToKnownTypeCode(leftUType.GetSign())); + targetType = FindType(inst.InputType, leftUType.GetSign()); } } if (inst.IsLifted) { @@ -1316,6 +1316,9 @@ namespace ICSharpCode.Decompiler.CSharp return resultExpr; } + /// + /// Gets a type matching the stack type and sign. + /// IType FindType(StackType stackType, Sign sign) { if (stackType == StackType.I && settings.NativeIntegers) { @@ -1325,6 +1328,14 @@ namespace ICSharpCode.Decompiler.CSharp } } + /// + /// Gets a type used for performing arithmetic with the stack type and sign. + /// + /// This may result in a larger type than requested when the selected C# version + /// doesn't support native integers. + /// Should only be used after a call to PrepareArithmeticArgument() + /// to ensure that we're not preserving extra bits from an oversized TranslatedExpression. + /// IType FindArithmeticType(StackType stackType, Sign sign) { if (stackType == StackType.I) { @@ -1396,6 +1407,8 @@ namespace ICSharpCode.Decompiler.CSharp var left = Translate(inst.Left); var right = Translate(inst.Right); + left = PrepareArithmeticArgument(left, inst.LeftInputType, inst.Sign, inst.IsLifted); + Sign sign = inst.Sign; var leftUType = NullableType.GetUnderlyingType(left.Type); if (leftUType.IsCSharpSmallIntegerType() && sign != Sign.Unsigned && inst.UnderlyingResultType == StackType.I4) { @@ -1407,12 +1420,7 @@ namespace ICSharpCode.Decompiler.CSharp // if we don't need a specific sign, prefer keeping that of the input: sign = leftUType.GetSign(); } - IType targetType; - if (inst.UnderlyingResultType == StackType.I4) { - targetType = compilation.FindType(sign == Sign.Unsigned ? KnownTypeCode.UInt32 : KnownTypeCode.Int32); - } else { - targetType = compilation.FindType(sign == Sign.Unsigned ? KnownTypeCode.UInt64 : KnownTypeCode.Int64); - } + IType targetType = FindArithmeticType(inst.UnderlyingResultType, sign); if (NullableType.IsNullable(left.Type)) { targetType = NullableType.Create(compilation, targetType); }