コード例 #1
0
        private static ConstantValue GetConstantOneForBinOp(
            BinaryOperatorKind binaryOperatorKind)
        {
            switch (binaryOperatorKind.OperandTypes())
            {
            case BinaryOperatorKind.PointerAndInt:
            case BinaryOperatorKind.Int:
                return(ConstantValue.Create(1));

            case BinaryOperatorKind.UInt:
                return(ConstantValue.Create(1U));

            case BinaryOperatorKind.Long:
                return(ConstantValue.Create(1L));

            case BinaryOperatorKind.ULong:
                return(ConstantValue.Create(1LU));

            case BinaryOperatorKind.Float:
                return(ConstantValue.Create(1f));

            case BinaryOperatorKind.Double:
                return(ConstantValue.Create(1.0));

            case BinaryOperatorKind.Decimal:
                return(ConstantValue.Create(1m));

            default:
                throw ExceptionUtilities.UnexpectedValue(binaryOperatorKind.OperandTypes());
            }
        }
コード例 #2
0
 private RelationalDispatch(SyntaxNode syntax, ConstantValue value, BinaryOperatorKind op, ValueDispatchNode left, ValueDispatchNode right) : base(syntax)
 {
     Debug.Assert(op.OperandTypes() != 0);
     this.Value    = value;
     this.Operator = op;
     WithLeftAndRight(left, right);
 }
コード例 #3
0
        private TypeSymbol LiftedType(BinaryOperatorKind kind)
        {
            Debug.Assert(kind.IsLifted());

            var nullable = _compilation.GetSpecialType(SpecialType.core_Option_T);

            switch (kind.OperandTypes())
            {
            case BinaryOperatorKind.Int32: return(nullable.Construct(_compilation.GetSpecialType(SpecialType.System_Int32)));

            case BinaryOperatorKind.UInt32: return(nullable.Construct(_compilation.GetSpecialType(SpecialType.System_UInt32)));

            case BinaryOperatorKind.Int64: return(nullable.Construct(_compilation.GetSpecialType(SpecialType.System_Int64)));

            case BinaryOperatorKind.UInt64: return(nullable.Construct(_compilation.GetSpecialType(SpecialType.System_UInt64)));

            case BinaryOperatorKind.Float32: return(nullable.Construct(_compilation.GetSpecialType(SpecialType.System_Float32)));

            case BinaryOperatorKind.Float64: return(nullable.Construct(_compilation.GetSpecialType(SpecialType.System_Float64)));

            case BinaryOperatorKind.Int: return(nullable.Construct(_compilation.GetSpecialType(SpecialType.System_Int)));

            case BinaryOperatorKind.UInt: return(nullable.Construct(_compilation.GetSpecialType(SpecialType.System_UInt)));

            case BinaryOperatorKind.Bool: return(nullable.Construct(_compilation.GetSpecialType(SpecialType.System_Boolean)));
            }
            Debug.Assert(false, "Bad operator kind in lifted type");
            return(null);
        }
コード例 #4
0
        private TypeSymbol LiftedType(BinaryOperatorKind kind)
        {
            Debug.Assert(kind.IsLifted());

            var nullable = Compilation.GetSpecialType(SpecialType.System_Nullable_T);

            switch (kind.OperandTypes())
            {
            case BinaryOperatorKind.Int: return(nullable.Construct(Compilation.GetSpecialType(SpecialType.System_Int32)));

            case BinaryOperatorKind.UInt: return(nullable.Construct(Compilation.GetSpecialType(SpecialType.System_UInt32)));

            case BinaryOperatorKind.Long: return(nullable.Construct(Compilation.GetSpecialType(SpecialType.System_Int64)));

            case BinaryOperatorKind.ULong: return(nullable.Construct(Compilation.GetSpecialType(SpecialType.System_UInt64)));

            case BinaryOperatorKind.Float: return(nullable.Construct(Compilation.GetSpecialType(SpecialType.System_Single)));

            case BinaryOperatorKind.Double: return(nullable.Construct(Compilation.GetSpecialType(SpecialType.System_Double)));

            case BinaryOperatorKind.Decimal: return(nullable.Construct(Compilation.GetSpecialType(SpecialType.System_Decimal)));

            case BinaryOperatorKind.Bool: return(nullable.Construct(Compilation.GetSpecialType(SpecialType.System_Boolean)));
            }
            Debug.Assert(false, "Bad operator kind in lifted type");
            return(null);
        }
コード例 #5
0
        public static bool IsIntegral(this BinaryOperatorKind kind)
        {
            switch (kind.OperandTypes())
            {
            case BinaryOperatorKind.Int:
            case BinaryOperatorKind.UInt:
            case BinaryOperatorKind.Long:
            case BinaryOperatorKind.ULong:
            case BinaryOperatorKind.NInt:
            case BinaryOperatorKind.NUInt:
            case BinaryOperatorKind.Char:
            case BinaryOperatorKind.Enum:
            case BinaryOperatorKind.EnumAndUnderlying:
            case BinaryOperatorKind.UnderlyingAndEnum:
            case BinaryOperatorKind.Pointer:
            case BinaryOperatorKind.PointerAndInt:
            case BinaryOperatorKind.PointerAndUInt:
            case BinaryOperatorKind.PointerAndLong:
            case BinaryOperatorKind.PointerAndULong:
            case BinaryOperatorKind.IntAndPointer:
            case BinaryOperatorKind.UIntAndPointer:
            case BinaryOperatorKind.LongAndPointer:
            case BinaryOperatorKind.ULongAndPointer:
                return(true);
            }

            return(false);
        }
