Пример #1
0
        public override void Emit(EmitContext ec)
        {
            if (method_group.InstanceExpression == null)
            {
                ec.EmitNull();
            }
            else
            {
                var ie = new InstanceEmitter(method_group.InstanceExpression, false);
                ie.Emit(ec, method_group.ConditionalAccess);
            }

            var delegate_method = method_group.BestCandidate;

            // Any delegate must be sealed
            if (!delegate_method.DeclaringType.IsDelegate && delegate_method.IsVirtual && !method_group.IsBase)
            {
                ec.Emit(OpCodes.Dup);
                ec.Emit(OpCodes.Ldvirtftn, delegate_method);
            }
            else
            {
                ec.Emit(OpCodes.Ldftn, delegate_method);
            }

            ec.Emit(OpCodes.Newobj, constructor_method);
        }
Пример #2
0
        protected void EmitConditionalAccess(EmitContext ec)
        {
            var a_expr = arguments [0].Expr;

            var des = a_expr as DynamicExpressionStatement;

            if (des != null)
            {
                des.EmitConditionalAccess(ec);
            }

            if (HasConditionalAccess())
            {
                var NullOperatorLabel = ec.DefineLabel();

                if (ExpressionAnalyzer.IsInexpensiveLoad(a_expr))
                {
                    a_expr.Emit(ec);
                }
                else
                {
                    var lt = new LocalTemporary(a_expr.Type);
                    lt.EmitAssign(ec, a_expr, true, false);

                    Arguments [0].Expr = lt;
                }

                ec.Emit(OpCodes.Brtrue_S, NullOperatorLabel);

                if (!ec.ConditionalAccess.Statement)
                {
                    if (ec.ConditionalAccess.Type.IsNullableType)
                    {
                        Nullable.LiftedNull.Create(ec.ConditionalAccess.Type, Location.Null).Emit(ec);
                    }
                    else
                    {
                        ec.EmitNull();
                    }
                }

                ec.Emit(OpCodes.Br, ec.ConditionalAccess.EndLabel);
                ec.MarkLabel(NullOperatorLabel);

                return;
            }

            if (a_expr.HasConditionalAccess())
            {
                var lt = new LocalTemporary(a_expr.Type);
                lt.EmitAssign(ec, a_expr, false, false);

                Arguments [0].Expr = lt;
            }
        }
Пример #3
0
        public void EmitResultLift(EmitContext ec, TypeSpec type, bool statement)
        {
            if (!NullShortCircuit)
            {
                throw new InternalErrorException();
            }

            bool     value_rt = TypeSpec.IsValueType(type);
            TypeSpec lifted;

            if (value_rt)
            {
                if (type.IsNullableType)
                {
                    lifted = type;
                }
                else
                {
                    lifted = Nullable.NullableInfo.MakeType(ec.Module, type);
                    ec.Emit(OpCodes.Newobj, Nullable.NullableInfo.GetConstructor(lifted));
                }
            }
            else
            {
                lifted = null;
            }

            var end = ec.DefineLabel();

            if (value_on_stack || !statement)
            {
                ec.Emit(OpCodes.Br_S, end);
            }

            ec.MarkLabel(NullOperatorLabel);

            if (value_on_stack)
            {
                ec.Emit(OpCodes.Pop);
            }

            if (!statement)
            {
                if (value_rt)
                {
                    Nullable.LiftedNull.Create(lifted, Location.Null).Emit(ec);
                }
                else
                {
                    ec.EmitNull();
                }
            }

            ec.MarkLabel(end);
        }
Пример #4
0
        public override void Emit(EmitContext ec)
        {
            InstanceEmitter ie;

            if (method_group.InstanceExpression == null)
            {
                ie = new InstanceEmitter();
                ec.EmitNull();
            }
            else
            {
                ie = new InstanceEmitter(method_group.InstanceExpression, false);
                ie.NullShortCircuit = method_group.NullShortCircuit;
                ie.Emit(ec);
            }

            var delegate_method = method_group.BestCandidate;

            // Any delegate must be sealed
            if (!delegate_method.DeclaringType.IsDelegate && delegate_method.IsVirtual && !method_group.IsBase)
            {
                ec.Emit(OpCodes.Dup);
                ec.Emit(OpCodes.Ldvirtftn, delegate_method);
            }
            else
            {
                ec.Emit(OpCodes.Ldftn, delegate_method);
            }

            ec.Emit(OpCodes.Newobj, constructor_method);

            if (method_group.NullShortCircuit)
            {
                ie.EmitResultLift(ec, type, false);
            }
        }
