Exemplo n.º 1
0
        private EXPR FoldConstI8Op(ExpressionKind kind, EXPR op1, EXPRCONSTANT opConst1, EXPR op2, EXPRCONSTANT opConst2, PredefinedType ptOp)
        {
            Debug.Assert(ptOp == PredefinedType.PT_LONG || ptOp == PredefinedType.PT_ULONG);
            Debug.Assert(opConst1.isCONSTANT_OK());
            Debug.Assert(op1.type.isPredefType(ptOp) && op1.type == opConst1.type);
            Debug.Assert(op2 == null && opConst2 == null ||
                   op2 != null && opConst2 != null && opConst2.isCONSTANT_OK() && op1.type == op2.type && op1.type == opConst2.type);

            bool fSigned = (ptOp == PredefinedType.PT_LONG);
            bool fRes = false;
            // Allocate the result node.
            CType typeDest;
            CONSTVAL cv = new CONSTVAL();


            if (fSigned)
            {
                // long.
                long u1 = opConst1.asCONSTANT().getVal().longVal;
                long u2 = opConst2 != null ? opConst2.asCONSTANT().getVal().longVal : 0;
                long uRes = 0;
                switch (kind)
                {
                    case ExpressionKind.EK_ADD:
                        uRes = u1 + u2;
                        break;

                    case ExpressionKind.EK_SUB:
                        uRes = u1 - u2;
                        break;

                    case ExpressionKind.EK_MUL:
                        uRes = u1 * u2;
                        break;

                    case ExpressionKind.EK_DIV:
                        Debug.Assert(u2 != 0); // Caller should have handled this.
                        uRes = u1 / u2;
                        break;

                    case ExpressionKind.EK_MOD:
                        Debug.Assert(u2 != 0); // Caller should have handled this.
                        uRes = u1 % u2;
                        break;

                    case ExpressionKind.EK_NEG:
                        uRes = -u1;
                        break;

                    case ExpressionKind.EK_UPLUS:
                        uRes = u1;
                        break;
                    case ExpressionKind.EK_BITAND:
                        uRes = u1 & u2;
                        break;
                    case ExpressionKind.EK_BITOR:
                        uRes = u1 | u2;
                        break;
                    case ExpressionKind.EK_BITXOR:
                        uRes = u1 ^ u2;
                        break;
                    case ExpressionKind.EK_BITNOT:
                        uRes = ~u1;
                        break;
                    case ExpressionKind.EK_EQ:
                        fRes = (u1 == u2);
                        break;
                    case ExpressionKind.EK_NE:
                        fRes = (u1 != u2);
                        break;
                    case ExpressionKind.EK_LE:
                        fRes = u1 <= u2;
                        break;
                    case ExpressionKind.EK_LT:
                        fRes = u1 < u2;
                        break;
                    case ExpressionKind.EK_GE:
                        fRes = u1 >= u2;
                        break;
                    case ExpressionKind.EK_GT:
                        fRes = u1 > u2;
                        break;
                    default:
                        VSFAIL("Unknown op");
                        uRes = 0;
                        break;
                }

                if (kind.isRelational())
                {
                    cv.iVal = fRes ? 1 : 0;
                    typeDest = GetReqPDT(PredefinedType.PT_BOOL);
                }
                else
                {
                    cv = GetExprConstants().Create(uRes);
                    typeDest = GetOptPDT(ptOp);
                    Debug.Assert(typeDest != null);
                }
            }
            else
            {
                // ulong.
                // Get the operands
                ulong u1 = opConst1.asCONSTANT().getVal().ulongVal;
                ulong u2 = opConst2 != null ? opConst2.asCONSTANT().getVal().ulongVal : 0;
                ulong uRes = 0;

                // Do the operation.
                switch (kind)
                {
                    case ExpressionKind.EK_ADD:
                        uRes = u1 + u2;
                        break;

                    case ExpressionKind.EK_SUB:
                        uRes = u1 - u2;
                        break;

                    case ExpressionKind.EK_MUL:
                        uRes = u1 * u2;
                        break;

                    case ExpressionKind.EK_DIV:
                        Debug.Assert(u2 != 0); // Caller should have handled this.
                        uRes = u1 / u2;
                        break;

                    case ExpressionKind.EK_MOD:
                        Debug.Assert(u2 != 0); // Caller should have handled this.
                        uRes = u1 % u2;
                        break;

                    case ExpressionKind.EK_NEG:
                        // You can't do this!
                        return BadOperatorTypesError(kind, op1, op2);

                    case ExpressionKind.EK_UPLUS:
                        uRes = u1;
                        break;
                    case ExpressionKind.EK_BITAND:
                        uRes = u1 & u2;
                        break;
                    case ExpressionKind.EK_BITOR:
                        uRes = u1 | u2;
                        break;
                    case ExpressionKind.EK_BITXOR:
                        uRes = u1 ^ u2;
                        break;
                    case ExpressionKind.EK_BITNOT:
                        uRes = ~u1;
                        break;
                    case ExpressionKind.EK_EQ:
                        fRes = (u1 == u2);
                        break;
                    case ExpressionKind.EK_NE:
                        fRes = (u1 != u2);
                        break;
                    case ExpressionKind.EK_LE:
                        fRes = u1 <= u2;
                        break;
                    case ExpressionKind.EK_LT:
                        fRes = u1 < u2;
                        break;
                    case ExpressionKind.EK_GE:
                        fRes = u1 >= u2;
                        break;
                    case ExpressionKind.EK_GT:
                        fRes = u1 > u2;
                        break;
                    default:
                        VSFAIL("Unknown op");
                        uRes = 0;
                        break;
                }

                if (kind.isRelational())
                {
                    cv.iVal = fRes ? 1 : 0;
                    typeDest = GetReqPDT(PredefinedType.PT_BOOL);
                }
                else
                {
                    cv = GetExprConstants().Create(uRes);
                    typeDest = GetOptPDT(ptOp);
                    Debug.Assert(typeDest != null);
                }
            }


            // Allocate the result node.
            EXPR exprRes = GetExprFactory().CreateConstant(typeDest, cv);

            return exprRes;
        }
