Esempio n. 1
0
        public static DataType?GetResult(this ArithmeticOperation operation, DataType lhs, DataType rhs, out bool verifiable)
        {
            Contract.Requires(operation.IsBinary());
            Contract.Requires(lhs.IsStackType());
            Contract.Requires(rhs.IsStackType());

            verifiable = true;

            switch (operation)
            {
            // ECMA 335 III.1.5 Table 2: Binary Numeric Operations (add, div, mul, rem, sub)
            case ArithmeticOperation.Addition:
            case ArithmeticOperation.Division:
            case ArithmeticOperation.Multiplication:
            case ArithmeticOperation.Remainder:
            case ArithmeticOperation.Subtraction:

            // ECMA 335 III.1.5 Table 7: Overflow Arithmetic Operations (add.ovf, add.ovf.un, mul.ovf, mul.ovf.un, sub.ovf, sub.ovf.un)
            case ArithmeticOperation.Addition_OverflowCheck:
            case ArithmeticOperation.Addition_UnsignedWithOverflowCheck:
            case ArithmeticOperation.Multiplication_OverflowCheck:
            case ArithmeticOperation.Multiplication_UnsignedWithOverflowCheck:
            case ArithmeticOperation.Subtraction_OverflowCheck:
            case ArithmeticOperation.Subtraction_UnsignedWithOverflowCheck:

                if (lhs == rhs)
                {
                    if (lhs.IsIntegerStackType())
                    {
                        return(lhs);
                    }
                    if (lhs.IsFloat() && !operation.IsOverflowChecked())
                    {
                        return(lhs);
                    }
                    if (lhs.IsManagedPointer() && (operation == ArithmeticOperation.Subtraction ||
                                                   operation == ArithmeticOperation.Subtraction_UnsignedWithOverflowCheck))
                    {
                        verifiable = false;
                        return(DataType.NativeInt);
                    }
                }
                else
                {
                    if ((lhs == DataType.Int32 && rhs == DataType.NativeInt) ||
                        (lhs == DataType.NativeInt && rhs == DataType.Int32))
                    {
                        return(DataType.NativeInt);
                    }

                    if (lhs.IsManagedPointer() && (rhs == DataType.Int32 || rhs == DataType.NativeInt) &&
                        (operation == ArithmeticOperation.Addition || operation == ArithmeticOperation.Subtraction ||
                         operation == ArithmeticOperation.Addition_UnsignedWithOverflowCheck ||
                         operation == ArithmeticOperation.Subtraction_UnsignedWithOverflowCheck))
                    {
                        verifiable = false;
                        return(lhs);
                    }

                    if ((lhs == DataType.Int32 || lhs == DataType.NativeInt) && rhs.IsManagedPointer() &&
                        (operation == ArithmeticOperation.Addition || operation == ArithmeticOperation.Addition_UnsignedWithOverflowCheck))
                    {
                        verifiable = false;
                        return(rhs);
                    }
                }
                break;

            // ECMA 335 III.1.5 Table 5: Integer Operations (and, div.un, or, rem.un, xor - 'not' excluded)
            case ArithmeticOperation.BitwiseAnd:
            case ArithmeticOperation.Division_Unsigned:
            case ArithmeticOperation.BitwiseOr:
            case ArithmeticOperation.Remainder_Unsigned:
            case ArithmeticOperation.BitwiseXor:

                if (lhs == rhs)
                {
                    if (lhs.IsIntegerStackType())
                    {
                        return(lhs);
                    }
                }
                else
                {
                    if ((lhs == DataType.Int32 && rhs == DataType.NativeInt) ||
                        (lhs == DataType.NativeInt && rhs == DataType.Int32))
                    {
                        return(DataType.NativeInt);
                    }
                }
                break;

            // ECMA 335 III.1.5 Table 6: Shift Operations (shl, shr, shr.un)
            case ArithmeticOperation.BitShiftLeft:
            case ArithmeticOperation.BitShiftRight:
            case ArithmeticOperation.BitShiftRight_Unsigned:

                if (lhs.IsIntegerStackType() && (rhs == DataType.Int32 || rhs == DataType.NativeInt))
                {
                    return(lhs);
                }
                break;

            default:
                throw new ArgumentException("Invalid arithmetic operation enumerant.", "operation");
            }

            verifiable = false;
            return(null);
        }