コード例 #6
0
ファイル: EmitOperators.cs プロジェクト: lachbaer/roslyn1612
        private static bool IsUnsignedBinaryOperator(BoundBinaryOperator op)
        {
            BinaryOperatorKind opKind = op.OperatorKind;
            BinaryOperatorKind type   = opKind.OperandTypes();

            switch (type)
            {
            case BinaryOperatorKind.Enum:
            case BinaryOperatorKind.EnumAndUnderlying:
                return(IsUnsigned(Binder.GetEnumPromotedType(op.Left.Type.GetEnumUnderlyingType().SpecialType)));

            case BinaryOperatorKind.UnderlyingAndEnum:
                return(IsUnsigned(Binder.GetEnumPromotedType(op.Right.Type.GetEnumUnderlyingType().SpecialType)));

            case BinaryOperatorKind.UInt:
            case BinaryOperatorKind.ULong:
            case BinaryOperatorKind.ULongAndPointer:
            case BinaryOperatorKind.PointerAndInt:
            case BinaryOperatorKind.PointerAndUInt:
            case BinaryOperatorKind.PointerAndLong:
            case BinaryOperatorKind.PointerAndULong:
            case BinaryOperatorKind.Pointer:
                return(true);

            // Dev10 bases signedness on the first operand (see ILGENREC::genOperatorExpr).
            case BinaryOperatorKind.IntAndPointer:
            case BinaryOperatorKind.LongAndPointer:
            // Dev10 converts the uint to a native int, so it counts as signed.
            case BinaryOperatorKind.UIntAndPointer:
            default:
                return(false);
            }
        }
コード例 #7
0
        private BoundExpression VisitBinaryOperator(BinaryOperatorKind opKind, MethodSymbol methodOpt, TypeSymbol type, BoundExpression left, BoundExpression right)
        {
            bool   isChecked, isLifted, requiresLifted;
            string opName = GetBinaryOperatorName(opKind, out isChecked, out isLifted, out requiresLifted);

            // Fix up the null value for a nullable comparison vs null
            if ((object)left.Type == null && left.IsLiteralNull())
            {
                left = _bound.Default(right.Type);
            }
            if ((object)right.Type == null && right.IsLiteralNull())
            {
                right = _bound.Default(left.Type);
            }


            // Enums are handled as per their promoted underlying type
            switch (opKind.OperandTypes())
            {
            case BinaryOperatorKind.EnumAndUnderlying:
            case BinaryOperatorKind.UnderlyingAndEnum:
            case BinaryOperatorKind.Enum:
            {
                var enumOperand  = (opKind.OperandTypes() == BinaryOperatorKind.UnderlyingAndEnum) ? right : left;
                var promotedType = PromotedType(enumOperand.Type.StrippedType().GetEnumUnderlyingType());
                if (opKind.IsLifted())
                {
                    promotedType = _nullableType.Construct(promotedType);
                }

                var loweredLeft  = VisitAndPromoteEnumOperand(left, promotedType, isChecked);
                var loweredRight = VisitAndPromoteEnumOperand(right, promotedType, isChecked);

                var result = MakeBinary(methodOpt, type, isLifted, requiresLifted, opName, loweredLeft, loweredRight);
                return(Demote(result, type, isChecked));
            }

            default:
            {
                var loweredLeft  = Visit(left);
                var loweredRight = Visit(right);
                return(MakeBinary(methodOpt, type, isLifted, requiresLifted, opName, loweredLeft, loweredRight));
            }
            }
        }
コード例 #8
0
        public static bool IsEnum(this BinaryOperatorKind kind)
        {
            switch (kind.OperandTypes())
            {
            case BinaryOperatorKind.Enum:
            case BinaryOperatorKind.EnumAndUnderlying:
            case BinaryOperatorKind.UnderlyingAndEnum:
                return(true);
            }

            return(false);
        }
コード例 #9
0
ファイル: BuiltInOperators.cs プロジェクト: drcjt/Sloth
        private TypeSymbol ReturnType(BinaryOperatorKind kind)
        {
            switch (kind.OperandTypes())
            {
            case BinaryOperatorKind.Int: return(_compilation.GetSpecialType(SpecialType.System_Int32));

            case BinaryOperatorKind.String:
                return(_compilation.GetSpecialType(SpecialType.System_String));
            }
            Debug.Assert(false, "Bad operator kind in return type");
            return(null);
        }
コード例 #10
0
ファイル: EmitOperators.cs プロジェクト: lachbaer/roslyn1612
        private static bool IsFloat(BinaryOperatorKind opKind)
        {
            var type = opKind.OperandTypes();

            switch (type)
            {
            case BinaryOperatorKind.Float:
            case BinaryOperatorKind.Double:
                return(true);

            default:
                return(false);
            }
        }
コード例 #11
0
        private TypeSymbol RightType(BinaryOperatorKind kind)
        {
            if (kind.IsLifted())
            {
                return(LiftedType(kind));
            }
            else
            {
                switch (kind.OperandTypes())
                {
                case BinaryOperatorKind.Int32: return(_compilation.GetSpecialType(SpecialType.System_Int32));

                case BinaryOperatorKind.UInt32: return(_compilation.GetSpecialType(SpecialType.System_UInt32));

                case BinaryOperatorKind.Int64: return(_compilation.GetSpecialType(SpecialType.System_Int64));

                case BinaryOperatorKind.UInt64: return(_compilation.GetSpecialType(SpecialType.System_UInt64));

                case BinaryOperatorKind.Float32: return(_compilation.GetSpecialType(SpecialType.System_Float32));

                case BinaryOperatorKind.Float64: return(_compilation.GetSpecialType(SpecialType.System_Float64));

                case BinaryOperatorKind.Int: return(_compilation.GetSpecialType(SpecialType.System_Int));

                case BinaryOperatorKind.UInt: return(_compilation.GetSpecialType(SpecialType.System_UInt));

                case BinaryOperatorKind.Bool: return(_compilation.GetSpecialType(SpecialType.System_Boolean));

                case BinaryOperatorKind.ObjectAndString:
                case BinaryOperatorKind.String:
                    return(_compilation.GetSpecialType(SpecialType.System_String));

                case BinaryOperatorKind.StringAndObject:
                case BinaryOperatorKind.Object:
                    return(_compilation.GetSpecialType(SpecialType.System_Object));
                }
            }
            Debug.Assert(false, "Bad operator kind in right type");
            return(null);
        }
