示例#1
0
        /// <summary>
        /// Gets whether the specific binary instruction is compatible with a compound operation on the specified type.
        /// </summary>
        internal static bool IsBinaryCompatibleWithType(BinaryNumericInstruction binary, IType type)
        {
            if (binary.IsLifted)
            {
                if (!NullableType.IsNullable(type))
                {
                    return(false);
                }
                type = NullableType.GetUnderlyingType(type);
            }
            if (type.Kind == TypeKind.Enum)
            {
                switch (binary.Operator)
                {
                case BinaryNumericOperator.Add:
                case BinaryNumericOperator.Sub:
                case BinaryNumericOperator.BitAnd:
                case BinaryNumericOperator.BitOr:
                case BinaryNumericOperator.BitXor:
                    break;                             // OK

                default:
                    return(false);                            // operator not supported on enum types
                }
            }
            else if (type.Kind == TypeKind.Pointer)
            {
                switch (binary.Operator)
                {
                case BinaryNumericOperator.Add:
                case BinaryNumericOperator.Sub:
                    // ensure that the byte offset is a multiple of the pointer size
                    return(PointerArithmeticOffset.Detect(
                               binary.Right,
                               (PointerType)type,
                               checkForOverflow: binary.CheckForOverflow
                               ) != null);

                default:
                    return(false);                            // operator not supported on pointer types
                }
            }
            if (binary.Sign != Sign.None)
            {
                if (type.GetSign() != binary.Sign)
                {
                    return(false);
                }
            }
            return(true);
        }
示例#2
0
        /// <summary>
        /// Gets whether the specific binary instruction is compatible with a compound operation on the specified type.
        /// </summary>
        internal static bool IsBinaryCompatibleWithType(BinaryNumericInstruction binary, IType type)
        {
            if (binary.IsLifted)
            {
                if (!NullableType.IsNullable(type))
                {
                    return(false);
                }
                type = NullableType.GetUnderlyingType(type);
            }
            if (type.Kind == TypeKind.Unknown)
            {
                return(false);                // avoid introducing a potentially-incorrect compound assignment
            }
            else if (type.Kind == TypeKind.Enum)
            {
                switch (binary.Operator)
                {
                case BinaryNumericOperator.Add:
                case BinaryNumericOperator.Sub:
                case BinaryNumericOperator.BitAnd:
                case BinaryNumericOperator.BitOr:
                case BinaryNumericOperator.BitXor:
                    break;                             // OK

                default:
                    return(false);                            // operator not supported on enum types
                }
            }
            else if (type.Kind == TypeKind.Pointer)
            {
                switch (binary.Operator)
                {
                case BinaryNumericOperator.Add:
                case BinaryNumericOperator.Sub:
                    // ensure that the byte offset is a multiple of the pointer size
                    return(PointerArithmeticOffset.Detect(
                               binary.Right,
                               (PointerType)type,
                               checkForOverflow: binary.CheckForOverflow
                               ) != null);

                default:
                    return(false);                            // operator not supported on pointer types
                }
            }
            if (binary.Sign != Sign.None)
            {
                if (type.IsCSharpSmallIntegerType())
                {
                    // C# will use numeric promotion to int, binary op must be signed
                    if (binary.Sign != Sign.Signed)
                    {
                        return(false);
                    }
                }
                else
                {
                    // C# will use sign from type
                    if (type.GetSign() != binary.Sign)
                    {
                        return(false);
                    }
                }
            }
            // Can't transform if the RHS value would be need to be truncated for the LHS type.
            if (Transforms.TransformAssignment.IsImplicitTruncation(binary.Right, type, binary.IsLifted))
            {
                return(false);
            }
            return(true);
        }
示例#3
0
        /// <summary>
        /// Gets whether the specific binary instruction is compatible with a compound operation on the specified type.
        /// </summary>
        internal static bool IsBinaryCompatibleWithType(BinaryNumericInstruction binary, IType type, DecompilerSettings settings)
        {
            if (binary.IsLifted)
            {
                if (!NullableType.IsNullable(type))
                {
                    return(false);
                }
                type = NullableType.GetUnderlyingType(type);
            }
            if (type.Kind == TypeKind.Unknown)
            {
                return(false);                // avoid introducing a potentially-incorrect compound assignment
            }
            else if (type.Kind == TypeKind.Enum)
            {
                switch (binary.Operator)
                {
                case BinaryNumericOperator.Add:
                case BinaryNumericOperator.Sub:
                case BinaryNumericOperator.BitAnd:
                case BinaryNumericOperator.BitOr:
                case BinaryNumericOperator.BitXor:
                    break;                             // OK

                default:
                    return(false);                            // operator not supported on enum types
                }
            }
            else if (type.Kind == TypeKind.Pointer)
            {
                switch (binary.Operator)
                {
                case BinaryNumericOperator.Add:
                case BinaryNumericOperator.Sub:
                    // ensure that the byte offset is a multiple of the pointer size
                    return(PointerArithmeticOffset.Detect(
                               binary.Right,
                               ((PointerType)type).ElementType,
                               checkForOverflow: binary.CheckForOverflow
                               ) != null);

                default:
                    return(false);                            // operator not supported on pointer types
                }
            }
            else if (type.IsKnownType(KnownTypeCode.IntPtr) || type.IsKnownType(KnownTypeCode.UIntPtr))
            {
                // "target.intptr *= 2;" is compiler error, but
                // "target.intptr *= (nint)2;" works
                if (settings != null && !settings.NativeIntegers)
                {
                    // But if native integers are not available, we cannot use compound assignment.
                    return(false);
                }
                // The trick with casting the RHS to n(u)int doesn't work for shifts:
                switch (binary.Operator)
                {
                case BinaryNumericOperator.ShiftLeft:
                case BinaryNumericOperator.ShiftRight:
                    return(false);
                }
            }
            if (binary.Sign != Sign.None)
            {
                if (type.IsCSharpSmallIntegerType())
                {
                    // C# will use numeric promotion to int, binary op must be signed
                    if (binary.Sign != Sign.Signed)
                    {
                        return(false);
                    }
                }
                else
                {
                    // C# will use sign from type
                    if (type.GetSign() != binary.Sign)
                    {
                        return(false);
                    }
                }
            }
            // Can't transform if the RHS value would be need to be truncated for the LHS type.
            if (Transforms.TransformAssignment.IsImplicitTruncation(binary.Right, type, null, binary.IsLifted))
            {
                return(false);
            }
            return(true);
        }