コード例 #1
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);
        }
コード例 #2
0
ファイル: nullable.cs プロジェクト: saga/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);

				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);
		}
コード例 #3
0
ファイル: nullable.cs プロジェクト: Paccc/SharpDevelop
		void EmitBitwiseBoolean (EmitContext ec)
		{
			Label load_left = ec.DefineLabel ();
			Label load_right = ec.DefineLabel ();
			Label end_label = ec.DefineLabel ();
			Label is_null_label = ec.DefineLabel ();

			bool or = Binary.Oper == Binary.Operator.BitwiseOr;

			//
			// Both operands are bool? types
			//
			if (UnwrapLeft != null && UnwrapRight != null) {
				if (ec.HasSet (BuilderContext.Options.AsyncBody) && Binary.Right.ContainsEmitWithAwait ()) {
					Left = Left.EmitToField (ec);
					Right = Right.EmitToField (ec);
				}

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

				Right.Emit (ec);
				ec.Emit (OpCodes.Brtrue_S, load_left);

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

				// load left
				ec.MarkLabel (load_left);
				if (or)
					UnwrapRight.Load (ec);
				else
					UnwrapLeft.Load (ec);

				ec.Emit (OpCodes.Br_S, end_label);

				// load right
				ec.MarkLabel (load_right);
				if (or)
					UnwrapLeft.Load (ec);
				else
					UnwrapRight.Load (ec);

				ec.MarkLabel (end_label);
				return;
			}

			//
			// Faster version when one operand is bool
			//
			if (UnwrapLeft == null) {
				//
				// (bool, bool?)
				//
				// Optimizes remaining (false & bool?), (true | bool?) which are not easy to handle
				// in binary expression reduction
				//
				var c = Left as BoolConstant;
				if (c != null) {
					// Keep evaluation order
					UnwrapRight.Store (ec);

					ec.EmitInt (or ? 1 : 0);
					ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type));
				} else if (Left.IsNull) {
					UnwrapRight.Emit (ec);
					ec.Emit (or ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, is_null_label);

					UnwrapRight.Load (ec);
					ec.Emit (OpCodes.Br_S, end_label);

					ec.MarkLabel (is_null_label);
					LiftedNull.Create (type, loc).Emit (ec);
				} else {
					Left.Emit (ec);
					ec.Emit (or ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, load_right);

					ec.EmitInt (or ? 1 : 0);
					ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type));

					ec.Emit (OpCodes.Br_S, end_label);

					ec.MarkLabel (load_right);
					UnwrapRight.Original.Emit (ec);
				}
			} else {
				//
				// (bool?, bool)
				//
				// Keep left-right evaluation order
				UnwrapLeft.Store (ec);

				//
				// Optimizes remaining (bool? & false), (bool? | true) which are not easy to handle
				// in binary expression reduction
				//
				var c = Right as BoolConstant;
				if (c != null) {
					ec.EmitInt (or ? 1 : 0);
					ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type));
				} else if (Right.IsNull) {
					UnwrapLeft.Emit (ec);
					ec.Emit (or ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, is_null_label);

					UnwrapLeft.Load (ec);
					ec.Emit (OpCodes.Br_S, end_label);

					ec.MarkLabel (is_null_label);
					LiftedNull.Create (type, loc).Emit (ec);
				} else {
					Right.Emit (ec);
					ec.Emit (or ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, load_right);

					ec.EmitInt (or ? 1 : 0);
					ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type));

					ec.Emit (OpCodes.Br_S, end_label);

					ec.MarkLabel (load_right);

					UnwrapLeft.Load (ec);
				}
			}

			ec.MarkLabel (end_label);
 		}
コード例 #4
0
ファイル: nullable.cs プロジェクト: Paccc/SharpDevelop
		protected override void EmitOperation (EmitContext ec)
		{
			Label is_null_label = ec.DefineLabel ();
			Label end_label = ec.DefineLabel ();

			LocalTemporary lt = new LocalTemporary (type);

			// Value is on the stack
			lt.Store (ec);

			var call = new CallEmitter ();
			call.InstanceExpression = lt;
			call.EmitPredefined (ec, NullableInfo.GetHasValue (expr.Type), null);

			ec.Emit (OpCodes.Brfalse, is_null_label);

			call = new CallEmitter ();
			call.InstanceExpression = lt;
			call.EmitPredefined (ec, NullableInfo.GetGetValueOrDefault (expr.Type), null);

			lt.Release (ec);

			base.EmitOperation (ec);

			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);
		}
コード例 #5
0
ファイル: BinaryExpression.cs プロジェクト: jskripsky/mono
		void EmitLeftLiftedToNullBinary (EmitContext ec)
		{
			var ig = ec.ig;

			var ret = ig.DefineLabel ();
			var done = ig.DefineLabel ();

			var left = ec.EmitStored (this.left);

			ec.EmitNullableHasValue (left);
			ig.Emit (OpCodes.Brfalse, ret);

			ec.EmitNullableGetValueOrDefault (left);
			ec.Emit (right);

			EmitBinaryOperator (ec);

			ec.EmitNullableNew (Type);

			ig.Emit (OpCodes.Br, done);

			ig.MarkLabel (ret);

			var temp = ig.DeclareLocal (Type);
			ec.EmitNullableInitialize (temp);

			ig.MarkLabel (done);
		}