コード例 #12
0
ファイル: EmitOperators.cs プロジェクト: lachbaer/roslyn1612
        private static bool IsConditional(BinaryOperatorKind opKind)
        {
            switch (opKind.OperatorWithLogical())
            {
            case BinaryOperatorKind.LogicalAnd:
            case BinaryOperatorKind.LogicalOr:
            case BinaryOperatorKind.Equal:
            case BinaryOperatorKind.NotEqual:
            case BinaryOperatorKind.LessThan:
            case BinaryOperatorKind.LessThanOrEqual:
            case BinaryOperatorKind.GreaterThan:
            case BinaryOperatorKind.GreaterThanOrEqual:
                return(true);

            case BinaryOperatorKind.And:
            case BinaryOperatorKind.Or:
            case BinaryOperatorKind.Xor:
                return(opKind.OperandTypes() == BinaryOperatorKind.Bool);
            }

            return(false);
        }
コード例 #13
0
        private TypeSymbol LeftType(BinaryOperatorKind kind)
        {
            if (kind.IsLifted())
            {
                return(LiftedType(kind));
            }
            else
            {
                switch (kind.OperandTypes())
                {
                case BinaryOperatorKind.Int: return(Compilation.GetSpecialType(SpecialType.System_Int32));

                case BinaryOperatorKind.UInt: return(Compilation.GetSpecialType(SpecialType.System_UInt32));

                case BinaryOperatorKind.Long: return(Compilation.GetSpecialType(SpecialType.System_Int64));

                case BinaryOperatorKind.ULong: return(Compilation.GetSpecialType(SpecialType.System_UInt64));

                case BinaryOperatorKind.Float: return(Compilation.GetSpecialType(SpecialType.System_Single));

                case BinaryOperatorKind.Double: return(Compilation.GetSpecialType(SpecialType.System_Double));

                case BinaryOperatorKind.Decimal: return(Compilation.GetSpecialType(SpecialType.System_Decimal));

                case BinaryOperatorKind.Bool: return(Compilation.GetSpecialType(SpecialType.System_Boolean));

                case BinaryOperatorKind.ObjectAndString:
                case BinaryOperatorKind.Object:
                    return(Compilation.GetSpecialType(SpecialType.System_Object));

                case BinaryOperatorKind.String:
                case BinaryOperatorKind.StringAndObject:
                    return(Compilation.GetSpecialType(SpecialType.System_String));
                }
            }
            Debug.Assert(false, "Bad operator kind in left type");
            return(null);
        }
コード例 #14
0
        private BoundExpression LowerLiftedBuiltInComparisonOperator(
            CSharpSyntaxNode syntax,
            BinaryOperatorKind kind,
            BoundExpression loweredLeft,
            BoundExpression loweredRight)
        {
            // SPEC: For the equality operators == != :
            // SPEC: The lifted operator considers two null values equal and a null value unequal to
            // SPEC: any non-null value. If both operands are non-null the lifted operator unwraps
            // SPEC: the operands and applies the underlying operator to produce the bool result.
            // SPEC:
            // SPEC: For the relational operators < > <= >= :
            // SPEC: The lifted operator produces the value false if one or both operands
            // SPEC: are null. Otherwise the lifted operator unwraps the operands and
            // SPEC: applies the underlying operator to produce the bool result.

            // Note that this means that x == y is true but x <= y is false if both are null.
            // x <= y is not the same as (x < y) || (x == y).

            // Start with some simple optimizations for cases like one side being null.
            BoundExpression optimized = TrivialLiftedComparisonOperatorOptimizations(syntax, kind, loweredLeft, loweredRight, null);
            if (optimized != null)
            {
                return optimized;
            }

            // We rewrite x == y as 
            //
            // tempx = x; 
            // tempy = y;
            // result = tempx.GetValueOrDefault() == tempy.GetValueOrDefault() ? 
            //          tempx.HasValue == tempy.HasValue : 
            //          false;
            //
            // and x != y as
            //
            // tempx = x; 
            // tempy = y;
            // result = tempx.GetValueOrDefault() == tempy.GetValueOrDefault() ? 
            //          tempx.HasValue != tempy.HasValue : 
            //          true;
            //
            // Otherwise, we rewrite x OP y as
            //
            // tempx = x;
            // tempy = y;
            // result = tempx.GetValueOrDefault() OP tempy.GetValueOrDefault() ?
            //          tempx.HasValue & tempy.HasValue :
            //          false;
            //
            // Note that there is no reason to generate "&&" over "&"; the cost of
            // the added code for the conditional branch would be about the same as simply doing 
            // the bitwise & in the first place.
            //
            // We have not yet optimized the case where we have a known-not-null value on one side, 
            // and an unknown value on the other. In those cases we will still generate a temp, but
            // we will not generate the call to the unnecessary nullable ctor or to GetValueOrDefault.
            // Rather, we will generate the value's temp instead of a call to GetValueOrDefault, and generate
            // literal true for HasValue. The tree construction methods we call will use those constants
            // to eliminate unnecessary branches.

            BoundExpression xNonNull = NullableAlwaysHasValue(loweredLeft);
            BoundExpression yNonNull = NullableAlwaysHasValue(loweredRight);

            BoundAssignmentOperator tempAssignmentX;
            BoundLocal boundTempX = _factory.StoreToTemp(xNonNull ?? loweredLeft, out tempAssignmentX);
            BoundAssignmentOperator tempAssignmentY;
            BoundLocal boundTempY = _factory.StoreToTemp(yNonNull ?? loweredRight, out tempAssignmentY);

            BoundExpression callX_GetValueOrDefault = MakeOptimizedGetValueOrDefault(syntax, boundTempX);
            BoundExpression callY_GetValueOrDefault = MakeOptimizedGetValueOrDefault(syntax, boundTempY);
            BoundExpression callX_HasValue = MakeOptimizedHasValue(syntax, boundTempX);
            BoundExpression callY_HasValue = MakeOptimizedHasValue(syntax, boundTempY);

            // tempx.GetValueOrDefault() == tempy.GetValueOrDefault()
            BinaryOperatorKind operatorKind = kind.Operator();
            BinaryOperatorKind conditionOperator = operatorKind == BinaryOperatorKind.NotEqual ?
                BinaryOperatorKind.Equal :
                operatorKind;
            TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);

            BoundExpression condition = MakeBinaryOperator(
                syntax: syntax,
                operatorKind: conditionOperator.WithType(kind.OperandTypes()),
                loweredLeft: callX_GetValueOrDefault,
                loweredRight: callY_GetValueOrDefault,
                type: boolType,
                method: null);

            BinaryOperatorKind consequenceOperator;
            switch (operatorKind)
            {
                case BinaryOperatorKind.Equal:
                    consequenceOperator = BinaryOperatorKind.BoolEqual;
                    break;
                case BinaryOperatorKind.NotEqual:
                    consequenceOperator = BinaryOperatorKind.BoolNotEqual;
                    break;
                default:
                    consequenceOperator = BinaryOperatorKind.BoolAnd;
                    break;
            }

            // tempx.HasValue == tempy.HasValue
            BoundExpression consequence = MakeBinaryOperator(
                syntax: syntax,
                operatorKind: consequenceOperator,
                loweredLeft: callX_HasValue,
                loweredRight: callY_HasValue,
                type: boolType,
                method: null);

            // false
            BoundExpression alternative = this.MakeBooleanConstant(syntax, operatorKind == BinaryOperatorKind.NotEqual);

            // tempx.GetValueOrDefault() == tempy.GetValueOrDefault() ? 
            //          tempx.HasValue == tempy.HasValue : 
            //          false;
            BoundExpression conditionalExpression = RewriteConditionalOperator(
                syntax: syntax,
                rewrittenCondition: condition,
                rewrittenConsequence: consequence,
                rewrittenAlternative: alternative,
                constantValueOpt: null,
                rewrittenType: boolType);

            // tempx = x; 
            // tempy = y;
            // result = tempx.GetValueOrDefault() == tempy.GetValueOrDefault() ? 
            //          tempx.HasValue == tempy.HasValue : 
            //          false;
            return new BoundSequence(
                syntax: syntax,
                locals: ImmutableArray.Create<LocalSymbol>(boundTempX.LocalSymbol, boundTempY.LocalSymbol),
                sideEffects: ImmutableArray.Create<BoundExpression>(tempAssignmentX, tempAssignmentY),
                value: conditionalExpression,
                type: boolType);
        }
