Browse Source

Avoid using `>>>` operator when the context expects a cast to unsigned anyway.

pull/2994/head
Daniel Grunwald 2 years ago
parent
commit
a2019c5d78
  1. 30
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs
  2. 10
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

30
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs

@ -106,9 +106,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public uint RShiftByteWithZeroExtension(byte num)
{
// zero extend -> cast to unsigned -> unsigned shift
return (uint)num >> 8;
}
public int RShiftByteWithZeroExtensionReturnAsSigned(byte num)
{
#if CS110
// zero extend -> unsigned shift
return num >>> 8;
#else
// zero extend -> cast to unsigned -> unsigned shift -> cast to signed
return (int)((uint)num >> 8);
#endif
}
public int RShiftByteAsSByte(byte num)
{
return (sbyte)num >> 8;
@ -121,9 +133,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public uint RShiftSByteWithZeroExtension(sbyte num)
{
return (uint)num >> 8;
return (uint)((byte)num >> 4);
}
public uint RShiftSByteWithSignExtension(sbyte num)
{
// sign extend -> cast to unsigned -> unsigned shift
return (uint)num >> 4;
}
public int RShiftSByteWithSignExtensionReturnAsSigned(sbyte num)
{
#if CS110
// sign extend -> unsigned shift
return num >>> 4;
#else
// sign extend -> cast to unsigned -> unsigned shift -> cast to signed
return (int)((uint)num >> 4);
#endif
}
public int RShiftSByteAsByte(sbyte num)
{
return (byte)num >> 8;

10
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1208,9 +1208,9 @@ namespace ICSharpCode.Decompiler.CSharp
case BinaryNumericOperator.BitXor:
return HandleBinaryNumeric(inst, BinaryOperatorType.ExclusiveOr, context);
case BinaryNumericOperator.ShiftLeft:
return HandleShift(inst, BinaryOperatorType.ShiftLeft);
return HandleShift(inst, BinaryOperatorType.ShiftLeft, context);
case BinaryNumericOperator.ShiftRight:
return HandleShift(inst, BinaryOperatorType.ShiftRight);
return HandleShift(inst, BinaryOperatorType.ShiftRight, context);
default:
throw new ArgumentOutOfRangeException();
}
@ -1736,7 +1736,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
TranslatedExpression HandleShift(BinaryNumericInstruction inst, BinaryOperatorType op)
TranslatedExpression HandleShift(BinaryNumericInstruction inst, BinaryOperatorType op, TranslationContext context)
{
var left = Translate(inst.Left);
var right = Translate(inst.Right);
@ -1748,6 +1748,8 @@ namespace ICSharpCode.Decompiler.CSharp
bool couldUseUnsignedRightShift = (
sign == Sign.Unsigned && op == BinaryOperatorType.ShiftRight && settings.UnsignedRightShift
&& (leftUType.IsCSharpPrimitiveIntegerType() || leftUType.IsCSharpNativeIntegerType())
// If we need to cast to unsigned anyway, don't use >>> operator.
&& context.TypeHint.GetSign() != Sign.Unsigned
);
if (leftUType.IsCSharpSmallIntegerType() && inst.UnderlyingResultType == StackType.I4 &&
(sign != Sign.Unsigned || couldUseUnsignedRightShift))
@ -1760,7 +1762,7 @@ namespace ICSharpCode.Decompiler.CSharp
op = BinaryOperatorType.UnsignedShiftRight;
}
}
else if (couldUseUnsignedRightShift && leftUType.GetSize() == inst.UnderlyingResultType.GetSize())
else if (couldUseUnsignedRightShift && leftUType.GetSize() == inst.UnderlyingResultType.GetSize() && leftUType.GetSign() == Sign.Signed)
{
// Use C# 11 unsigned right shift operator. We don't need any casts in this case.
op = BinaryOperatorType.UnsignedShiftRight;

Loading…
Cancel
Save