コード例 #6
0
ファイル: BinaryExpression.cs プロジェクト: jskripsky/mono
		void EmitCoalesce (EmitContext ec)
		{
			var ig = ec.ig;
			var done = ig.DefineLabel ();
			var load_right = ig.DefineLabel ();

			var left = ec.EmitStored (this.left);
			var left_is_nullable = left.LocalType.IsNullable ();

			if (left_is_nullable)
				ec.EmitNullableHasValue (left);
			else
				ec.EmitLoad (left);

			ig.Emit (OpCodes.Brfalse, load_right);

			if (left_is_nullable && !Type.IsNullable ())
				ec.EmitNullableGetValue (left);
			else
				ec.EmitLoad (left);

			ig.Emit (OpCodes.Br, done);

			ig.MarkLabel (load_right);
			ec.Emit (this.right);

			ig.MarkLabel (done);
		}
コード例 #7
0
ファイル: nullable.cs プロジェクト: samcf111/unityMono5.5.0
        //
        // Emits optimized equality or inequality operator when possible
        //
        void EmitEquality(EmitContext ec)
        {
            //
            // Either left or right is null
            //
            if (UnwrapLeft != null && Binary.Right.IsNull)               // TODO: Optimize for EmitBranchable
            //
            // left.HasValue == false
            //
            {
                UnwrapLeft.EmitCheck(ec);
                if (Binary.Oper == Binary.Operator.Equality)
                {
                    ec.EmitInt(0);
                    ec.Emit(OpCodes.Ceq);
                }
                return;
            }

            if (UnwrapRight != null && Binary.Left.IsNull)
            {
                //
                // right.HasValue == false
                //
                UnwrapRight.EmitCheck(ec);
                if (Binary.Oper == Binary.Operator.Equality)
                {
                    ec.EmitInt(0);
                    ec.Emit(OpCodes.Ceq);
                }
                return;
            }

            Label dissimilar_label = ec.DefineLabel();
            Label end_label        = ec.DefineLabel();

            if (UserOperator != null)
            {
                var left = Left;

                if (UnwrapLeft != null)
                {
                    UnwrapLeft.EmitCheck(ec);
                }
                else
                {
                    // Keep evaluation order same
                    if (!(Left is VariableReference))
                    {
                        Left.Emit(ec);
                        var lt = new LocalTemporary(Left.Type);
                        lt.Store(ec);
                        left = lt;
                    }
                }

                if (UnwrapRight != null)
                {
                    UnwrapRight.EmitCheck(ec);

                    if (UnwrapLeft != null)
                    {
                        ec.Emit(OpCodes.Bne_Un, dissimilar_label);

                        Label compare_label = ec.DefineLabel();
                        UnwrapLeft.EmitCheck(ec);
                        ec.Emit(OpCodes.Brtrue, compare_label);

                        if (Binary.Oper == Binary.Operator.Equality)
                        {
                            ec.EmitInt(1);
                        }
                        else
                        {
                            ec.EmitInt(0);
                        }

                        ec.Emit(OpCodes.Br, end_label);

                        ec.MarkLabel(compare_label);
                    }
                    else
                    {
                        ec.Emit(OpCodes.Brfalse, dissimilar_label);
                    }
                }
                else
                {
                    ec.Emit(OpCodes.Brfalse, dissimilar_label);
                }

                var args = new Arguments(2);
                args.Add(new Argument(left));
                args.Add(new Argument(Right));

                var call = new CallEmitter();
                call.EmitPredefined(ec, UserOperator, args);
            }
            else
            {
                if (ec.HasSet(BuilderContext.Options.AsyncBody) && Binary.Right.ContainsEmitWithAwait())
                {
                    Left  = Left.EmitToField(ec);
                    Right = Right.EmitToField(ec);
                }

                //
                // Emit underlying value comparison first.
                //
                // For this code: int? a = 1; bool b = a == 1;
                //
                // We emit something similar to this. Expressions with side effects have local
                // variable created by Unwrap expression
                //
                //	left.GetValueOrDefault ()
                //	right
                //	bne.un.s   dissimilar_label
                //  left.HasValue
                //	br.s       end_label
                // dissimilar_label:
                //	ldc.i4.0
                // end_label:
                //

                Left.Emit(ec);
                Right.Emit(ec);

                ec.Emit(OpCodes.Bne_Un_S, dissimilar_label);

                //
                // Check both left and right expressions for Unwrap call in which
                // case we need to run get_HasValue() check because the type is
                // nullable and could have null value
                //
                if (UnwrapLeft != null)
                {
                    UnwrapLeft.EmitCheck(ec);
                }

                if (UnwrapRight != null)
                {
                    UnwrapRight.EmitCheck(ec);
                }

                if (UnwrapLeft != null && UnwrapRight != null)
                {
                    if (Binary.Oper == Binary.Operator.Inequality)
                    {
                        ec.Emit(OpCodes.Xor);
                    }
                    else
                    {
                        ec.Emit(OpCodes.Ceq);
                    }
                }
                else
                {
                    if (Binary.Oper == Binary.Operator.Inequality)
                    {
                        ec.EmitInt(0);
                        ec.Emit(OpCodes.Ceq);
                    }
                }
            }

            ec.Emit(OpCodes.Br_S, end_label);

            ec.MarkLabel(dissimilar_label);
            if (Binary.Oper == Binary.Operator.Inequality)
            {
                ec.EmitInt(1);
            }
            else
            {
                ec.EmitInt(0);
            }

            ec.MarkLabel(end_label);
        }