コード例 #15
0
        private BoundExpression MakeBinaryOperator(
            BoundBinaryOperator oldNode,
            CSharpSyntaxNode syntax,
            BinaryOperatorKind operatorKind,
            BoundExpression loweredLeft,
            BoundExpression loweredRight,
            TypeSymbol type,
            MethodSymbol method,
            bool isPointerElementAccess = false,
            bool isCompoundAssignment = false,
            BoundUnaryOperator applyParentUnaryOperator = null)
        {
            Debug.Assert(oldNode == null || (oldNode.Syntax == syntax));

            if (_inExpressionLambda)
            {
                switch (operatorKind.Operator() | operatorKind.OperandTypes())
                {
                    case BinaryOperatorKind.ObjectAndStringConcatenation:
                    case BinaryOperatorKind.StringAndObjectConcatenation:
                    case BinaryOperatorKind.StringConcatenation:
                        return RewriteStringConcatenation(syntax, operatorKind, loweredLeft, loweredRight, type);
                    case BinaryOperatorKind.DelegateCombination:
                        return RewriteDelegateOperation(syntax, operatorKind, loweredLeft, loweredRight, type, SpecialMember.System_Delegate__Combine);
                    case BinaryOperatorKind.DelegateRemoval:
                        return RewriteDelegateOperation(syntax, operatorKind, loweredLeft, loweredRight, type, SpecialMember.System_Delegate__Remove);
                    case BinaryOperatorKind.DelegateEqual:
                        return RewriteDelegateOperation(syntax, operatorKind, loweredLeft, loweredRight, type, SpecialMember.System_Delegate__op_Equality);
                    case BinaryOperatorKind.DelegateNotEqual:
                        return RewriteDelegateOperation(syntax, operatorKind, loweredLeft, loweredRight, type, SpecialMember.System_Delegate__op_Inequality);
                }
            }
            else
            // try to lower the expression.
            {
                if (operatorKind.IsDynamic())
                {
                    Debug.Assert(!isPointerElementAccess);

                    if (operatorKind.IsLogical())
                    {
                        return MakeDynamicLogicalBinaryOperator(syntax, operatorKind, loweredLeft, loweredRight, method, type, isCompoundAssignment, applyParentUnaryOperator);
                    }
                    else
                    {
                        Debug.Assert((object)method == null);
                        return _dynamicFactory.MakeDynamicBinaryOperator(operatorKind, loweredLeft, loweredRight, isCompoundAssignment, type).ToExpression();
                    }
                }

                if (operatorKind.IsLifted())
                {
                    return RewriteLiftedBinaryOperator(syntax, operatorKind, loweredLeft, loweredRight, type, method);
                }

                if (operatorKind.IsUserDefined())
                {
                    return LowerUserDefinedBinaryOperator(syntax, operatorKind, loweredLeft, loweredRight, type, method);
                }

                switch (operatorKind.OperatorWithLogical() | operatorKind.OperandTypes())
                {
                    case BinaryOperatorKind.NullableNullEqual:
                    case BinaryOperatorKind.NullableNullNotEqual:
                        return RewriteNullableNullEquality(syntax, operatorKind, loweredLeft, loweredRight, type);

                    case BinaryOperatorKind.ObjectAndStringConcatenation:
                    case BinaryOperatorKind.StringAndObjectConcatenation:
                    case BinaryOperatorKind.StringConcatenation:
                        return RewriteStringConcatenation(syntax, operatorKind, loweredLeft, loweredRight, type);

                    case BinaryOperatorKind.StringEqual:
                        return RewriteStringEquality(oldNode, syntax, operatorKind, loweredLeft, loweredRight, type, SpecialMember.System_String__op_Equality);

                    case BinaryOperatorKind.StringNotEqual:
                        return RewriteStringEquality(oldNode, syntax, operatorKind, loweredLeft, loweredRight, type, SpecialMember.System_String__op_Inequality);

                    case BinaryOperatorKind.DelegateCombination:
                        return RewriteDelegateOperation(syntax, operatorKind, loweredLeft, loweredRight, type, SpecialMember.System_Delegate__Combine);

                    case BinaryOperatorKind.DelegateRemoval:
                        return RewriteDelegateOperation(syntax, operatorKind, loweredLeft, loweredRight, type, SpecialMember.System_Delegate__Remove);

                    case BinaryOperatorKind.DelegateEqual:
                        return RewriteDelegateOperation(syntax, operatorKind, loweredLeft, loweredRight, type, SpecialMember.System_Delegate__op_Equality);

                    case BinaryOperatorKind.DelegateNotEqual:
                        return RewriteDelegateOperation(syntax, operatorKind, loweredLeft, loweredRight, type, SpecialMember.System_Delegate__op_Inequality);

                    case BinaryOperatorKind.LogicalBoolAnd:
                        if (loweredRight.ConstantValue == ConstantValue.True) return loweredLeft;
                        if (loweredLeft.ConstantValue == ConstantValue.True) return loweredRight;
                        if (loweredLeft.ConstantValue == ConstantValue.False) return loweredLeft;

                        if (loweredRight.Kind == BoundKind.Local || loweredRight.Kind == BoundKind.Parameter)
                        {
                            operatorKind &= ~BinaryOperatorKind.Logical;
                        }

                        goto default;

                    case BinaryOperatorKind.LogicalBoolOr:
                        if (loweredRight.ConstantValue == ConstantValue.False) return loweredLeft;
                        if (loweredLeft.ConstantValue == ConstantValue.False) return loweredRight;
                        if (loweredLeft.ConstantValue == ConstantValue.True) return loweredLeft;

                        if (loweredRight.Kind == BoundKind.Local || loweredRight.Kind == BoundKind.Parameter)
                        {
                            operatorKind &= ~BinaryOperatorKind.Logical;
                        }

                        goto default;

                    case BinaryOperatorKind.BoolAnd:
                        if (loweredRight.ConstantValue == ConstantValue.True) return loweredLeft;
                        if (loweredLeft.ConstantValue == ConstantValue.True) return loweredRight;
                        goto default;

                    case BinaryOperatorKind.BoolOr:
                        if (loweredRight.ConstantValue == ConstantValue.False) return loweredLeft;
                        if (loweredLeft.ConstantValue == ConstantValue.False) return loweredRight;
                        goto default;

                    case BinaryOperatorKind.BoolEqual:
                        if (loweredLeft.ConstantValue == ConstantValue.True) return loweredRight;
                        if (loweredRight.ConstantValue == ConstantValue.True) return loweredLeft;

                        if (loweredLeft.ConstantValue == ConstantValue.False)
                            return MakeUnaryOperator(UnaryOperatorKind.BoolLogicalNegation, syntax, null, loweredRight, loweredRight.Type);

                        if (loweredRight.ConstantValue == ConstantValue.False)
                            return MakeUnaryOperator(UnaryOperatorKind.BoolLogicalNegation, syntax, null, loweredLeft, loweredLeft.Type);

                        goto default;

                    case BinaryOperatorKind.BoolNotEqual:
                        if (loweredLeft.ConstantValue == ConstantValue.False) return loweredRight;
                        if (loweredRight.ConstantValue == ConstantValue.False) return loweredLeft;

                        if (loweredLeft.ConstantValue == ConstantValue.True)
                            return MakeUnaryOperator(UnaryOperatorKind.BoolLogicalNegation, syntax, null, loweredRight, loweredRight.Type);

                        if (loweredRight.ConstantValue == ConstantValue.True)
                            return MakeUnaryOperator(UnaryOperatorKind.BoolLogicalNegation, syntax, null, loweredLeft, loweredLeft.Type);

                        goto default;

                    case BinaryOperatorKind.BoolXor:
                        if (loweredLeft.ConstantValue == ConstantValue.False) return loweredRight;
                        if (loweredRight.ConstantValue == ConstantValue.False) return loweredLeft;

                        if (loweredLeft.ConstantValue == ConstantValue.True)
                            return MakeUnaryOperator(UnaryOperatorKind.BoolLogicalNegation, syntax, null, loweredRight, loweredRight.Type);

                        if (loweredRight.ConstantValue == ConstantValue.True)
                            return MakeUnaryOperator(UnaryOperatorKind.BoolLogicalNegation, syntax, null, loweredLeft, loweredLeft.Type);

                        goto default;

                    case BinaryOperatorKind.IntLeftShift:
                    case BinaryOperatorKind.UIntLeftShift:
                    case BinaryOperatorKind.IntRightShift:
                    case BinaryOperatorKind.UIntRightShift:
                        return RewriteBuiltInShiftOperation(oldNode, syntax, operatorKind, loweredLeft, loweredRight, type, 0x1F);

                    case BinaryOperatorKind.LongLeftShift:
                    case BinaryOperatorKind.ULongLeftShift:
                    case BinaryOperatorKind.LongRightShift:
                    case BinaryOperatorKind.ULongRightShift:
                        return RewriteBuiltInShiftOperation(oldNode, syntax, operatorKind, loweredLeft, loweredRight, type, 0x3F);

                    case BinaryOperatorKind.DecimalAddition:
                    case BinaryOperatorKind.DecimalSubtraction:
                    case BinaryOperatorKind.DecimalMultiplication:
                    case BinaryOperatorKind.DecimalDivision:
                    case BinaryOperatorKind.DecimalRemainder:
                    case BinaryOperatorKind.DecimalEqual:
                    case BinaryOperatorKind.DecimalNotEqual:
                    case BinaryOperatorKind.DecimalLessThan:
                    case BinaryOperatorKind.DecimalLessThanOrEqual:
                    case BinaryOperatorKind.DecimalGreaterThan:
                    case BinaryOperatorKind.DecimalGreaterThanOrEqual:
                        return RewriteDecimalBinaryOperation(syntax, loweredLeft, loweredRight, operatorKind);

                    case BinaryOperatorKind.PointerAndIntAddition:
                    case BinaryOperatorKind.PointerAndUIntAddition:
                    case BinaryOperatorKind.PointerAndLongAddition:
                    case BinaryOperatorKind.PointerAndULongAddition:
                    case BinaryOperatorKind.PointerAndIntSubtraction:
                    case BinaryOperatorKind.PointerAndUIntSubtraction:
                    case BinaryOperatorKind.PointerAndLongSubtraction:
                    case BinaryOperatorKind.PointerAndULongSubtraction:
                        if (loweredRight.IsDefaultValue())
                        {
                            return loweredLeft;
                        }
                        return RewritePointerNumericOperator(syntax, operatorKind, loweredLeft, loweredRight, type, isPointerElementAccess, isLeftPointer: true);

                    case BinaryOperatorKind.IntAndPointerAddition:
                    case BinaryOperatorKind.UIntAndPointerAddition:
                    case BinaryOperatorKind.LongAndPointerAddition:
                    case BinaryOperatorKind.ULongAndPointerAddition:
                        if (loweredLeft.IsDefaultValue())
                        {
                            return loweredRight;
                        }
                        return RewritePointerNumericOperator(syntax, operatorKind, loweredLeft, loweredRight, type, isPointerElementAccess, isLeftPointer: false);

                    case BinaryOperatorKind.PointerSubtraction:
                        return RewritePointerSubtraction(operatorKind, loweredLeft, loweredRight, type);

                    case BinaryOperatorKind.IntAddition:
                    case BinaryOperatorKind.UIntAddition:
                    case BinaryOperatorKind.LongAddition:
                    case BinaryOperatorKind.ULongAddition:
                        if (loweredLeft.IsDefaultValue())
                        {
                            return loweredRight;
                        }
                        if (loweredRight.IsDefaultValue())
                        {
                            return loweredLeft;
                        }
                        goto default;

                    case BinaryOperatorKind.IntSubtraction:
                    case BinaryOperatorKind.LongSubtraction:
                    case BinaryOperatorKind.UIntSubtraction:
                    case BinaryOperatorKind.ULongSubtraction:
                        if (loweredRight.IsDefaultValue())
                        {
                            return loweredLeft;
                        }
                        goto default;

                    case BinaryOperatorKind.IntMultiplication:
                    case BinaryOperatorKind.LongMultiplication:
                    case BinaryOperatorKind.UIntMultiplication:
                    case BinaryOperatorKind.ULongMultiplication:
                        if (loweredLeft.IsDefaultValue())
                        {
                            return loweredLeft;
                        }
                        if (loweredRight.IsDefaultValue())
                        {
                            return loweredRight;
                        }
                        if (loweredLeft.ConstantValue?.UInt64Value == 1)
                        {
                            return loweredRight;
                        }
                        if (loweredRight.ConstantValue?.UInt64Value == 1)
                        {
                            return loweredLeft;
                        }
                        goto default;

                    case BinaryOperatorKind.IntGreaterThan:
                    case BinaryOperatorKind.IntLessThanOrEqual:
                        if (loweredLeft.Kind == BoundKind.ArrayLength && loweredRight.IsDefaultValue())
                        {
                            //array length is never negative
                            var newOp = operatorKind == BinaryOperatorKind.IntGreaterThan ?
                                                        BinaryOperatorKind.NotEqual :
                                                        BinaryOperatorKind.Equal;

                            operatorKind &= ~BinaryOperatorKind.OpMask;
                            operatorKind |= newOp;
                            loweredLeft = UnconvertArrayLength((BoundArrayLength)loweredLeft);
                        }
                        goto default;

                    case BinaryOperatorKind.IntLessThan:
                    case BinaryOperatorKind.IntGreaterThanOrEqual:
                        if (loweredRight.Kind == BoundKind.ArrayLength && loweredLeft.IsDefaultValue())
                        {
                            //array length is never negative
                            var newOp = operatorKind == BinaryOperatorKind.IntLessThan ?
                                                        BinaryOperatorKind.NotEqual :
                                                        BinaryOperatorKind.Equal;

                            operatorKind &= ~BinaryOperatorKind.OpMask;
                            operatorKind |= newOp;
                            loweredRight = UnconvertArrayLength((BoundArrayLength)loweredRight);
                        }
                        goto default;

                    case BinaryOperatorKind.IntEqual:
                    case BinaryOperatorKind.IntNotEqual:
                        if (loweredLeft.Kind == BoundKind.ArrayLength && loweredRight.IsDefaultValue())
                        {
                            loweredLeft = UnconvertArrayLength((BoundArrayLength)loweredLeft);
                        }
                        else if (loweredRight.Kind == BoundKind.ArrayLength && loweredLeft.IsDefaultValue())
                        {
                            loweredRight = UnconvertArrayLength((BoundArrayLength)loweredRight);
                        }

                        goto default;

                    default:
                        break;
                }
            }

            return (oldNode != null) ?
                oldNode.Update(operatorKind, loweredLeft, loweredRight, oldNode.ConstantValueOpt, oldNode.MethodOpt, oldNode.ResultKind, type) :
                new BoundBinaryOperator(syntax, operatorKind, loweredLeft, loweredRight, null, null, LookupResultKind.Viable, type);
        }