Exemplo n.º 2
0
        private EXPR FoldConstI4Op(ExpressionKind kind, EXPR op1, EXPRCONSTANT opConst1, EXPR op2, EXPRCONSTANT opConst2, PredefinedType ptOp)
        {
            Debug.Assert(ptOp == PredefinedType.PT_INT || ptOp == PredefinedType.PT_UINT);
            Debug.Assert(opConst1.isCONSTANT_OK());
            Debug.Assert(op1.type.isPredefType(ptOp) && op1.type == opConst1.type);
            Debug.Assert(op2 == null && opConst2 == null ||
                   op2 != null && opConst2 != null && opConst2.isCONSTANT_OK() && op1.type == op2.type && op1.type == opConst2.type);

            bool fSigned = (ptOp == PredefinedType.PT_INT);

            // Get the operands
            uint u1 = opConst1.asCONSTANT().getVal().uiVal;
            uint u2 = opConst2 != null ? opConst2.asCONSTANT().getVal().uiVal : 0;
            uint uRes;

            // The code below doesn't work if uint isn't 4 bytes!
            Debug.Assert(sizeof(uint) == 4);

            // The sign bit.
            uint uSign = 0x80000000;

            // Do the operation.
            switch (kind)
            {
                case ExpressionKind.EK_ADD:
                    uRes = u1 + u2;
                    // For signed, we want either sign(u1) != sign(u2) or sign(u1) == sign(uRes).
                    // For unsigned, the result should be at least as big as either operand (if it's bigger than
                    // one, it will be bigger than the other as well).
                    if (fSigned)
                    {
                        EnsureChecked(0 != (((u1 ^ u2) | (u1 ^ uRes ^ uSign)) & uSign));
                    }
                    else
                    {
                        EnsureChecked(uRes >= u1);
                    }
                    break;

                case ExpressionKind.EK_SUB:
                    uRes = u1 - u2;
                    // For signed, we want either sign(u1) == sign(u2) or sign(u1) == sign(uRes).
                    // For unsigned, the result should be no bigger than the first operand.
                    if (fSigned)
                    {
                        EnsureChecked(0 != (((u1 ^ u2 ^ uSign) | (u1 ^ uRes ^ uSign)) & uSign));
                    }
                    else
                    {
                        EnsureChecked(uRes <= u1);
                    }
                    break;

                case ExpressionKind.EK_MUL:
                    // Multiply mod 2^32 doesn't depend on signed vs unsigned.
                    uRes = u1 * u2;
                    // Note that divide depends on signed-ness.
                    // For signed, the first check detects 0x80000000 / 0xFFFFFFFF == 0x80000000.
                    // This test needs to come first to avoid an integer overflow exception - yes we get this
                    // in native code.
                    if (u1 == 0 || u2 == 0)
                    {
                        break;
                    }

                    if (fSigned)
                    {
                        EnsureChecked((u2 != uRes || u1 == 1) && (int)uRes / (int)u1 == (int)u2);
                    }
                    else
                    {
                        EnsureChecked(uRes / u1 == u2);
                    }
                    break;

                case ExpressionKind.EK_DIV:
                    Debug.Assert(u2 != 0); // Caller should have handled this.
                    if (!fSigned)
                    {
                        uRes = u1 / u2;
                    }
                    else if (u2 != 0)
                    {
                        uRes = (uint)((int)u1 / (int)u2);
                    }
                    else
                    {
                        uRes = (uint)-(int)u1;
                        EnsureChecked(u1 != uSign);
                    }
                    break;

                case ExpressionKind.EK_MOD:
                    Debug.Assert(u2 != 0); // Caller should have handled this.
                    if (!fSigned)
                    {
                        uRes = u1 % u2;
                    }
                    else if (u2 != 0)
                    {
                        uRes = (uint)((int)u1 % (int)u2);
                    }
                    else
                    {
                        uRes = 0;
                    }
                    break;

                case ExpressionKind.EK_NEG:
                    if (!fSigned)
                    {
                        // Special case: a unary minus promotes a uint to a long
                        CONSTVAL cv = GetExprConstants().Create(-(long)u1);
                        EXPRCONSTANT foldedConst = GetExprFactory().CreateConstant(GetReqPDT(PredefinedType.PT_LONG), cv);

                        return foldedConst;
                    }

                    uRes = (uint)-(int)u1;
                    EnsureChecked(u1 != uSign);
                    break;

                case ExpressionKind.EK_UPLUS:
                    uRes = u1;
                    break;
                case ExpressionKind.EK_BITAND:
                    uRes = u1 & u2;
                    break;
                case ExpressionKind.EK_BITOR:
                    uRes = u1 | u2;
                    break;
                case ExpressionKind.EK_BITXOR:
                    uRes = u1 ^ u2;
                    break;
                case ExpressionKind.EK_BITNOT:
                    uRes = ~u1;
                    break;
                case ExpressionKind.EK_EQ:
                    uRes = (uint)((u1 == u2) ? 1 : 0);
                    break;
                case ExpressionKind.EK_NE:
                    uRes = (uint)((u1 != u2) ? 1 : 0);
                    break;
                case ExpressionKind.EK_LE:
                    uRes = (uint)((fSigned ? (int)u1 <= (int)u2 : u1 <= u2) ? 1 : 0);
                    break;
                case ExpressionKind.EK_LT:
                    uRes = (uint)((fSigned ? (int)u1 < (int)u2 : u1 < u2) ? 1 : 0);
                    break;
                case ExpressionKind.EK_GE:
                    uRes = (uint)((fSigned ? (int)u1 >= (int)u2 : u1 >= u2) ? 1 : 0);
                    break;
                case ExpressionKind.EK_GT:
                    uRes = (uint)((fSigned ? (int)u1 > (int)u2 : u1 > u2) ? 1 : 0);
                    break;
                default:
                    VSFAIL("Unknown op");
                    uRes = 0;
                    break;
            }

            CType typeDest = GetOptPDT(kind.isRelational() ? PredefinedType.PT_BOOL : ptOp);
            Debug.Assert(typeDest != null);

            // Allocate the result node.
            EXPR exprRes = GetExprFactory().CreateConstant(typeDest, ConstValFactory.GetUInt(uRes));

            return exprRes;
        }