Пример #5
0
		public override void Emit (EmitContext ec)
		{
			//
			// Use same anonymous method implementation for scenarios where same
			// code is used from multiple blocks, e.g. field initializers
			//
			if (method == null) {
				//
				// Delay an anonymous method definition to avoid emitting unused code
				// for unreachable blocks or expression trees
				//
				method = DoCreateMethodHost (ec);
				method.Define ();
			}

			bool is_static = (method.ModFlags & Modifiers.STATIC) != 0;
			if (is_static && am_cache == null) {
				//
				// Creates a field cache to store delegate instance if it's not generic
				//
				if (!method.MemberName.IsGeneric) {
					var parent = method.Parent.PartialContainer;
					int id = parent.AnonymousMethodsCounter++;
					var cache_type = storey != null && storey.Mutator != null ? storey.Mutator.Mutate (type) : type;

					am_cache = new Field (parent, new TypeExpression (cache_type, loc),
						Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
						new MemberName (CompilerGeneratedContainer.MakeName (null, "f", "am$cache", id), loc), null);
					am_cache.Define ();
					parent.AddField (am_cache);
				} else {
					// TODO: Implement caching of generated generic static methods
					//
					// Idea:
					//
					// Some extra class is needed to capture variable generic type
					// arguments. Maybe we could re-use anonymous types, with a unique
					// anonymous method id, but they are quite heavy.
					//
					// Consider : "() => typeof(T);"
					//
					// We need something like
					// static class Wrap<Tn, Tm, DelegateType> {
					//		public static DelegateType cache;
					// }
					//
					// We then specialize local variable to capture all generic parameters
					// and delegate type, e.g. "Wrap<Ta, Tb, DelegateTypeInst> cache;"
					//
				}
			}

			Label l_initialized = ec.DefineLabel ();

			if (am_cache != null) {
				ec.Emit (OpCodes.Ldsfld, am_cache.Spec);
				ec.Emit (OpCodes.Brtrue_S, l_initialized);
			}

			//
			// Load method delegate implementation
			//

			if (is_static) {
				ec.EmitNull ();
			} else if (storey != null) {
				Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext));
				if (e != null) {
					e.Emit (ec);
				}
			} else {
				ec.EmitThis ();

				//
				// Special case for value type storey where this is not lifted but
				// droped off to parent class
				//
				for (var b = Block.Parent; b != null; b = b.Parent) {
					if (b.ParametersBlock.StateMachine != null) {
						ec.Emit (OpCodes.Ldfld, b.ParametersBlock.StateMachine.HoistedThis.Field.Spec);
						break;
					}
				}
			}

			var delegate_method = method.Spec;
			if (storey != null && storey.MemberName.IsGeneric) {
				TypeSpec t = storey.Instance.Type;

				//
				// Mutate anonymous method instance type if we are in nested
				// hoisted generic anonymous method storey
				//
				if (ec.IsAnonymousStoreyMutateRequired) {
					t = storey.Mutator.Mutate (t);
				}

				ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ()));
			} else {
				if (delegate_method.IsGeneric)
					delegate_method = delegate_method.MakeGenericMethod (ec.MemberContext, method.TypeParameters);

				ec.Emit (OpCodes.Ldftn, delegate_method);
			}

			var constructor_method = Delegate.GetConstructor (type);
			ec.Emit (OpCodes.Newobj, constructor_method);

			if (am_cache != null) {
				ec.Emit (OpCodes.Stsfld, am_cache.Spec);
				ec.MarkLabel (l_initialized);
				ec.Emit (OpCodes.Ldsfld, am_cache.Spec);
			}
		}
Пример #6
0
		public override void Emit (EmitContext ec)
		{
			ec.EmitNull ();

			// Only to make verifier happy
			if (type.IsGenericParameter)
				ec.Emit (OpCodes.Unbox_Any, type);
		}
Пример #7
0
		public override void Emit (EmitContext ec)
		{
			if (Value == null) {
				ec.EmitNull ();
				return;
			}

			//
			// Use string.Empty for both literals and constants even if
			// it's not allowed at language level
			//
			if (Value.Length == 0 && ec.Module.Compiler.Settings.Optimize) {
				var string_type = ec.BuiltinTypes.String;
				if (ec.CurrentType != string_type) {
					var m = ec.Module.PredefinedMembers.StringEmpty.Get ();
					if (m != null) {
						ec.Emit (OpCodes.Ldsfld, m);
						return;
					}
				}
			}

			ec.Emit (OpCodes.Ldstr, Value);
		}