コード例 #8
0
ファイル: nullable.cs プロジェクト: saga/mono
		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);
		}
コード例 #9
0
ファイル: nullable.cs プロジェクト: nuxleus/mono
 public override void EmitBranchable(EmitContext ec, Label target, bool onTrue)
 {
     Emit(ec);
     ec.Emit(onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
 }
コード例 #10
0
ファイル: nullable.cs プロジェクト: nuxleus/mono
        //
        // Emits optimized equality or inequality operator when possible
        //
        void EmitEquality(EmitContext ec)
        {
            //
            // Either left or right is null
            //
            if (left_unwrap != null && (IsRightNullLifted || right.IsNull))
            {
                left_unwrap.EmitCheck(ec);
                if (Oper == Binary.Operator.Equality)
                {
                    ec.Emit(OpCodes.Ldc_I4_0);
                    ec.Emit(OpCodes.Ceq);
                }
                return;
            }

            if (right_unwrap != null && (IsLeftNullLifted || left.IsNull))
            {
                right_unwrap.EmitCheck(ec);
                if (Oper == Binary.Operator.Equality)
                {
                    ec.Emit(OpCodes.Ldc_I4_0);
                    ec.Emit(OpCodes.Ceq);
                }
                return;
            }

            Label dissimilar_label = ec.DefineLabel();
            Label end_label        = ec.DefineLabel();

            if (user_operator != null)
            {
                user_operator.Emit(ec);
                ec.Emit(Oper == Operator.Equality ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, dissimilar_label);
            }
            else
            {
                left.Emit(ec);
                right.Emit(ec);

                ec.Emit(OpCodes.Bne_Un_S, dissimilar_label);
            }

            if (left_unwrap != null)
            {
                left_unwrap.EmitCheck(ec);
            }

            if (right_unwrap != null)
            {
                right_unwrap.EmitCheck(ec);
            }

            if (left_unwrap != null && right_unwrap != null)
            {
                if (Oper == Operator.Inequality)
                {
                    ec.Emit(OpCodes.Xor);
                }
                else
                {
                    ec.Emit(OpCodes.Ceq);
                }
            }
            else
            {
                if (Oper == Operator.Inequality)
                {
                    ec.Emit(OpCodes.Ldc_I4_0);
                    ec.Emit(OpCodes.Ceq);
                }
            }

            ec.Emit(OpCodes.Br_S, end_label);

            ec.MarkLabel(dissimilar_label);
            if (Oper == Operator.Inequality)
            {
                ec.Emit(OpCodes.Ldc_I4_1);
            }
            else
            {
                ec.Emit(OpCodes.Ldc_I4_0);
            }

            ec.MarkLabel(end_label);
        }
コード例 #11
0
ファイル: nullable.cs プロジェクト: nuxleus/mono
        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);
        }
コード例 #12
0
ファイル: nullable.cs プロジェクト: nuxleus/mono
 public override void Emit(EmitContext ec)
 {
     child.Emit(ec);
     ec.Emit(OpCodes.Newobj, NullableInfo.GetConstructor(type));
 }
