예제 #1
0
        private void EmitTypeBinaryExpression(Expression expr)
        {
            TypeBinaryExpression node = (TypeBinaryExpression)expr;

            if (node.NodeType == ExpressionType.TypeEqual)
            {
                EmitExpression(node.ReduceTypeEqual());
                return;
            }

            Type type = node.Expression.Type;

            // Try to determine the result statically
            AnalyzeTypeIsResult result = ConstantCheck.AnalyzeTypeIs(node);

            if (result == AnalyzeTypeIsResult.KnownTrue ||
                result == AnalyzeTypeIsResult.KnownFalse)
            {
                // Result is known statically, so just emit the expression for
                // its side effects and return the result
                EmitExpressionAsVoid(node.Expression);
                _ilg.EmitBoolean(result == AnalyzeTypeIsResult.KnownTrue);
                return;
            }

            if (result == AnalyzeTypeIsResult.KnownAssignable)
            {
                // We know the type can be assigned, but still need to check
                // for null at runtime
                if (type.IsNullableType())
                {
                    EmitAddress(node.Expression, type);
                    _ilg.EmitHasValue(type);
                    return;
                }

                Debug.Assert(!type.GetTypeInfo().IsValueType);
                EmitExpression(node.Expression);
                _ilg.Emit(OpCodes.Ldnull);
                _ilg.Emit(OpCodes.Ceq);
                _ilg.Emit(OpCodes.Ldc_I4_0);
                _ilg.Emit(OpCodes.Ceq);
                return;
            }

            Debug.Assert(result == AnalyzeTypeIsResult.Unknown);

            // Emit a full runtime "isinst" check
            EmitExpression(node.Expression);
            if (type.GetTypeInfo().IsValueType)
            {
                _ilg.Emit(OpCodes.Box, type);
            }
            _ilg.Emit(OpCodes.Isinst, node.TypeOperand);
            _ilg.Emit(OpCodes.Ldnull);
            _ilg.Emit(OpCodes.Cgt_Un);
        }
예제 #2
0
        private void EmitTypeBinaryExpression(Expression expr)
        {
            var node = (TypeBinaryExpression)expr;

            if (node.NodeType == ExpressionType.TypeEqual)
            {
                EmitExpression(node.ReduceTypeEqual());
                return;
            }

            var type = node.Expression.Type;

            // Try to determine the result statically
            var result = ConstantCheck.AnalyzeTypeIs(node);

            switch (result)
            {
            case AnalyzeTypeIsResult.KnownTrue:
            case AnalyzeTypeIsResult.KnownFalse:
                // Result is known statically, so just emit the expression for
                // its side effects and return the result
                EmitExpressionAsVoid(node.Expression);
                IL.EmitPrimitive(result == AnalyzeTypeIsResult.KnownTrue);
                return;

            case AnalyzeTypeIsResult.KnownAssignable when type.IsNullable():
                EmitAddress(node.Expression, type);

                IL.EmitHasValue(type);
                return;

            case AnalyzeTypeIsResult.KnownAssignable:
                Debug.Assert(!type.IsValueType);
                EmitExpression(node.Expression);
                IL.Emit(OpCodes.Ldnull);
                IL.Emit(OpCodes.Cgt_Un);
                return;

            default:
                break;
            }

            Debug.Assert(result == AnalyzeTypeIsResult.Unknown);

            // Emit a full runtime "isinst" check
            EmitExpression(node.Expression);
            if (type.IsValueType)
            {
                IL.Emit(OpCodes.Box, type);
            }

            IL.Emit(OpCodes.Isinst, node.TypeOperand);
            IL.Emit(OpCodes.Ldnull);
            IL.Emit(OpCodes.Cgt_Un);
        }