Beispiel #1
0
        public virtual void Emit(EmitContext ec)
        {
            if (!IsByRef)
            {
                if (ArgType == AType.ExtensionTypeConditionalAccess)
                {
                    var ie = new InstanceEmitter(Expr, false);
                    ie.Emit(ec, true);
                }
                else
                {
                    Expr.Emit(ec);
                }

                return;
            }

            AddressOp mode = AddressOp.Store;

            if (ArgType == AType.Ref)
            {
                mode |= AddressOp.Load;
            }

            IMemoryLocation ml = (IMemoryLocation)Expr;

            ml.AddressOf(ec, mode);
        }
Beispiel #2
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);
            }
        }
Beispiel #3
0
        public void EmitPredefined(EmitContext ec, MethodSpec method, Arguments Arguments, bool statement = false, Location?loc = null)
        {
            Expression instance_copy = null;

            if (!HasAwaitArguments && ec.HasSet(BuilderContext.Options.AsyncBody))
            {
                HasAwaitArguments = Arguments != null && Arguments.ContainsEmitWithAwait();
                if (HasAwaitArguments && InstanceExpressionOnStack)
                {
                    throw new NotSupportedException();
                }
            }

            OpCode         call_op;
            LocalTemporary lt = null;

            if (method.IsStatic)
            {
                call_op = OpCodes.Call;
            }
            else
            {
                call_op = IsVirtualCallRequired(InstanceExpression, method) ? OpCodes.Callvirt : OpCodes.Call;

                if (HasAwaitArguments)
                {
                    instance_copy = InstanceExpression.EmitToField(ec);
                    var ie = new InstanceEmitter(instance_copy, IsAddressCall(instance_copy, call_op, method.DeclaringType));

                    if (Arguments == null)
                    {
                        ie.EmitLoad(ec, true);
                    }
                }
                else if (!InstanceExpressionOnStack)
                {
                    var ie = new InstanceEmitter(InstanceExpression, IsAddressCall(InstanceExpression, call_op, method.DeclaringType));
                    ie.Emit(ec, ConditionalAccess);

                    if (DuplicateArguments)
                    {
                        ec.Emit(OpCodes.Dup);
                        if (Arguments != null && Arguments.Count != 0)
                        {
                            lt = new LocalTemporary(ie.GetStackType(ec));
                            lt.Store(ec);
                            instance_copy = lt;
                        }
                    }
                }
            }

            if (Arguments != null && !InstanceExpressionOnStack)
            {
                EmittedArguments = Arguments.Emit(ec, DuplicateArguments, HasAwaitArguments);
                if (EmittedArguments != null)
                {
                    if (instance_copy != null)
                    {
                        var ie = new InstanceEmitter(instance_copy, IsAddressCall(instance_copy, call_op, method.DeclaringType));
                        ie.Emit(ec, ConditionalAccess);

                        if (lt != null)
                        {
                            lt.Release(ec);
                        }
                    }

                    EmittedArguments.Emit(ec);
                }
            }

            if (call_op == OpCodes.Callvirt && (InstanceExpression.Type.IsGenericParameter || InstanceExpression.Type.IsStructOrEnum))
            {
                ec.Emit(OpCodes.Constrained, InstanceExpression.Type);
            }

            if (loc != null)
            {
                //
                // Emit explicit sequence point for expressions like Foo.Bar () to help debugger to
                // break at right place when LHS expression can be stepped-into
                //
                ec.MarkCallEntry(loc.Value);
            }

            //
            // Set instance expression to actual result expression. When it contains await it can be
            // picked up by caller
            //
            InstanceExpression = instance_copy;

            if (method.Parameters.HasArglist)
            {
                var varargs_types = GetVarargsTypes(method, Arguments);
                ec.Emit(call_op, method, varargs_types);
            }
            else
            {
                //
                // If you have:
                // this.DoFoo ();
                // and DoFoo is not virtual, you can omit the callvirt,
                // because you don't need the null checking behavior.
                //
                ec.Emit(call_op, method);
            }

            //
            // Pop the return value if there is one and stack should be empty
            //
            if (statement && method.ReturnType.Kind != MemberKind.Void)
            {
                ec.Emit(OpCodes.Pop);
            }
        }