コード例 #13
0
ファイル: nullable.cs プロジェクト: samcf111/unityMono5.5.0
        void EmitBitwiseBoolean(EmitContext ec)
        {
            Label load_left     = ec.DefineLabel();
            Label load_right    = ec.DefineLabel();
            Label end_label     = ec.DefineLabel();
            Label is_null_label = ec.DefineLabel();

            bool or = Binary.Oper == Binary.Operator.BitwiseOr;

            //
            // Both operands are bool? types
            //
            if ((UnwrapLeft != null && !Left.IsNull) && (UnwrapRight != null && !Right.IsNull))
            {
                if (ec.HasSet(BuilderContext.Options.AsyncBody) && Binary.Right.ContainsEmitWithAwait())
                {
                    Left  = Left.EmitToField(ec);
                    Right = Right.EmitToField(ec);
                }
                else
                {
                    UnwrapLeft.Store(ec);
                    UnwrapRight.Store(ec);
                }

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

                Right.Emit(ec);
                ec.Emit(OpCodes.Brtrue_S, load_left);

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

                // load left
                ec.MarkLabel(load_left);
                if (or)
                {
                    UnwrapRight.Load(ec);
                }
                else
                {
                    UnwrapLeft.Load(ec);
                }

                ec.Emit(OpCodes.Br_S, end_label);

                // load right
                ec.MarkLabel(load_right);
                if (or)
                {
                    UnwrapLeft.Load(ec);
                }
                else
                {
                    UnwrapRight.Load(ec);
                }

                ec.MarkLabel(end_label);
                return;
            }

            //
            // Faster version when one operand is bool
            //
            if (UnwrapLeft == null)
            {
                //
                // (bool, bool?)
                //
                // Optimizes remaining (false & bool?), (true | bool?) which are not easy to handle
                // in binary expression reduction
                //
                var c = Left as BoolConstant;
                if (c != null)
                {
                    // Keep evaluation order
                    UnwrapRight.Store(ec);

                    ec.EmitInt(or ? 1 : 0);
                    ec.Emit(OpCodes.Newobj, NullableInfo.GetConstructor(type));
                }
                else if (Left.IsNull)
                {
                    UnwrapRight.Emit(ec);
                    ec.Emit(or ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, is_null_label);

                    UnwrapRight.Load(ec);
                    ec.Emit(OpCodes.Br_S, end_label);

                    ec.MarkLabel(is_null_label);
                    LiftedNull.Create(type, loc).Emit(ec);
                }
                else
                {
                    Left.Emit(ec);
                    UnwrapRight.Store(ec);

                    ec.Emit(or ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, load_right);

                    ec.EmitInt(or ? 1 : 0);
                    ec.Emit(OpCodes.Newobj, NullableInfo.GetConstructor(type));

                    ec.Emit(OpCodes.Br_S, end_label);

                    ec.MarkLabel(load_right);
                    UnwrapRight.Load(ec);
                }
            }
            else
            {
                //
                // (bool?, bool)
                //
                // Keep left-right evaluation order
                UnwrapLeft.Store(ec);

                //
                // Optimizes remaining (bool? & false), (bool? | true) which are not easy to handle
                // in binary expression reduction
                //
                var c = Right as BoolConstant;
                if (c != null)
                {
                    ec.EmitInt(or ? 1 : 0);
                    ec.Emit(OpCodes.Newobj, NullableInfo.GetConstructor(type));
                }
                else if (Right.IsNull)
                {
                    UnwrapLeft.Emit(ec);
                    ec.Emit(or ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, is_null_label);

                    UnwrapLeft.Load(ec);
                    ec.Emit(OpCodes.Br_S, end_label);

                    ec.MarkLabel(is_null_label);
                    LiftedNull.Create(type, loc).Emit(ec);
                }
                else if (Left.IsNull && UnwrapRight != null)
                {
                    UnwrapRight.Emit(ec);

                    ec.Emit(or ? OpCodes.Brtrue_S : OpCodes.Brfalse_S, load_right);

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

                    ec.Emit(OpCodes.Br_S, end_label);

                    ec.MarkLabel(load_right);

                    UnwrapRight.Load(ec);
                }
                else
                {
                    Right.Emit(ec);
                    ec.Emit(or ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, load_left);

                    ec.EmitInt(or ? 1 : 0);
                    ec.Emit(OpCodes.Newobj, NullableInfo.GetConstructor(type));

                    ec.Emit(OpCodes.Br_S, end_label);

                    ec.MarkLabel(load_left);

                    UnwrapLeft.Load(ec);
                }
            }

            ec.MarkLabel(end_label);
        }
コード例 #14
0
ファイル: nullable.cs プロジェクト: samcf111/unityMono5.5.0
        public override void Emit(EmitContext ec)
        {
            if (IsBitwiseBoolean && UserOperator == null)
            {
                EmitBitwiseBoolean(ec);
                return;
            }

            if ((Binary.Oper & Binary.Operator.EqualityMask) != 0)
            {
                EmitEquality(ec);
                return;
            }

            Label is_null_label = ec.DefineLabel();
            Label end_label     = ec.DefineLabel();

            if (ec.HasSet(BuilderContext.Options.AsyncBody) && Right.ContainsEmitWithAwait())
            {
                Left  = Left.EmitToField(ec);
                Right = Right.EmitToField(ec);
            }

            if (UnwrapLeft != null)
            {
                UnwrapLeft.EmitCheck(ec);
            }

            //
            // Don't emit HasValue check when left and right expressions are same
            //
            if (UnwrapRight != null && !Binary.Left.Equals(Binary.Right))
            {
                UnwrapRight.EmitCheck(ec);
                if (UnwrapLeft != null)
                {
                    ec.Emit(OpCodes.And);
                }
            }

            ec.Emit(OpCodes.Brfalse, is_null_label);

            if (UserOperator != null)
            {
                var args = new Arguments(2);
                args.Add(new Argument(Left));
                args.Add(new Argument(Right));

                var call = new CallEmitter();
                call.EmitPredefined(ec, UserOperator, args);
            }
            else
            {
                Binary.EmitOperator(ec, Left, Right);
            }

            //
            // Wrap the result when the operator return type is nullable type
            //
            if (type.IsNullableType)
            {
                ec.Emit(OpCodes.Newobj, NullableInfo.GetConstructor(type));
            }

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

            if ((Binary.Oper & Binary.Operator.ComparisonMask) != 0)
            {
                ec.EmitInt(0);
            }
            else
            {
                LiftedNull.Create(type, loc).Emit(ec);
            }

            ec.MarkLabel(end_label);
        }
コード例 #15
0
ファイル: nullable.cs プロジェクト: samcf111/unityMono5.5.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);
        }
コード例 #16
0
ファイル: nullable.cs プロジェクト: saga/mono
		public override void Emit (EmitContext ec)
		{
			child.Emit (ec);
			ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type));
		}
コード例 #17
0
ファイル: nullable.cs プロジェクト: saga/mono
		public void AddressOf (EmitContext ec, AddressOp Mode)
		{
			LocalTemporary value_target = new LocalTemporary (type);
				
			value_target.AddressOf (ec, AddressOp.Store);
			ec.Emit (OpCodes.Initobj, type);
			((IMemoryLocation) value_target).AddressOf (ec, Mode);
		}