コード例 #16
0
        private BoundExpression MakeBuiltInIncrementOperator(BoundIncrementOperator node, BoundExpression rewrittenValueToIncrement)
        {
            BoundExpression result;
            // If we have a built-in increment or decrement then things get a bit trickier. Suppose for example we have
            // a user-defined conversion from X to short and from short to X, but no user-defined increment operator on
            // X.  The increment portion of "++x" is then: (X)(short)((int)(short)x + 1). That is, first x must be
            // converted to short via an implicit user- defined conversion, then to int via an implicit numeric
            // conversion, then the addition is performed in integers. The resulting integer is converted back to short,
            // and then the short is converted to X.

            // This is the input and output type of the unary increment operator we're going to call.
            // That is, "short" in the example above.
            TypeSymbol unaryOperandType = GetUnaryOperatorType(node);

            // This is the kind of binary operator that we're going to realize the unary operator
            // as. That is, "int + int --> int" in the example above.
            BinaryOperatorKind binaryOperatorKind = GetCorrespondingBinaryOperator(node);

            binaryOperatorKind |= IsIncrement(node) ? BinaryOperatorKind.Addition : BinaryOperatorKind.Subtraction;

            // The "1" in the example above.
            ConstantValue constantOne = GetConstantOneForBinOp(binaryOperatorKind);

            Debug.Assert(constantOne != null);
            Debug.Assert(constantOne.SpecialType != SpecialType.None);
            Debug.Assert(binaryOperatorKind.OperandTypes() != 0);

            // The input/output type of the binary operand. "int" in the example.
            TypeSymbol binaryOperandType = _compilation.GetSpecialType(constantOne.SpecialType);

            // 1
            BoundExpression boundOne = MakeLiteral(
                syntax: node.Syntax,
                constantValue: constantOne,
                type: binaryOperandType);

            if (binaryOperatorKind.IsLifted())
            {
                binaryOperandType = _compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(binaryOperandType);
                MethodSymbol ctor = UnsafeGetNullableMethod(node.Syntax, binaryOperandType, SpecialMember.System_Nullable_T__ctor);
                boundOne = new BoundObjectCreationExpression(node.Syntax, ctor, boundOne);
            }

            // Now we construct the other operand to the binary addition. We start with just plain "x".
            BoundExpression binaryOperand = rewrittenValueToIncrement;

            bool @checked = node.OperatorKind.IsChecked();

            // If we need to make a conversion from the original operand type to the operand type of the
            // underlying increment operation, do it now.
            if (!node.OperandConversion.IsIdentity)
            {
                // (short)x
                binaryOperand = MakeConversionNode(
                    syntax: node.Syntax,
                    rewrittenOperand: binaryOperand,
                    conversion: node.OperandConversion,
                    rewrittenType: unaryOperandType,
                    @checked: @checked);
            }

            // Early-out for pointer increment - we don't need to convert the operands to a common type.
            if (node.OperatorKind.OperandTypes() == UnaryOperatorKind.Pointer)
            {
                Debug.Assert(binaryOperatorKind.OperandTypes() == BinaryOperatorKind.PointerAndInt);
                Debug.Assert(binaryOperand.Type.IsPointerType());
                Debug.Assert(boundOne.Type.SpecialType == SpecialType.System_Int32);
                return(MakeBinaryOperator(node.Syntax, binaryOperatorKind, binaryOperand, boundOne, binaryOperand.Type, method: null));
            }

            // If we need to make a conversion from the unary operator type to the binary operator type,
            // do it now.

            // (int)(short)x
            binaryOperand = MakeConversionNode(binaryOperand, binaryOperandType, @checked);

            // Perform the addition.

            // (int)(short)x + 1
            BoundExpression binOp;

            if (unaryOperandType.SpecialType == SpecialType.System_Decimal)
            {
                binOp = MakeDecimalIncDecOperator(node.Syntax, binaryOperatorKind, binaryOperand);
            }
            else if (unaryOperandType.IsNullableType() && unaryOperandType.GetNullableUnderlyingType().SpecialType == SpecialType.System_Decimal)
            {
                binOp = MakeLiftedDecimalIncDecOperator(node.Syntax, binaryOperatorKind, binaryOperand);
            }
            else
            {
                binOp = MakeBinaryOperator(node.Syntax, binaryOperatorKind, binaryOperand, boundOne, binaryOperandType, method: null);
            }

            // Generate the conversion back to the type of the unary operator.

            // (short)((int)(short)x + 1)
            result = MakeConversionNode(binOp, unaryOperandType, @checked);
            return(result);
        }