Beispiel #4
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);
		}
Beispiel #5
0
		public virtual void Emit (EmitContext ec)
		{
			if (!IsByRef) {
				if (ArgType == AType.ExtensionTypeConditionalAccess) {
					var ie = new InstanceEmitter (Expr, false);
					ie.Emit (ec, true);
				} else {
					Expr.Emit (ec);
				}

				return;
			}

			AddressOp mode = AddressOp.Store;
			if (ArgType == AType.Ref)
				mode |= AddressOp.Load;

			IMemoryLocation ml = (IMemoryLocation) Expr;
			ml.AddressOf (ec, mode);
		}
Beispiel #6
0
		public void EmitPredefined (EmitContext ec, MethodSpec method, Arguments Arguments, bool statement = false, Location? loc = null)
		{
			Expression instance_copy = null;

			if (!HasAwaitArguments && ec.HasSet (BuilderContext.Options.AsyncBody)) {
				HasAwaitArguments = Arguments != null && Arguments.ContainsEmitWithAwait ();
				if (HasAwaitArguments && InstanceExpressionOnStack) {
					throw new NotSupportedException ();
				}
			}

			OpCode call_op;
			LocalTemporary lt = null;

			if (method.IsStatic) {
				call_op = OpCodes.Call;
			} else {
				call_op = IsVirtualCallRequired (InstanceExpression, method) ? OpCodes.Callvirt : OpCodes.Call;

				if (HasAwaitArguments) {
					instance_copy = InstanceExpression.EmitToField (ec);
					var ie = new InstanceEmitter (instance_copy, IsAddressCall (instance_copy, call_op, method.DeclaringType));

					if (Arguments == null) {
						ie.EmitLoad (ec, true);
					}
				} else if (!InstanceExpressionOnStack) {
					var ie = new InstanceEmitter (InstanceExpression, IsAddressCall (InstanceExpression, call_op, method.DeclaringType));
					ie.Emit (ec, ConditionalAccess);

					if (DuplicateArguments) {
						ec.Emit (OpCodes.Dup);
						if (Arguments != null && Arguments.Count != 0) {
							lt = new LocalTemporary (ie.GetStackType (ec));
							lt.Store (ec);
							instance_copy = lt;
						}
					}
				}
			}

			if (Arguments != null && !InstanceExpressionOnStack) {
				EmittedArguments = Arguments.Emit (ec, DuplicateArguments, HasAwaitArguments);
				if (EmittedArguments != null) {
					if (instance_copy != null) {
						var ie = new InstanceEmitter (instance_copy, IsAddressCall (instance_copy, call_op, method.DeclaringType));
						ie.Emit (ec, ConditionalAccess);

						if (lt != null)
							lt.Release (ec);
					}

					EmittedArguments.Emit (ec);
				}
			}

			if (call_op == OpCodes.Callvirt && (InstanceExpression.Type.IsGenericParameter || InstanceExpression.Type.IsStructOrEnum)) {
				ec.Emit (OpCodes.Constrained, InstanceExpression.Type);
			}

			if (loc != null) {
				//
				// Emit explicit sequence point for expressions like Foo.Bar () to help debugger to
				// break at right place when LHS expression can be stepped-into
				//
				ec.MarkCallEntry (loc.Value);
			}

			//
			// Set instance expression to actual result expression. When it contains await it can be
			// picked up by caller
			//
			InstanceExpression = instance_copy;

			if (method.Parameters.HasArglist) {
				var varargs_types = GetVarargsTypes (method, Arguments);
				ec.Emit (call_op, method, varargs_types);
			} else {
				//
				// If you have:
				// this.DoFoo ();
				// and DoFoo is not virtual, you can omit the callvirt,
				// because you don't need the null checking behavior.
				//
				ec.Emit (call_op, method);
			}

			// 
			// Pop the return value if there is one and stack should be empty
			//
			if (statement && method.ReturnType.Kind != MemberKind.Void)
				ec.Emit (OpCodes.Pop);
		}