コード例 #18
0
ファイル: nullable.cs プロジェクト: nuxleus/mono
        public override void Emit(EmitContext ec)
        {
            //
            // Optimize same expression operation
            //
            if (right_unwrap != null && right.Equals(left))
            {
                right_unwrap = left_unwrap;
            }

            if (user_operator == null && IsBitwiseBoolean)
            {
                EmitBitwiseBoolean(ec);
                return;
            }

            if ((Oper & Operator.EqualityMask) != 0)
            {
                EmitEquality(ec);
                return;
            }

            Label is_null_label = ec.DefineLabel();
            Label end_label     = ec.DefineLabel();

            if (left_unwrap != null)
            {
                left_unwrap.EmitCheck(ec);
                ec.Emit(OpCodes.Brfalse, is_null_label);
            }

            //
            // Don't emit HasValue check when left and right expressions are same
            //
            if (right_unwrap != null && !left.Equals(right))
            {
                right_unwrap.EmitCheck(ec);
                ec.Emit(OpCodes.Brfalse, is_null_label);
            }

            EmitOperator(ec, left.Type);

            if (wrap_ctor != null)
            {
                ec.Emit(OpCodes.Newobj, wrap_ctor);
            }

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

            if ((Oper & Operator.ComparisonMask) != 0)
            {
                ec.Emit(OpCodes.Ldc_I4_0);
            }
            else
            {
                LiftedNull.Create(type, loc).Emit(ec);
            }

            ec.MarkLabel(end_label);
        }
コード例 #19
0
ファイル: nullable.cs プロジェクト: saga/mono
		public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
		{
			Emit (ec);
			ec.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
		}			
コード例 #20
0
 private void EmitNonLiftedBinary(EmitContext emitContext)
 {
     emitContext.Emit(_left);
     emitContext.Emit(_right);
     EmitBinaryOperator(emitContext);
 }
コード例 #21
0
ファイル: BinaryExpression.cs プロジェクト: jskripsky/mono
		void EmitUserDefinedLogicalShortCircuit (EmitContext ec)
		{
			var ig = ec.ig;
			var and = NodeType == ExpressionType.AndAlso;

			var done = ig.DefineLabel ();

			var left = ec.EmitStored (this.left);

			ec.EmitLoad (left);
			ig.Emit (OpCodes.Dup);
			ec.EmitCall (and ? GetFalseOperator () : GetTrueOperator ());
			ig.Emit (OpCodes.Brtrue, done);

			ec.Emit (this.right);
			ec.EmitCall (method);

			ig.MarkLabel (done);
		}
コード例 #22
0
ファイル: nullable.cs プロジェクト: bl8/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)
					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);
		}
コード例 #23
0
ファイル: BinaryExpression.cs プロジェクト: jskripsky/mono
		void EmitConvertedCoalesce (EmitContext ec)
		{
			var ig = ec.ig;
			var done = ig.DefineLabel ();
			var load_right = ig.DefineLabel ();

			var left = ec.EmitStored (this.left);

			if (left.LocalType.IsNullable ())
				ec.EmitNullableHasValue (left);
			else
				ec.EmitLoad (left);

			ig.Emit (OpCodes.Brfalse, load_right);

			ec.Emit (conversion);
			ec.EmitLoad (left);
			ig.Emit (OpCodes.Callvirt, conversion.Type.GetInvokeMethod ());

			ig.Emit (OpCodes.Br, done);

			ig.MarkLabel (load_right);
			ec.Emit (this.right);

			ig.MarkLabel (done);
		}
コード例 #24
0
ファイル: nullable.cs プロジェクト: Profit0004/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;
			}

			//
			// 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);
		}
コード例 #25
0
ファイル: BinaryExpression.cs プロジェクト: jskripsky/mono
		void EmitNonLiftedBinary (EmitContext ec)
		{
			ec.Emit (left);
			ec.Emit (right);
			EmitBinaryOperator (ec);
		}
コード例 #26
0
ファイル: nullable.cs プロジェクト: speier/shake
        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);
            ec.Emit (OpCodes.Brtrue, end_label);

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

            ec.MarkLabel (end_label);
        }
コード例 #27
0
ファイル: nullable.cs プロジェクト: Paccc/SharpDevelop
		public override void Emit (EmitContext ec)
		{
			if (IsBitwiseBoolean && UserOperator == null) {
				EmitBitwiseBoolean (ec);
				return;
			}

			if ((Binary.Oper & Binary.Operator.EqualityMask) != 0) {
				EmitEquality (ec);
				return;
			}

			Label is_null_label = ec.DefineLabel ();
			Label end_label = ec.DefineLabel ();

			if (ec.HasSet (BuilderContext.Options.AsyncBody) && Right.ContainsEmitWithAwait ()) {
				Left = Left.EmitToField (ec);
				Right = Right.EmitToField (ec);
			}

			if (UnwrapLeft != null) {
				UnwrapLeft.EmitCheck (ec);
			}

			//
			// Don't emit HasValue check when left and right expressions are same
			//
			if (UnwrapRight != null && !Binary.Left.Equals (Binary.Right)) {
				UnwrapRight.EmitCheck (ec);
				if (UnwrapLeft != null) {
					ec.Emit (OpCodes.And);
				}
			}

			ec.Emit (OpCodes.Brfalse, is_null_label);

			if (UserOperator != null) {
				var args = new Arguments (2);
				args.Add (new Argument (Left));
				args.Add (new Argument (Right));

				var call = new CallEmitter ();
				call.EmitPredefined (ec, UserOperator, args);
			} else {
				Binary.EmitOperator (ec, Left, Right);
			}

			//
			// Wrap the result when the operator return type is nullable type
			//
			if (type.IsNullableType)
				ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type));

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

			if ((Binary.Oper & Binary.Operator.ComparisonMask) != 0) {
				ec.EmitInt (0);
			} else {
				LiftedNull.Create (type, loc).Emit (ec);
			}

			ec.MarkLabel (end_label);
		}