Пример #8
0
        public void Emit(EmitContext ec, bool conditionalAccess)
        {
            Label NullOperatorLabel;

            Nullable.Unwrap unwrap;

            if (conditionalAccess && Expression.IsNeverNull(instance))
            {
                conditionalAccess = false;
            }

            if (conditionalAccess)
            {
                NullOperatorLabel = ec.DefineLabel();
                unwrap            = instance as Nullable.Unwrap;
            }
            else
            {
                NullOperatorLabel = new Label();
                unwrap            = null;
            }

            IMemoryLocation instance_address       = null;
            bool            conditional_access_dup = false;

            if (unwrap != null)
            {
                unwrap.Store(ec);
                unwrap.EmitCheck(ec);
                ec.Emit(OpCodes.Brtrue_S, NullOperatorLabel);
            }
            else
            {
                if (conditionalAccess && addressRequired)
                {
                    //
                    // Don't allocate temp variable when instance load is cheap and load and load-address
                    // operate on same memory
                    //
                    instance_address = instance as VariableReference;
                    if (instance_address == null)
                    {
                        instance_address = instance as LocalTemporary;
                    }

                    if (instance_address == null)
                    {
                        EmitLoad(ec, false);
                        ec.Emit(OpCodes.Dup);
                        ec.EmitLoadFromPtr(instance.Type);

                        conditional_access_dup = true;
                    }
                    else
                    {
                        instance.Emit(ec);
                    }
                }
                else
                {
                    EmitLoad(ec, !conditionalAccess);

                    if (conditionalAccess)
                    {
                        conditional_access_dup = !IsInexpensiveLoad();
                        if (conditional_access_dup)
                        {
                            ec.Emit(OpCodes.Dup);
                        }
                    }
                }

                if (conditionalAccess)
                {
                    if (instance.Type.Kind == MemberKind.TypeParameter)
                    {
                        ec.Emit(OpCodes.Box, instance.Type);
                    }

                    ec.Emit(OpCodes.Brtrue_S, NullOperatorLabel);

                    if (conditional_access_dup)
                    {
                        ec.Emit(OpCodes.Pop);
                    }
                }
            }

            if (conditionalAccess)
            {
                if (!ec.ConditionalAccess.Statement)
                {
                    if (ec.ConditionalAccess.Type.IsNullableType)
                    {
                        Nullable.LiftedNull.Create(ec.ConditionalAccess.Type, Location.Null).Emit(ec);
                    }
                    else
                    {
                        ec.EmitNull();
                    }
                }

                ec.Emit(OpCodes.Br, ec.ConditionalAccess.EndLabel);
                ec.MarkLabel(NullOperatorLabel);

                if (instance_address != null)
                {
                    instance_address.AddressOf(ec, AddressOp.Load);
                }
                else if (unwrap != null)
                {
                    unwrap.Emit(ec);
                    var tmp = ec.GetTemporaryLocal(unwrap.Type);
                    ec.Emit(OpCodes.Stloc, tmp);
                    ec.Emit(OpCodes.Ldloca, tmp);
                    ec.FreeTemporaryLocal(tmp, unwrap.Type);
                }
                else if (!conditional_access_dup)
                {
                    instance.Emit(ec);
                }
            }
        }
