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) public uint RShiftByteWithZeroExtension(byte num)
{ {
// zero extend -> cast to unsigned -> unsigned shift
return (uint)num >> 8; 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) public int RShiftByteAsSByte(byte num)
{ {
return (sbyte)num >> 8; return (sbyte)num >> 8;
@ -121,9 +133,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public uint RShiftSByteWithZeroExtension(sbyte num) 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) public int RShiftSByteAsByte(sbyte num)
{ {
return (byte)num >> 8; return (byte)num >> 8;

10
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1208,9 +1208,9 @@ namespace ICSharpCode.Decompiler.CSharp
case BinaryNumericOperator.BitXor: case BinaryNumericOperator.BitXor:
return HandleBinaryNumeric(inst, BinaryOperatorType.ExclusiveOr, context); return HandleBinaryNumeric(inst, BinaryOperatorType.ExclusiveOr, context);
case BinaryNumericOperator.ShiftLeft: case BinaryNumericOperator.ShiftLeft:
return HandleShift(inst, BinaryOperatorType.ShiftLeft); return HandleShift(inst, BinaryOperatorType.ShiftLeft, context);
case BinaryNumericOperator.ShiftRight: case BinaryNumericOperator.ShiftRight:
return HandleShift(inst, BinaryOperatorType.ShiftRight); return HandleShift(inst, BinaryOperatorType.ShiftRight, context);
default: default:
throw new ArgumentOutOfRangeException(); 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 left = Translate(inst.Left);
var right = Translate(inst.Right); var right = Translate(inst.Right);
@ -1748,6 +1748,8 @@ namespace ICSharpCode.Decompiler.CSharp
bool couldUseUnsignedRightShift = ( bool couldUseUnsignedRightShift = (
sign == Sign.Unsigned && op == BinaryOperatorType.ShiftRight && settings.UnsignedRightShift sign == Sign.Unsigned && op == BinaryOperatorType.ShiftRight && settings.UnsignedRightShift
&& (leftUType.IsCSharpPrimitiveIntegerType() || leftUType.IsCSharpNativeIntegerType()) && (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 && if (leftUType.IsCSharpSmallIntegerType() && inst.UnderlyingResultType == StackType.I4 &&
(sign != Sign.Unsigned || couldUseUnsignedRightShift)) (sign != Sign.Unsigned || couldUseUnsignedRightShift))
@ -1760,7 +1762,7 @@ namespace ICSharpCode.Decompiler.CSharp
op = BinaryOperatorType.UnsignedShiftRight; 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. // Use C# 11 unsigned right shift operator. We don't need any casts in this case.
op = BinaryOperatorType.UnsignedShiftRight; op = BinaryOperatorType.UnsignedShiftRight;

Loading…
Cancel
Save