コード例 #28
0
ファイル: nullable.cs プロジェクト: yayanyang/monodevelop
		//
		// Emits optimized equality or inequality operator when possible
		//
		void EmitEquality (EmitContext ec)
		{
			//
			// Either left or right is null
			//
			if (left_unwrap != null && (IsRightNullLifted || right.IsNull)) {
				left_unwrap.EmitCheck (ec);
				if (Oper == Binary.Operator.Equality) {
					ec.EmitInt (0);
					ec.Emit (OpCodes.Ceq);
				}
				return;
			}

			if (right_unwrap != null && (IsLeftNullLifted || left.IsNull)) {
				right_unwrap.EmitCheck (ec);
				if (Oper == Binary.Operator.Equality) {
					ec.EmitInt (0);
					ec.Emit (OpCodes.Ceq);
				}
				return;
			}

			Label dissimilar_label = ec.DefineLabel ();
			Label end_label = ec.DefineLabel ();

			if (user_operator != null) {
				user_operator.Emit (ec);
				ec.Emit (Oper == Operator.Equality ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, dissimilar_label);
			} else {
				if (ec.HasSet (BuilderContext.Options.AsyncBody) && right.ContainsEmitWithAwait ()) {
					left = left.EmitToField (ec);
					right = right.EmitToField (ec);
				}

				left.Emit (ec);
				right.Emit (ec);

				ec.Emit (OpCodes.Bne_Un_S, dissimilar_label);
			}

			if (left_unwrap != null)
				left_unwrap.EmitCheck (ec);

			if (right_unwrap != null)
				right_unwrap.EmitCheck (ec);

			if (left_unwrap != null && right_unwrap != null) {
				if (Oper == Operator.Inequality)
					ec.Emit (OpCodes.Xor);
				else
					ec.Emit (OpCodes.Ceq);
			} else {
				if (Oper == Operator.Inequality) {
					ec.EmitInt (0);
					ec.Emit (OpCodes.Ceq);
				}
			}

			ec.Emit (OpCodes.Br_S, end_label);

			ec.MarkLabel (dissimilar_label);
			if (Oper == Operator.Inequality)
				ec.EmitInt (1);
			else
				ec.EmitInt (0);

			ec.MarkLabel (end_label);
		}
コード例 #29
0
ファイル: nullable.cs プロジェクト: Paccc/SharpDevelop
		//
		// Emits optimized equality or inequality operator when possible
		//
		void EmitEquality (EmitContext ec)
		{
			//
			// Either left or right is null
			// 
			if (UnwrapLeft != null && Binary.Right.IsNull) { // TODO: Optimize for EmitBranchable
				//
				// left.HasValue == false 
				//
				UnwrapLeft.EmitCheck (ec);
				if (Binary.Oper == Binary.Operator.Equality) {
					ec.EmitInt (0);
					ec.Emit (OpCodes.Ceq);
				}
				return;
			}

			if (UnwrapRight != null && Binary.Left.IsNull) {
				//
				// right.HasValue == false 
				//
				UnwrapRight.EmitCheck (ec);
				if (Binary.Oper == Binary.Operator.Equality) {
					ec.EmitInt (0);
					ec.Emit (OpCodes.Ceq);
				}
				return;
			}

			Label dissimilar_label = ec.DefineLabel ();
			Label end_label = ec.DefineLabel ();

			if (UserOperator != null) {
				var left = Left;

				if (UnwrapLeft != null) {
					UnwrapLeft.EmitCheck (ec);
				} else {
					// Keep evaluation order same
					if (!(Left is VariableReference)) {
						Left.Emit (ec);
						var lt = new LocalTemporary (Left.Type);
						lt.Store (ec);
						left = lt;
					}
				}

				if (UnwrapRight != null) {
					UnwrapRight.EmitCheck (ec);

					if (UnwrapLeft != null) {
						ec.Emit (OpCodes.Bne_Un, dissimilar_label);

						Label compare_label = ec.DefineLabel ();
						UnwrapLeft.EmitCheck (ec);
						ec.Emit (OpCodes.Brtrue, compare_label);

						if (Binary.Oper == Binary.Operator.Equality)
							ec.EmitInt (1);
						else
							ec.EmitInt (0);

						ec.Emit (OpCodes.Br, end_label);

						ec.MarkLabel (compare_label);
					} else {
						ec.Emit (OpCodes.Brfalse, dissimilar_label);
					}
				} else {
					ec.Emit (OpCodes.Brfalse, dissimilar_label);
				}

				var args = new Arguments (2);
				args.Add (new Argument (left));
				args.Add (new Argument (Right));

				var call = new CallEmitter ();
				call.EmitPredefined (ec, UserOperator, args);
			} else {
				if (ec.HasSet (BuilderContext.Options.AsyncBody) && Binary.Right.ContainsEmitWithAwait ()) {
					Left = Left.EmitToField (ec);
					Right = Right.EmitToField (ec);
				}

				//
				// Emit underlying value comparison first.
				//
				// For this code: int? a = 1; bool b = a == 1;
				//
				// We emit something similar to this. Expressions with side effects have local
				// variable created by Unwrap expression
				//
				//	left.GetValueOrDefault ()
				//	right
				//	bne.un.s   dissimilar_label
				//  left.HasValue
				//	br.s       end_label
				// dissimilar_label:
				//	ldc.i4.0
				// end_label:
				//

				Left.Emit (ec);
				Right.Emit (ec);

				ec.Emit (OpCodes.Bne_Un_S, dissimilar_label);

				//
				// Check both left and right expressions for Unwrap call in which
				// case we need to run get_HasValue() check because the type is
				// nullable and could have null value
				//
				if (UnwrapLeft != null)
					UnwrapLeft.EmitCheck (ec);

				if (UnwrapRight != null)
					UnwrapRight.EmitCheck (ec);

				if (UnwrapLeft != null && UnwrapRight != null) {
					if (Binary.Oper == Binary.Operator.Inequality)
						ec.Emit (OpCodes.Xor);
					else
						ec.Emit (OpCodes.Ceq);
				} else {
					if (Binary.Oper == Binary.Operator.Inequality) {
						ec.EmitInt (0);
						ec.Emit (OpCodes.Ceq);
					}
				}
			}

			ec.Emit (OpCodes.Br_S, end_label);

			ec.MarkLabel (dissimilar_label);
			if (Binary.Oper == Binary.Operator.Inequality)
				ec.EmitInt (1);
			else
				ec.EmitInt (0);

			ec.MarkLabel (end_label);
		}