コード例 #17
0
ファイル: EmitOperators.cs プロジェクト: xier2012/roslyn
        private static bool IsConditional(BinaryOperatorKind opKind)
        {
            switch (opKind.OperatorWithLogical())
            {
                case BinaryOperatorKind.LogicalAnd:
                case BinaryOperatorKind.LogicalOr:
                case BinaryOperatorKind.Equal:
                case BinaryOperatorKind.NotEqual:
                case BinaryOperatorKind.LessThan:
                case BinaryOperatorKind.LessThanOrEqual:
                case BinaryOperatorKind.GreaterThan:
                case BinaryOperatorKind.GreaterThanOrEqual:
                    return true;

                case BinaryOperatorKind.And:
                case BinaryOperatorKind.Or:
                case BinaryOperatorKind.Xor:
                    return opKind.OperandTypes() == BinaryOperatorKind.Bool;
            }

            return false;
        }
コード例 #18
0
        private BoundExpression VisitBinaryOperator(BinaryOperatorKind opKind, MethodSymbol methodOpt, TypeSymbol type, BoundExpression left, BoundExpression right)
        {
            bool isChecked, isLifted, requiresLifted;
            string opName = GetBinaryOperatorName(opKind, out isChecked, out isLifted, out requiresLifted);

            // Fix up the null value for a nullable comparison vs null
            if ((object)left.Type == null && left.IsLiteralNull())
            {
                left = _bound.Default(right.Type);
            }
            if ((object)right.Type == null && right.IsLiteralNull())
            {
                right = _bound.Default(left.Type);
            }

            var loweredLeft = Visit(left);
            var loweredRight = Visit(right);

            // Enums are handled as per their promoted underlying type
            switch (opKind.OperandTypes())
            {
                case BinaryOperatorKind.Enum:
                case BinaryOperatorKind.EnumAndUnderlying:
                case BinaryOperatorKind.UnderlyingAndEnum:
                    {
                        var enumOperand = (opKind.OperandTypes() == BinaryOperatorKind.UnderlyingAndEnum) ? right : left;
                        var promotedType = PromotedType(enumOperand.Type.StrippedType().GetEnumUnderlyingType());
                        if (opKind.IsLifted())
                        {
                            promotedType = _nullableType.Construct(promotedType);
                        }

                        loweredLeft = PromoteEnumOperand(left, loweredLeft, promotedType, isChecked);
                        loweredRight = PromoteEnumOperand(right, loweredRight, promotedType, isChecked);

                        var result = MakeBinary(methodOpt, type, isLifted, requiresLifted, opName, loweredLeft, loweredRight);
                        return Demote(result, type, isChecked);
                    }
                default:
                    return MakeBinary(methodOpt, type, isLifted, requiresLifted, opName, loweredLeft, loweredRight);
            }
        }
