Browse Source

Support unary operators on native integers.

pull/2063/head
Daniel Grunwald 5 years ago
parent
commit
dc3dd193c8
  1. 7
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs
  2. 17
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 10
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs

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

@ -102,6 +102,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine((nuint)i < u); Console.WriteLine((nuint)i < u);
} }
public void Unary()
{
Console.WriteLine(~i);
Console.WriteLine(~u);
Console.WriteLine(-i);
}
public object[] Boxing() public object[] Boxing()
{ {
return new object[10] { return new object[10] {

17
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -567,7 +567,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (argUType.GetStackType().GetSize() < inst.UnderlyingResultType.GetSize() if (argUType.GetStackType().GetSize() < inst.UnderlyingResultType.GetSize()
|| argUType.Kind == TypeKind.Enum && argUType.IsSmallIntegerType() || argUType.Kind == TypeKind.Enum && argUType.IsSmallIntegerType()
|| argUType.GetStackType() == StackType.I || (argUType.GetStackType() == StackType.I && !argUType.IsCSharpNativeIntegerType())
|| argUType.IsKnownType(KnownTypeCode.Boolean) || argUType.IsKnownType(KnownTypeCode.Boolean)
|| argUType.IsKnownType(KnownTypeCode.Char)) || argUType.IsKnownType(KnownTypeCode.Char))
{ {
@ -576,13 +576,11 @@ namespace ICSharpCode.Decompiler.CSharp
// Same if the argument is an enum based on a small integer type // Same if the argument is an enum based on a small integer type
// (those don't undergo numeric promotion in C# the way non-enum small integer types do). // (those don't undergo numeric promotion in C# the way non-enum small integer types do).
// Same if the type is one that does not support ~ (IntPtr, bool and char). // Same if the type is one that does not support ~ (IntPtr, bool and char).
StackType targetStackType = inst.UnderlyingResultType; Sign sign = context.TypeHint.GetSign();
if (targetStackType == StackType.I) { if (sign == Sign.None) {
// IntPtr doesn't support operator ~. sign = argUType.GetSign();
// Note that it's OK to use a type that's larger than necessary.
targetStackType = StackType.I8;
} }
IType targetType = compilation.FindType(targetStackType.ToKnownTypeCode(argUType.GetSign())); IType targetType = FindArithmeticType(inst.UnderlyingResultType, sign);
if (inst.IsLifted) { if (inst.IsLifted) {
targetType = NullableType.Create(compilation, targetType); targetType = NullableType.Create(compilation, targetType);
} }
@ -1261,11 +1259,12 @@ namespace ICSharpCode.Decompiler.CSharp
if (op == BinaryOperatorType.Subtract && inst.Left.MatchLdcI(0)) { if (op == BinaryOperatorType.Subtract && inst.Left.MatchLdcI(0)) {
IType rightUType = NullableType.GetUnderlyingType(right.Type); IType rightUType = NullableType.GetUnderlyingType(right.Type);
if (rightUType.IsKnownType(KnownTypeCode.Int32) || rightUType.IsKnownType(KnownTypeCode.Int64) || rightUType.IsCSharpSmallIntegerType()) { if (rightUType.IsKnownType(KnownTypeCode.Int32) || rightUType.IsKnownType(KnownTypeCode.Int64)
|| rightUType.IsCSharpSmallIntegerType() || rightUType.IsCSharpNativeIntegerType()) {
// unary minus is supported on signed int and long, and on the small integer types (since they promote to int) // 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); var uoe = new UnaryOperatorExpression(UnaryOperatorType.Minus, right.Expression);
uoe.AddAnnotation(inst.CheckForOverflow ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation); uoe.AddAnnotation(inst.CheckForOverflow ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation);
var resultType = rightUType.IsKnownType(KnownTypeCode.Int64) ? rightUType : compilation.FindType(KnownTypeCode.Int32); var resultType = FindArithmeticType(inst.RightInputType, Sign.Signed);
if (inst.IsLifted) if (inst.IsLifted)
resultType = NullableType.Create(compilation, resultType); resultType = NullableType.Create(compilation, resultType);
return uoe.WithILInstruction(inst).WithRR(new OperatorResolveResult( return uoe.WithILInstruction(inst).WithRR(new OperatorResolveResult(

10
ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs

@ -449,14 +449,20 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
// C# 4.0 spec: §7.6.9 Postfix increment and decrement operators // C# 4.0 spec: §7.6.9 Postfix increment and decrement operators
// C# 4.0 spec: §7.7.5 Prefix increment and decrement operators // C# 4.0 spec: §7.7.5 Prefix increment and decrement operators
TypeCode code = ReflectionHelper.GetTypeCode(type); TypeCode code = ReflectionHelper.GetTypeCode(type);
if ((code >= TypeCode.Char && code <= TypeCode.Decimal) || type.Kind == TypeKind.Enum || type.Kind == TypeKind.Pointer) if ((code >= TypeCode.Char && code <= TypeCode.Decimal) || type.Kind == TypeKind.Enum || type.Kind == TypeKind.Pointer || type.IsCSharpNativeIntegerType())
return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable); return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable);
else else
return new ErrorResolveResult(expression.Type); return new ErrorResolveResult(expression.Type);
case UnaryOperatorType.Plus: case UnaryOperatorType.Plus:
if (type.IsCSharpNativeIntegerType()) {
return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable);
}
methodGroup = operators.UnaryPlusOperators; methodGroup = operators.UnaryPlusOperators;
break; break;
case UnaryOperatorType.Minus: case UnaryOperatorType.Minus:
if (type.IsCSharpNativeIntegerType()) {
return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable);
}
methodGroup = CheckForOverflow ? operators.CheckedUnaryMinusOperators : operators.UncheckedUnaryMinusOperators; methodGroup = CheckForOverflow ? operators.CheckedUnaryMinusOperators : operators.UncheckedUnaryMinusOperators;
break; break;
case UnaryOperatorType.Not: case UnaryOperatorType.Not:
@ -474,6 +480,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
return rr; return rr;
} }
return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable); return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable);
} else if (type.IsCSharpNativeIntegerType()) {
return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable);
} else { } else {
methodGroup = operators.BitwiseComplementOperators; methodGroup = operators.BitwiseComplementOperators;
break; break;

Loading…
Cancel
Save