コード例 #30
0
ファイル: nullable.cs プロジェクト: MichaelWalsh/mono
		void EmitBitwiseBoolean (EmitContext ec)
		{
			Label load_left = ec.DefineLabel ();
			Label load_right = ec.DefineLabel ();
			Label end_label = ec.DefineLabel ();

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

			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 {
				right_unwrap.Load (ec);
				right_unwrap = left_unwrap;
			}
			ec.Emit (OpCodes.Br_S, end_label);

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

			ec.MarkLabel (end_label);
		}
コード例 #31
0
ファイル: nullable.cs プロジェクト: saga/mono
		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);
		}
コード例 #32
0
		void EmitConvertToNullable (EmitContext ec)
		{
			ec.Emit (operand);

			if (IsUnBoxing ()) {
				EmitUnbox (ec);
				return;
			}

			if (operand.Type != Type.GetNotNullableType ()) {
				EmitPrimitiveConversion (ec,
					operand.Type,
					Type.GetNotNullableType ());
			}

			ec.EmitNullableNew (Type);
		}
コード例 #33
0
ファイル: nullable.cs プロジェクト: saga/mono
		public override void Emit (EmitContext ec)
		{
			// TODO: generate less temporary variables
			LocalTemporary value_target = new LocalTemporary (type);

			value_target.AddressOf (ec, AddressOp.Store);
			ec.Emit (OpCodes.Initobj, type);
			value_target.Emit (ec);
		}
コード例 #34
0
		void EmitConvertFromNullable (EmitContext ec)
		{
			if (IsBoxing ()) {
				ec.Emit (operand);
				EmitBox (ec);
				return;
			}

			ec.EmitCall (operand, operand.Type.GetMethod ("get_Value"));

			if (operand.Type.GetNotNullableType () != Type) {
				EmitPrimitiveConversion (ec,
					operand.Type.GetNotNullableType (),
					Type);
			}
		}
コード例 #35
0
ファイル: nullable.cs プロジェクト: saga/mono
		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);
		}
コード例 #36
0
		void EmitUserDefinedOperator (EmitContext ec)
		{
			if (!IsLifted) {
				ec.Emit (operand);
				ec.EmitCall (method);
			} else if (IsLiftedToNull) {
				EmitUserDefinedLiftedToNullOperator (ec);
			} else
				EmitUserDefinedLiftedOperator (ec);
		}
コード例 #37
0
ファイル: nullable.cs プロジェクト: saga/mono
		//
		// Emits optimized equality or inequality operator when possible
		//
		void EmitEquality (EmitContext ec)
		{
			//
			// Either left or right is null
			//
			if (left_unwrap != null && (IsRightNullLifted || right.IsNull)) {
				left_unwrap.EmitCheck (ec);
				if (Oper == Binary.Operator.Equality) {
					ec.Emit (OpCodes.Ldc_I4_0);
					ec.Emit (OpCodes.Ceq);
				}
				return;
			}

			if (right_unwrap != null && (IsLeftNullLifted || left.IsNull)) {
				right_unwrap.EmitCheck (ec);
				if (Oper == Binary.Operator.Equality) {
					ec.Emit (OpCodes.Ldc_I4_0);
					ec.Emit (OpCodes.Ceq);
				}
				return;
			}

			Label dissimilar_label = ec.DefineLabel ();
			Label end_label = ec.DefineLabel ();

			if (user_operator != null) {
				user_operator.Emit (ec);
				ec.Emit (Oper == Operator.Equality ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, dissimilar_label);
			} else {
				left.Emit (ec);
				right.Emit (ec);

				ec.Emit (OpCodes.Bne_Un_S, dissimilar_label);
			}

			if (left_unwrap != null)
				left_unwrap.EmitCheck (ec);

			if (right_unwrap != null)
				right_unwrap.EmitCheck (ec);

			if (left_unwrap != null && right_unwrap != null) {
				if (Oper == Operator.Inequality)
					ec.Emit (OpCodes.Xor);
				else
					ec.Emit (OpCodes.Ceq);
			} else {
				if (Oper == Operator.Inequality) {
					ec.Emit (OpCodes.Ldc_I4_0);
					ec.Emit (OpCodes.Ceq);
				}
			}

			ec.Emit (OpCodes.Br_S, end_label);

			ec.MarkLabel (dissimilar_label);
			if (Oper == Operator.Inequality)
				ec.Emit (OpCodes.Ldc_I4_1);
			else
				ec.Emit (OpCodes.Ldc_I4_0);

			ec.MarkLabel (end_label);
		}