コード例 #19
0
ファイル: EmitOperators.cs プロジェクト: xier2012/roslyn
 private static bool IsFloat(BinaryOperatorKind opKind)
 {
     var type = opKind.OperandTypes();
     switch (type)
     {
         case BinaryOperatorKind.Float:
         case BinaryOperatorKind.Double:
             return true;
         default:
             return false;
     }
 }
コード例 #20
0
 private static ConstantValue GetConstantOneForBinOp(
     BinaryOperatorKind binaryOperatorKind)
 {
     switch (binaryOperatorKind.OperandTypes())
     {
         case BinaryOperatorKind.PointerAndInt:
         case BinaryOperatorKind.Int:
             return ConstantValue.Create(1);
         case BinaryOperatorKind.UInt:
             return ConstantValue.Create(1U);
         case BinaryOperatorKind.Long:
             return ConstantValue.Create(1L);
         case BinaryOperatorKind.ULong:
             return ConstantValue.Create(1LU);
         case BinaryOperatorKind.Float:
             return ConstantValue.Create(1f);
         case BinaryOperatorKind.Double:
             return ConstantValue.Create(1.0);
         case BinaryOperatorKind.Decimal:
             return ConstantValue.Create(1m);
         default:
             throw ExceptionUtilities.UnexpectedValue(binaryOperatorKind.OperandTypes());
     }
 }
