Beispiel #1
0
        private AggregateType GetEnumBinOpType(ExpressionKind ek, CType argType1, CType argType2, out AggregateType ppEnumType)
        {
            Debug.Assert(argType1.isEnumType() || argType2.isEnumType());

            AggregateType type1 = argType1.AsAggregateType();
            AggregateType type2 = argType2.AsAggregateType();

            AggregateType typeEnum = type1.isEnumType() ? type1 : type2;

            Debug.Assert(type1 == typeEnum || type1 == typeEnum.underlyingEnumType());
            Debug.Assert(type2 == typeEnum || type2 == typeEnum.underlyingEnumType());

            AggregateType typeDst = typeEnum;

            switch (ek)
            {
                case ExpressionKind.EK_BITAND:
                case ExpressionKind.EK_BITOR:
                case ExpressionKind.EK_BITXOR:
                    Debug.Assert(type1 == type2);
                    break;

                case ExpressionKind.EK_ADD:
                    Debug.Assert(type1 != type2);
                    break;

                case ExpressionKind.EK_SUB:
                    if (type1 == type2)
                        typeDst = typeEnum.underlyingEnumType();
                    break;

                default:
                    Debug.Assert(ek.isRelational());
                    typeDst = GetReqPDT(PredefinedType.PT_BOOL);
                    break;
            }

            ppEnumType = typeEnum;
            return typeDst;
        }
Beispiel #2
0
        /*
          Bind an float/double operator: +, -, , /, %, <, >, <=, >=, ==, !=. If both operations are constants, the result
          will be a constant also. op2 can be null for a unary operator. The operands are assumed
          to be already converted to the correct type.
         */
        // We have an intentional divide by 0 there, so disable the warning...
#if _MSC_VER
#pragma warning( disable : 4723 )
#endif
        private EXPR bindFloatOp(ExpressionKind kind, EXPRFLAG flags, EXPR op1, EXPR op2)
        {
            //Debug.Assert(kind.isRelational() || kind.isArithmetic());
            Debug.Assert(op2 == null || op1.type == op2.type);
            Debug.Assert(op1.type.isPredefType(PredefinedType.PT_FLOAT) || op1.type.isPredefType(PredefinedType.PT_DOUBLE));

            EXPR exprRes;
            EXPR opConst1 = op1.GetConst();
            EXPR opConst2 = op2 != null ? op2.GetConst() : null;

            // Check for constants and fold them.
            if (opConst1 != null && (op2 == null || opConst2 != null))
            {
                // Get the operands
                double d1 = opConst1.asCONSTANT().getVal().doubleVal;
                double d2 = opConst2 != null ? opConst2.asCONSTANT().getVal().doubleVal : 0.0;
                double result = 0;      // if isBoolResult is false
                bool result_b = false;  // if isBoolResult is true

                // Do the operation.
                switch (kind)
                {
                    case ExpressionKind.EK_ADD:
                        result = d1 + d2;
                        break;
                    case ExpressionKind.EK_SUB:
                        result = d1 - d2;
                        break;
                    case ExpressionKind.EK_MUL:
                        result = d1 * d2;
                        break;
                    case ExpressionKind.EK_DIV:
                        result = d1 / d2;
                        break;
                    case ExpressionKind.EK_NEG:
                        result = -d1;
                        break;
                    case ExpressionKind.EK_UPLUS:
                        result = d1;
                        break;
                    case ExpressionKind.EK_MOD:
                        result = d1 % d2;
                        break;
                    case ExpressionKind.EK_EQ:
                        result_b = (d1 == d2);
                        break;
                    case ExpressionKind.EK_NE:
                        result_b = (d1 != d2);
                        break;
                    case ExpressionKind.EK_LE:
                        result_b = (d1 <= d2);
                        break;
                    case ExpressionKind.EK_LT:
                        result_b = (d1 < d2);
                        break;
                    case ExpressionKind.EK_GE:
                        result_b = (d1 >= d2);
                        break;
                    case ExpressionKind.EK_GT:
                        result_b = (d1 > d2);
                        break;
                    default:
                        Debug.Assert(false);
                        result = 0.0;  // unexpected operation.
                        break;
                }

                CType typeDest;
                CONSTVAL cv = new CONSTVAL();

                // Allocate the result node.
                if (kind.isRelational())
                {
                    cv.iVal = result_b ? 1 : 0;
                    typeDest = GetReqPDT(PredefinedType.PT_BOOL);
                }
                else
                {
                    // NaN has some implementation defined bits that differ between platforms.
                    // Normalize it to produce identical images across all platforms
                    /*
                     * How do we get here?
                    if (_isnan(result))
                    {
                        cv = ConstValFactory.GetNan();
                    }
                    else
                    {
                     * */
                    cv = GetExprConstants().Create(result);

                    typeDest = op1.type;
                }
                exprRes = GetExprFactory().CreateConstant(typeDest, cv);
            }
            else
            {
                // Allocate the result expression.
                CType typeDest = kind.isRelational() ? GetReqPDT(PredefinedType.PT_BOOL) : op1.type;

                exprRes = GetExprFactory().CreateOperator(kind, typeDest, op1, op2);
                flags = ~EXPRFLAG.EXF_CHECKOVERFLOW;
                exprRes.flags |= flags;
            }

            return exprRes;
        }
Beispiel #3
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;
        }
Beispiel #4
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;
        }
Beispiel #5
0
        /*
            Convert and constant fold an expression involving I4, U4, I8 or U8 operands. The operands are
            assumed to be already converted to the correct types.
        */
        private EXPR BindIntOp(ExpressionKind kind, EXPRFLAG flags, EXPR op1, EXPR op2, PredefinedType ptOp)
        {
            //Debug.Assert(kind.isRelational() || kind.isArithmetic() || kind.isBitwise());
            Debug.Assert(ptOp == PredefinedType.PT_INT || ptOp == PredefinedType.PT_UINT || ptOp == PredefinedType.PT_LONG || ptOp == PredefinedType.PT_ULONG);
            CType typeOp = GetReqPDT(ptOp);
            Debug.Assert(typeOp != null);
            Debug.Assert(op1 != null && op1.type == typeOp);
            Debug.Assert(op2 == null || op2.type == typeOp);
            Debug.Assert((op2 == null) == (kind == ExpressionKind.EK_NEG || kind == ExpressionKind.EK_UPLUS || kind == ExpressionKind.EK_BITNOT));

            if (isDivByZero(kind, op2))
            {
                GetErrorContext().Error(ErrorCode.ERR_IntDivByZero);
                EXPR rval = GetExprFactory().CreateBinop(kind, typeOp, op1, op2);
                rval.SetError();
                return rval;
            }

            // This optimization CANNOT be moved to a later pass.  See comments in
            // FoldIntegerConstants.
            EXPR exprFolded = FoldIntegerConstants(kind, flags, op1, op2, ptOp);
            if (exprFolded != null)
            {
                return exprFolded;
            }

            if (kind == ExpressionKind.EK_NEG)
            {
                return BindIntegerNeg(flags, op1, ptOp);
            }

            CType typeDest = kind.isRelational() ? GetReqPDT(PredefinedType.PT_BOOL) : typeOp;

            EXPR exprRes = GetExprFactory().CreateOperator(kind, typeDest, op1, op2);
            exprRes.flags |= flags;
            Debug.Assert((exprRes.flags & EXPRFLAG.EXF_LVALUE) == 0);
            return exprRes;
        }