コード例 #38
0
ファイル: BinaryExpression.cs プロジェクト: jskripsky/mono
		void EmitLogicalShortCircuit (EmitContext ec)
		{
			var ig = ec.ig;
			var and = NodeType == ExpressionType.AndAlso;
			var ret = ig.DefineLabel ();
			var done = ig.DefineLabel ();

			ec.Emit (left);
			ig.Emit (and ? OpCodes.Brfalse : OpCodes.Brtrue, ret);

			ec.Emit (right);

			ig.Emit (OpCodes.Br, done);

			ig.MarkLabel (ret);
			ig.Emit (and ? OpCodes.Ldc_I4_0 : OpCodes.Ldc_I4_1);

			ig.MarkLabel (done);
		}
コード例 #39
0
ファイル: nullable.cs プロジェクト: saga/mono
		public override void Emit (EmitContext ec)
		{
			//
			// Optimize same expression operation
			//
			if (right_unwrap != null && right.Equals (left))
				right_unwrap = left_unwrap;

			if (user_operator == null && IsBitwiseBoolean) {
				EmitBitwiseBoolean (ec);
				return;
			}

			if ((Oper & Operator.EqualityMask) != 0) {
				EmitEquality (ec);
				return;
			}

			Label is_null_label = ec.DefineLabel ();
			Label end_label = ec.DefineLabel ();

			if (left_unwrap != null) {
				left_unwrap.EmitCheck (ec);
				ec.Emit (OpCodes.Brfalse, is_null_label);
			}

			//
			// Don't emit HasValue check when left and right expressions are same
			//
			if (right_unwrap != null && !left.Equals (right)) {
				right_unwrap.EmitCheck (ec);
				ec.Emit (OpCodes.Brfalse, is_null_label);
			}

			EmitOperator (ec, left.Type);

			if (wrap_ctor != null)
				ec.Emit (OpCodes.Newobj, wrap_ctor);

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

			if ((Oper & Operator.ComparisonMask) != 0) {
				ec.Emit (OpCodes.Ldc_I4_0);
			} else {
				LiftedNull.Create (type, loc).Emit (ec);
			}

			ec.MarkLabel (end_label);
		}
コード例 #40
0
        protected override void DoEmit(EmitContext ec)
        {
            var variable = ec.ResolveVariable(this, null);

            if (variable != null)
            {
                if (variable.Scope == VariableScope.Function)
                {
                    ec.Emit(OpCode.LoadConstant, Value.Pointer(variable.Address));
                }
                else
                {
                    if (variable.VariableType is CBasicType ||
                        variable.VariableType is CPointerType ||
                        variable.VariableType is CEnumType)
                    {
                        if (variable.Scope == VariableScope.Arg)
                        {
                            ec.Emit(OpCode.LoadArg, variable.Address);
                        }
                        else if (variable.Scope == VariableScope.Global)
                        {
                            ec.Emit(OpCode.LoadGlobal, variable.Address);
                        }
                        else if (variable.Scope == VariableScope.Local)
                        {
                            ec.Emit(OpCode.LoadLocal, variable.Address);
                        }
                        else if (variable.Scope == VariableScope.Constant)
                        {
                            ec.Emit(OpCode.LoadConstant, variable.Constant);
                        }
                        else
                        {
                            throw new NotSupportedException("Cannot evaluate variable scope '" + variable.Scope + "'");
                        }
                    }
                    else if (variable.VariableType is CArrayType arrayType)
                    {
                        if (variable.Scope == VariableScope.Arg)
                        {
                            ec.Emit(OpCode.LoadConstant, Value.Pointer(variable.Address));
                            ec.Emit(OpCode.LoadFramePointer);
                            ec.Emit(OpCode.OffsetPointer);
                        }
                        else if (variable.Scope == VariableScope.Global)
                        {
                            ec.Emit(OpCode.LoadConstant, Value.Pointer(variable.Address));
                        }
                        else if (variable.Scope == VariableScope.Local)
                        {
                            ec.Emit(OpCode.LoadConstant, Value.Pointer(variable.Address));
                            ec.Emit(OpCode.LoadFramePointer);
                            ec.Emit(OpCode.OffsetPointer);
                        }
                        else
                        {
                            throw new NotSupportedException("Cannot evaluate array variable scope '" + variable.Scope + "'");
                        }
                    }
                    else
                    {
                        throw new NotSupportedException("Cannot evaluate variable type '" + variable.VariableType + "'");
                    }
                }
            }
            else
            {
                ec.Emit(OpCode.LoadConstant, 0);
            }
        }