Пример #9
0
		public void Emit (EmitContext ec, bool conditionalAccess)
		{
			Label NullOperatorLabel;
			Nullable.Unwrap unwrap;

			if (conditionalAccess && Expression.IsNeverNull (instance))
				conditionalAccess = false;

			if (conditionalAccess) {
				NullOperatorLabel = ec.DefineLabel ();
				unwrap = instance as Nullable.Unwrap;
			} else {
				NullOperatorLabel = new Label ();
				unwrap = null;
			}

			IMemoryLocation instance_address = null;
			bool conditional_access_dup = false;

			if (unwrap != null) {
				unwrap.Store (ec);
				unwrap.EmitCheck (ec);
				ec.Emit (OpCodes.Brtrue_S, NullOperatorLabel);
			} else {
				if (conditionalAccess && addressRequired) {
					//
					// Don't allocate temp variable when instance load is cheap and load and load-address
					// operate on same memory
					//
					instance_address = instance as VariableReference;
					if (instance_address == null)
						instance_address = instance as LocalTemporary;

					if (instance_address == null) {
						EmitLoad (ec, false);
						ec.Emit (OpCodes.Dup);
						ec.EmitLoadFromPtr (instance.Type);

						conditional_access_dup = true;
					} else {
						instance.Emit (ec);
					}
				} else {
					EmitLoad (ec, !conditionalAccess);

					if (conditionalAccess) {
						conditional_access_dup = !IsInexpensiveLoad ();
						if (conditional_access_dup)
							ec.Emit (OpCodes.Dup);
					}
				}

				if (conditionalAccess) {
					if (instance.Type.Kind == MemberKind.TypeParameter)
						ec.Emit (OpCodes.Box, instance.Type);

					ec.Emit (OpCodes.Brtrue_S, NullOperatorLabel);

					if (conditional_access_dup)
						ec.Emit (OpCodes.Pop);
				}
			}

			if (conditionalAccess) {
				if (!ec.ConditionalAccess.Statement) {
					if (ec.ConditionalAccess.Type.IsNullableType)
						Nullable.LiftedNull.Create (ec.ConditionalAccess.Type, Location.Null).Emit (ec);
					else
						ec.EmitNull ();
				}

				ec.Emit (OpCodes.Br, ec.ConditionalAccess.EndLabel);
				ec.MarkLabel (NullOperatorLabel);

				if (instance_address != null) {
					instance_address.AddressOf (ec, AddressOp.Load);
				} else if (unwrap != null) {
					unwrap.Emit (ec);
					var tmp = ec.GetTemporaryLocal (unwrap.Type);
					ec.Emit (OpCodes.Stloc, tmp);
					ec.Emit (OpCodes.Ldloca, tmp);
					ec.FreeTemporaryLocal (tmp, unwrap.Type);
				} else if (!conditional_access_dup) {
					instance.Emit (ec);
				}
			}
		}
Пример #10
0
		public override void Emit (EmitContext ec)
		{
			if (conditional_access_receiver)
				ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ());

			if (method_group.InstanceExpression == null) {
				ec.EmitNull ();
			} else {
				var ie = new InstanceEmitter (method_group.InstanceExpression, false);
				ie.Emit (ec, method_group.ConditionalAccess);
			}

			var delegate_method = method_group.BestCandidate;

			// Any delegate must be sealed
			if (!delegate_method.DeclaringType.IsDelegate && delegate_method.IsVirtual && !method_group.IsBase) {
				ec.Emit (OpCodes.Dup);
				ec.Emit (OpCodes.Ldvirtftn, delegate_method);
			} else {
				ec.Emit (OpCodes.Ldftn, delegate_method);
			}

			ec.Emit (OpCodes.Newobj, constructor_method);

			if (conditional_access_receiver)
				ec.CloseConditionalAccess (null);
		}
Пример #11
0
		protected void EmitConditionalAccess (EmitContext ec)
		{
			var a_expr = arguments [0].Expr;

			var des = a_expr as DynamicExpressionStatement;
			if (des != null) {
				des.EmitConditionalAccess (ec);
			}

			if (HasConditionalAccess ()) {
				var NullOperatorLabel = ec.DefineLabel ();

				if (ExpressionAnalyzer.IsInexpensiveLoad (a_expr)) {
					a_expr.Emit (ec);
				} else {
					var lt = new LocalTemporary (a_expr.Type);
					lt.EmitAssign (ec, a_expr, true, false);

					Arguments [0].Expr = lt;
				}

				ec.Emit (OpCodes.Brtrue_S, NullOperatorLabel);

				if (!ec.ConditionalAccess.Statement) {
					if (ec.ConditionalAccess.Type.IsNullableType)
						Nullable.LiftedNull.Create (ec.ConditionalAccess.Type, Location.Null).Emit (ec);
					else
						ec.EmitNull ();
				}

				ec.Emit (OpCodes.Br, ec.ConditionalAccess.EndLabel);
				ec.MarkLabel (NullOperatorLabel);

				return;
			}

			if (a_expr.HasConditionalAccess ()) {
				var lt = new LocalTemporary (a_expr.Type);
				lt.EmitAssign (ec, a_expr, false, false);

				Arguments [0].Expr = lt;
			}
		}
