Browse Source

Fix native integer shifts.

pull/2063/head
Daniel Grunwald 5 years ago
parent
commit
a7826e399e
  1. 19
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs
  2. 22
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

19
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs

@ -83,6 +83,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine((nuint)i + u); 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() public object[] Boxing()
{ {
return new object[10] { return new object[10] {

22
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -795,7 +795,7 @@ namespace ICSharpCode.Decompiler.CSharp
} else if (rightUType.GetStackType() == inst.InputType && !rightUType.IsSmallIntegerType()) { } else if (rightUType.GetStackType() == inst.InputType && !rightUType.IsSmallIntegerType()) {
targetType = rightUType; targetType = rightUType;
} else { } else {
targetType = compilation.FindType(inst.InputType.ToKnownTypeCode(leftUType.GetSign())); targetType = FindType(inst.InputType, leftUType.GetSign());
} }
} }
if (inst.IsLifted) { if (inst.IsLifted) {
@ -1316,6 +1316,9 @@ namespace ICSharpCode.Decompiler.CSharp
return resultExpr; return resultExpr;
} }
/// <summary>
/// Gets a type matching the stack type and sign.
/// </summary>
IType FindType(StackType stackType, Sign sign) IType FindType(StackType stackType, Sign sign)
{ {
if (stackType == StackType.I && settings.NativeIntegers) { if (stackType == StackType.I && settings.NativeIntegers) {
@ -1325,6 +1328,14 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
/// <summary>
/// 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.
/// </summary>
IType FindArithmeticType(StackType stackType, Sign sign) IType FindArithmeticType(StackType stackType, Sign sign)
{ {
if (stackType == StackType.I) { if (stackType == StackType.I) {
@ -1396,6 +1407,8 @@ namespace ICSharpCode.Decompiler.CSharp
var left = Translate(inst.Left); var left = Translate(inst.Left);
var right = Translate(inst.Right); var right = Translate(inst.Right);
left = PrepareArithmeticArgument(left, inst.LeftInputType, inst.Sign, inst.IsLifted);
Sign sign = inst.Sign; Sign sign = inst.Sign;
var leftUType = NullableType.GetUnderlyingType(left.Type); var leftUType = NullableType.GetUnderlyingType(left.Type);
if (leftUType.IsCSharpSmallIntegerType() && sign != Sign.Unsigned && inst.UnderlyingResultType == StackType.I4) { 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: // if we don't need a specific sign, prefer keeping that of the input:
sign = leftUType.GetSign(); sign = leftUType.GetSign();
} }
IType targetType; IType targetType = FindArithmeticType(inst.UnderlyingResultType, sign);
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);
}
if (NullableType.IsNullable(left.Type)) { if (NullableType.IsNullable(left.Type)) {
targetType = NullableType.Create(compilation, targetType); targetType = NullableType.Create(compilation, targetType);
} }

Loading…
Cancel
Save