Beispiel #1
0
        void DoEmit(EmitContext ec, bool is_expr)
        {
            Label is_null_label = ec.DefineLabel();
            Label end_label     = ec.DefineLabel();

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

            if (is_expr)
            {
                underlying.Emit(ec);
                ec.Emit(OpCodes.Br_S, end_label);
            }
            else
            {
                underlying.EmitStatement(ec);
            }

            ec.MarkLabel(is_null_label);
            if (is_expr)
            {
                LiftedNull.Create(type, loc).Emit(ec);
            }

            ec.MarkLabel(end_label);
        }
Beispiel #2
0
        public override void Emit(EmitContext ec)
        {
            Label is_null_label = ec.DefineLabel();
            Label end_label     = ec.DefineLabel();

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

            if (user_operator != null)
            {
                user_operator.Emit(ec);
            }
            else
            {
                EmitOperator(ec, NullableInfo.GetUnderlyingType(type));
            }

            ec.Emit(OpCodes.Newobj, NullableInfo.GetConstructor(type));
            ec.Emit(OpCodes.Br_S, end_label);

            ec.MarkLabel(is_null_label);
            LiftedNull.Create(type, loc).Emit(ec);

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

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

            NullableInfo ni = new NullableInfo(type);

            if (user_operator != null)
            {
                user_operator.Emit(ec);
            }
            else
            {
                EmitOperator(ec, ni.UnderlyingType);
            }

            ig.Emit(OpCodes.Newobj, ni.Constructor);
            ig.Emit(OpCodes.Br_S, end_label);

            ig.MarkLabel(is_null_label);
            LiftedNull.Create(type, loc).Emit(ec);

            ig.MarkLabel(end_label);
        }
Beispiel #4
0
        public override void Emit(EmitContext ec)
        {
            ILGenerator ig = ec.ig;

            Label end_label = ig.DefineLabel();

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

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

                left.Emit(ec);
                ig.Emit(OpCodes.Br, end_label);

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

                ig.MarkLabel(end_label);
                return;
            }

            left.Emit(ec);

            ig.Emit(OpCodes.Dup);
            ig.Emit(OpCodes.Brtrue, end_label);

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

            ig.MarkLabel(end_label);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
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;
            }

            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);
        }
Beispiel #7
0
        public override void Emit(EmitContext ec)
        {
            Label is_null_label = ec.DefineLabel();
            Label end_label     = ec.DefineLabel();

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

            expr.Emit(ec);

            ec.Emit(OpCodes.Br, end_label);
            ec.MarkLabel(is_null_label);

            null_value.Emit(ec);
            ec.MarkLabel(end_label);
        }
Beispiel #8
0
        public override void Emit(EmitContext ec)
        {
            ILGenerator ig            = ec.ig;
            Label       is_null_label = ig.DefineLabel();
            Label       end_label     = ig.DefineLabel();

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

            expr.Emit(ec);

            ig.Emit(OpCodes.Br, end_label);
            ig.MarkLabel(is_null_label);

            null_value.Emit(ec);
            ig.MarkLabel(end_label);
        }
Beispiel #9
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);

                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);
        }
Beispiel #10
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);
        }
Beispiel #11
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);
        }