Пример #12
0
		public override void Emit (EmitContext ec)
		{
			if (method_group.InstanceExpression == null)
				ec.EmitNull ();
			else
				method_group.InstanceExpression.Emit (ec);

			var delegate_method = method_group.BestCandidate;

			// Any delegate must be sealed
			if (!delegate_method.DeclaringType.IsDelegate && delegate_method.IsVirtual && !method_group.IsBase) {
				ec.Emit (OpCodes.Dup);
				ec.Emit (OpCodes.Ldvirtftn, delegate_method);
			} else {
				ec.Emit (OpCodes.Ldftn, delegate_method);
			}

			ec.Emit (OpCodes.Newobj, constructor_method);
		}
Пример #13
0
		public void EmitResultLift (EmitContext ec, TypeSpec type, bool statement)
		{
			if (!NullShortCircuit)
				throw new InternalErrorException ();

			bool value_rt = TypeSpec.IsValueType (type);
			TypeSpec lifted;
			if (value_rt) {
				if (type.IsNullableType)
					lifted = type;
				else {
					lifted = Nullable.NullableInfo.MakeType (ec.Module, type);
					ec.Emit (OpCodes.Newobj, Nullable.NullableInfo.GetConstructor (lifted));
				}
			} else {
				lifted = null;
			}

			var end = ec.DefineLabel ();
			if (value_on_stack || !statement) {
				ec.Emit (OpCodes.Br_S, end);
			}

			ec.MarkLabel (NullOperatorLabel);

			if (value_on_stack)
				ec.Emit (OpCodes.Pop);

			if (!statement) {
				if (value_rt)
					Nullable.LiftedNull.Create (lifted, Location.Null).Emit (ec);
				else
					ec.EmitNull ();
			}

			ec.MarkLabel (end);
		}
Пример #14
0
        public void Emit(EmitContext ec, bool conditionalAccess)
        {
            Label NullOperatorLabel;

            Nullable.Unwrap unwrap;

            if (conditionalAccess && Expression.IsNeverNull(instance))
            {
                conditionalAccess = false;
            }

            if (conditionalAccess)
            {
                NullOperatorLabel = ec.DefineLabel();
                unwrap            = instance as Nullable.Unwrap;
            }
            else
            {
                NullOperatorLabel = new Label();
                unwrap            = null;
            }

            if (unwrap != null)
            {
                unwrap.Store(ec);
                unwrap.EmitCheck(ec);
                ec.Emit(OpCodes.Brtrue_S, NullOperatorLabel);
            }
            else
            {
                EmitLoad(ec);

                if (conditionalAccess)
                {
                    ec.Emit(OpCodes.Dup);
                    ec.Emit(OpCodes.Brtrue_S, NullOperatorLabel);
                    ec.Emit(OpCodes.Pop);
                }
            }

            if (conditionalAccess)
            {
                if (!ec.ConditionalAccess.Statement)
                {
                    if (ec.ConditionalAccess.Type.IsNullableType)
                    {
                        Nullable.LiftedNull.Create(ec.ConditionalAccess.Type, Location.Null).Emit(ec);
                    }
                    else
                    {
                        ec.EmitNull();
                    }
                }

                ec.Emit(OpCodes.Br, ec.ConditionalAccess.EndLabel);
                ec.MarkLabel(NullOperatorLabel);

                if (unwrap != null)
                {
                    unwrap.Emit(ec);
                    var tmp = ec.GetTemporaryLocal(unwrap.Type);
                    ec.Emit(OpCodes.Stloc, tmp);
                    ec.Emit(OpCodes.Ldloca, tmp);
                    ec.FreeTemporaryLocal(tmp, unwrap.Type);
                }
            }
        }
Пример #15
0
		public override void Emit (EmitContext ec)
		{
			InstanceEmitter ie;
			if (method_group.InstanceExpression == null) {
				ie = new InstanceEmitter ();
				ec.EmitNull ();
			} else {
				ie = new InstanceEmitter (method_group.InstanceExpression, false);
				ie.NullShortCircuit = method_group.NullShortCircuit;
				ie.Emit (ec);
			}

			var delegate_method = method_group.BestCandidate;

			// Any delegate must be sealed
			if (!delegate_method.DeclaringType.IsDelegate && delegate_method.IsVirtual && !method_group.IsBase) {
				ec.Emit (OpCodes.Dup);
				ec.Emit (OpCodes.Ldvirtftn, delegate_method);
			} else {
				ec.Emit (OpCodes.Ldftn, delegate_method);
			}

			ec.Emit (OpCodes.Newobj, constructor_method);

			if (method_group.NullShortCircuit) {
				ie.EmitResultLift (ec, type, false);
			}
		}