コード例 #21
0
 public static bool IsDynamic(this BinaryOperatorKind kind)
 {
     return(kind.OperandTypes() == BinaryOperatorKind.Dynamic);
 }
コード例 #22
0
ファイル: BuiltInOperators.cs プロジェクト: riversky/roslyn
        private TypeSymbol LiftedType(BinaryOperatorKind kind)
        {
            Debug.Assert(kind.IsLifted());

            var nullable = Compilation.GetSpecialType(SpecialType.System_Nullable_T);

            switch (kind.OperandTypes())
            {
                case BinaryOperatorKind.Int: return nullable.Construct(Compilation.GetSpecialType(SpecialType.System_Int32));
                case BinaryOperatorKind.UInt: return nullable.Construct(Compilation.GetSpecialType(SpecialType.System_UInt32));
                case BinaryOperatorKind.Long: return nullable.Construct(Compilation.GetSpecialType(SpecialType.System_Int64));
                case BinaryOperatorKind.ULong: return nullable.Construct(Compilation.GetSpecialType(SpecialType.System_UInt64));
                case BinaryOperatorKind.Float: return nullable.Construct(Compilation.GetSpecialType(SpecialType.System_Single));
                case BinaryOperatorKind.Double: return nullable.Construct(Compilation.GetSpecialType(SpecialType.System_Double));
                case BinaryOperatorKind.Decimal: return nullable.Construct(Compilation.GetSpecialType(SpecialType.System_Decimal));
                case BinaryOperatorKind.Bool: return nullable.Construct(Compilation.GetSpecialType(SpecialType.System_Boolean));
            }
            Debug.Assert(false, "Bad operator kind in lifted type");
            return null;
        }
コード例 #23
0
ファイル: BuiltInOperators.cs プロジェクト: riversky/roslyn
 private TypeSymbol ReturnType(BinaryOperatorKind kind)
 {
     if (kind.IsLifted())
     {
         return LiftedType(kind);
     }
     else
     {
         switch (kind.OperandTypes())
         {
             case BinaryOperatorKind.Int: return Compilation.GetSpecialType(SpecialType.System_Int32);
             case BinaryOperatorKind.UInt: return Compilation.GetSpecialType(SpecialType.System_UInt32);
             case BinaryOperatorKind.Long: return Compilation.GetSpecialType(SpecialType.System_Int64);
             case BinaryOperatorKind.ULong: return Compilation.GetSpecialType(SpecialType.System_UInt64);
             case BinaryOperatorKind.Float: return Compilation.GetSpecialType(SpecialType.System_Single);
             case BinaryOperatorKind.Double: return Compilation.GetSpecialType(SpecialType.System_Double);
             case BinaryOperatorKind.Decimal: return Compilation.GetSpecialType(SpecialType.System_Decimal);
             case BinaryOperatorKind.Bool: return Compilation.GetSpecialType(SpecialType.System_Boolean);
             case BinaryOperatorKind.Object: return Compilation.GetSpecialType(SpecialType.System_Object);
             case BinaryOperatorKind.ObjectAndString:
             case BinaryOperatorKind.StringAndObject:
             case BinaryOperatorKind.String:
                 return Compilation.GetSpecialType(SpecialType.System_String);
         }
     }
     Debug.Assert(false, "Bad operator kind in return type");
     return null;
 }