예제 #1
0
파일: nullable.cs 프로젝트: sagood/mono
        public override void Emit(EmitContext ec)
        {
            Label end_label = ec.DefineLabel();

            if (unwrap != null)
            {
                Label is_null_label = ec.DefineLabel();

                unwrap.EmitCheck(ec);
                ec.Emit(OpCodes.Brfalse, is_null_label);

                //
                // When both expressions are nullable the unwrap
                // is needed only for null check not for value uwrap
                //
                if (type.IsNullableType && TypeSpecComparer.IsEqual(NullableInfo.GetUnderlyingType(type), unwrap.Type))
                {
                    unwrap.Load(ec);
                }
                else
                {
                    left.Emit(ec);
                }

                ec.Emit(OpCodes.Br, end_label);

                ec.MarkLabel(is_null_label);
                right.Emit(ec);

                ec.MarkLabel(end_label);
                return;
            }

            left.Emit(ec);
            ec.Emit(OpCodes.Dup);

            // Only to make verifier happy
            if (left.Type.IsGenericParameter)
            {
                ec.Emit(OpCodes.Box, left.Type);
            }

            ec.Emit(OpCodes.Brtrue, end_label);

            ec.Emit(OpCodes.Pop);
            right.Emit(ec);

            ec.MarkLabel(end_label);
        }
예제 #2
0
파일: nullable.cs 프로젝트: mdae/MonoRT
        void EmitBitwiseBoolean(EmitContext ec)
        {
            ILGenerator ig = ec.ig;

            Label load_left  = ig.DefineLabel();
            Label load_right = ig.DefineLabel();
            Label end_label  = ig.DefineLabel();

            left_unwrap.Emit(ec);
            ig.Emit(OpCodes.Brtrue_S, load_right);

            right_unwrap.Emit(ec);
            ig.Emit(OpCodes.Brtrue_S, load_left);

            left_unwrap.EmitCheck(ec);
            ig.Emit(OpCodes.Brfalse_S, load_right);

            // load left
            ig.MarkLabel(load_left);

            if (Oper == Operator.BitwiseAnd)
            {
                left_unwrap.Load(ec);
            }
            else
            {
                right_unwrap.Load(ec);
                right_unwrap = left_unwrap;
            }
            ig.Emit(OpCodes.Br_S, end_label);

            // load right
            ig.MarkLabel(load_right);
            right_unwrap.Load(ec);

            ig.MarkLabel(end_label);
        }
예제 #3
0
        public override void Emit(EmitContext ec)
        {
            Label end_label = ec.DefineLabel();

            if (unwrap != null)
            {
                Label is_null_label = ec.DefineLabel();

                unwrap.EmitCheck(ec);
                ec.Emit(OpCodes.Brfalse, is_null_label);

                //
                // When both expressions are nullable the unwrap
                // is needed only for null check not for value uwrap
                //
                if (type.IsNullableType && TypeSpecComparer.IsEqual(NullableInfo.GetUnderlyingType(type), unwrap.Type))
                {
                    unwrap.Load(ec);
                }
                else
                {
                    left.Emit(ec);
                }

                ec.Emit(OpCodes.Br, end_label);

                ec.MarkLabel(is_null_label);
                right.Emit(ec);

                ec.MarkLabel(end_label);
                return;
            }

            //
            // Null check is done on original expression not after expression is converted to
            // result type. This is in most cases same but when user conversion is involved
            // we can end up in situation when user operator does the null handling which is
            // not what the operator is supposed to do.
            // There is tricky case where cast of left expression is meant to be cast of
            // whole source expression (null check is done on it) and cast from right-to-left
            // conversion needs to do null check on unconverted source expression.
            //
            if (user_conversion_left)
            {
                var op_expr = (UserCast)left;

                op_expr.Source.Emit(ec);
                LocalTemporary temp;

                // TODO: More load kinds can be special cased
                if (!(op_expr.Source is VariableReference))
                {
                    temp = new LocalTemporary(op_expr.Source.Type);
                    temp.Store(ec);
                    temp.Emit(ec);
                    op_expr.Source = temp;
                }
                else
                {
                    temp = null;
                }

                var right_label = ec.DefineLabel();
                ec.Emit(OpCodes.Brfalse_S, right_label);
                left.Emit(ec);
                ec.Emit(OpCodes.Br, end_label);
                ec.MarkLabel(right_label);

                if (temp != null)
                {
                    temp.Release(ec);
                }
            }
            else
            {
                //
                // Common case where expression is not modified before null check and
                // we generate better/smaller code
                //
                left.Emit(ec);
                ec.Emit(OpCodes.Dup);

                // Only to make verifier happy
                if (left.Type.IsGenericParameter)
                {
                    ec.Emit(OpCodes.Box, left.Type);
                }

                ec.Emit(OpCodes.Brtrue, end_label);

                ec.Emit(OpCodes.Pop);
            }

            right.Emit(ec);

            ec.MarkLabel(end_label);
        }
예제 #4
0
        void EmitBitwiseBoolean(EmitContext ec)
        {
            Label load_left  = ec.DefineLabel();
            Label load_right = ec.DefineLabel();
            Label end_label  = ec.DefineLabel();

            // null & value, null | value
            if (left_unwrap == null)
            {
                left_unwrap  = right_unwrap;
                right_unwrap = null;
                right        = left;
            }

            left_unwrap.Emit(ec);
            ec.Emit(OpCodes.Brtrue_S, load_right);

            // value & null, value | null
            if (right_unwrap != null)
            {
                right_unwrap.Emit(ec);
                ec.Emit(OpCodes.Brtrue_S, load_left);
            }

            left_unwrap.EmitCheck(ec);
            ec.Emit(OpCodes.Brfalse_S, load_right);

            // load left
            ec.MarkLabel(load_left);

            if (Oper == Operator.BitwiseAnd)
            {
                left_unwrap.Load(ec);
            }
            else
            {
                if (right_unwrap == null)
                {
                    right.Emit(ec);
                    if (right is EmptyConstantCast || right is EmptyCast)
                    {
                        ec.Emit(OpCodes.Newobj, NullableInfo.GetConstructor(type));
                    }
                }
                else
                {
                    right_unwrap.Load(ec);
                    right_unwrap = left_unwrap;
                }
            }
            ec.Emit(OpCodes.Br_S, end_label);

            // load right
            ec.MarkLabel(load_right);
            if (right_unwrap == null)
            {
                if (Oper == Operator.BitwiseAnd)
                {
                    right.Emit(ec);
                    if (right is EmptyConstantCast || right is EmptyCast)
                    {
                        ec.Emit(OpCodes.Newobj, NullableInfo.GetConstructor(type));
                    }
                }
                else
                {
                    left_unwrap.Load(ec);
                }
            }
            else
            {
                right_unwrap.Load(ec);
            }

            ec.MarkLabel(end_label);
        }