Store() public méthode

public Store ( EmitContext ec ) : void
ec EmitContext
Résultat void
Exemple #1
0
        //
        // if `dup_args' is true or any of arguments contains await.
        // A copy of all arguments will be returned to the caller
        //
        public virtual Arguments Emit(EmitContext ec, bool dup_args, bool prepareAwait)
        {
            List <Argument> dups;

            if ((dup_args && Count != 0) || prepareAwait)
            {
                dups = new List <Argument> (Count);
            }
            else
            {
                dups = null;
            }

            LocalTemporary lt;

            foreach (Argument a in args)
            {
                if (prepareAwait)
                {
                    dups.Add(a.EmitToField(ec, true));
                    continue;
                }

                a.Emit(ec);

                if (!dup_args)
                {
                    continue;
                }

                if (a.Expr.IsSideEffectFree)
                {
                    //
                    // No need to create a temporary variable for side effect free expressions. I assume
                    // all side-effect free expressions are cheap, this has to be tweaked when we become
                    // more aggressive on detection
                    //
                    dups.Add(a);
                }
                else
                {
                    ec.Emit(OpCodes.Dup);

                    // TODO: Release local temporary on next Emit
                    // Need to add a flag to argument to indicate this
                    lt = new LocalTemporary(a.Type);
                    lt.Store(ec);

                    dups.Add(new Argument(lt, a.ArgType));
                }
            }

            if (dups != null)
            {
                return(new Arguments(dups));
            }

            return(null);
        }
Exemple #2
0
        public void EmitAssign(EmitContext ec)
        {
            Expr.Emit(ec);
            variable = new LocalTemporary(Expr.Type);
            variable.Store(ec);

            Expr = variable;
        }
Exemple #3
0
        public void EmitAwaitOnCompletedDynamic(EmitContext ec, FieldExpr awaiter)
        {
            var critical = Module.PredefinedTypes.ICriticalNotifyCompletion;

            if (!critical.Define())
            {
                throw new NotImplementedException();
            }

            var temp_critical  = new LocalTemporary(critical.TypeSpec);
            var label_critical = ec.DefineLabel();
            var label_end      = ec.DefineLabel();

            //
            // Special path for dynamic awaiters
            //
            // var awaiter = this.$awaiter as ICriticalNotifyCompletion;
            // if (awaiter == null) {
            //    var completion = (INotifyCompletion) this.$awaiter;
            //    this.$builder.AwaitOnCompleted (ref completion, ref this);
            // } else {
            //    this.$builder.AwaitUnsafeOnCompleted (ref awaiter, ref this);
            // }
            //
            awaiter.Emit(ec);
            ec.Emit(OpCodes.Isinst, critical.TypeSpec);
            temp_critical.Store(ec);
            temp_critical.Emit(ec);
            ec.Emit(OpCodes.Brtrue_S, label_critical);

            var temp = new LocalTemporary(Module.PredefinedTypes.INotifyCompletion.TypeSpec);

            awaiter.Emit(ec);
            ec.Emit(OpCodes.Castclass, temp.Type);
            temp.Store(ec);
            EmitOnCompleted(ec, temp, false);
            temp.Release(ec);
            ec.Emit(OpCodes.Br_S, label_end);

            ec.MarkLabel(label_critical);

            EmitOnCompleted(ec, temp_critical, true);

            ec.MarkLabel(label_end);

            temp_critical.Release(ec);
        }
Exemple #4
0
        static TypeSpec EmitCallInstance(EmitContext ec, Expression instance, TypeSpec declaringType, OpCode callOpcode)
        {
            var instance_type = instance.Type;

            //
            // Push the instance expression
            //
            if ((instance_type.IsStruct && (callOpcode == OpCodes.Callvirt || (callOpcode == OpCodes.Call && declaringType.IsStruct))) ||
                instance_type.IsGenericParameter || declaringType.IsNullableType)
            {
                //
                // If the expression implements IMemoryLocation, then
                // we can optimize and use AddressOf on the
                // return.
                //
                // If not we have to use some temporary storage for
                // it.
                var iml = instance as IMemoryLocation;
                if (iml != null)
                {
                    iml.AddressOf(ec, AddressOp.Load);
                }
                else
                {
                    LocalTemporary temp = new LocalTemporary(instance_type);
                    instance.Emit(ec);
                    temp.Store(ec);
                    temp.AddressOf(ec, AddressOp.Load);
                    temp.Release(ec);
                }

                return(ReferenceContainer.MakeType(ec.Module, instance_type));
            }

            if (instance_type.IsEnum || instance_type.IsStruct)
            {
                instance.Emit(ec);
                ec.Emit(OpCodes.Box, instance_type);
                return(ec.BuiltinTypes.Object);
            }

            instance.Emit(ec);
            return(instance_type);
        }
Exemple #5
0
        public void EmitLoad(EmitContext ec)
        {
            var instance_type = instance.Type;

            //
            // Push the instance expression
            //
            if (addressRequired)
            {
                //
                // If the expression implements IMemoryLocation, then
                // we can optimize and use AddressOf on the
                // return.
                //
                // If not we have to use some temporary storage for
                // it.
                var iml = instance as IMemoryLocation;
                if (iml != null)
                {
                    iml.AddressOf(ec, AddressOp.Load);
                }
                else
                {
                    LocalTemporary temp = new LocalTemporary(instance_type);
                    instance.Emit(ec);
                    temp.Store(ec);
                    temp.AddressOf(ec, AddressOp.Load);
                }

                return;
            }

            instance.Emit(ec);

            // Only to make verifier happy
            if (instance_type.IsGenericParameter && !(instance is This) && TypeSpec.IsReferenceType(instance_type))
            {
                ec.Emit(OpCodes.Box, instance_type);
            }
            else if (instance_type.IsStructOrEnum)
            {
                ec.Emit(OpCodes.Box, instance_type);
            }
        }
Exemple #6
0
        //
        // if `dup_args' is true, a copy of the arguments will be left
        // on the stack and return value will contain an array of access
        // expressions
        // NOTE: It's caller responsibility is to release temporary variables
        //
        public virtual Expression[] Emit(EmitContext ec, bool dup_args)
        {
            Expression[] temps;

            if (dup_args && Count != 0)
            {
                temps = new Expression [Count];
            }
            else
            {
                temps = null;
            }

            int            i = 0;
            LocalTemporary lt;

            foreach (Argument a in args)
            {
                a.Emit(ec);
                if (!dup_args)
                {
                    continue;
                }

                if (a.Expr is Constant || a.Expr is This)
                {
                    //
                    // No need to create a temporary variable for constants
                    //
                    temps[i] = a.Expr;
                }
                else
                {
                    ec.Emit(OpCodes.Dup);
                    temps[i] = lt = new LocalTemporary(a.Type);
                    lt.Store(ec);
                }

                ++i;
            }

            return(temps);
        }
Exemple #7
0
        public void EmitToVariable(EmitContext ec)
        {
            var type = Expr.Type;

            if (IsByRef)
            {
                var ml = (IMemoryLocation)Expr;
                ml.AddressOf(ec, AddressOp.LoadStore);
                type = ReferenceContainer.MakeType(ec.Module, type);
            }
            else
            {
                Expr.Emit(ec);
            }

            variable = new LocalTemporary(type);
            variable.Store(ec);

            Expr = variable;
        }
Exemple #8
0
        public void EmitLoad(EmitContext ec, bool boxInstance)
        {
            var instance_type = instance.Type;

            //
            // Push the instance expression
            //
            if (addressRequired)
            {
                //
                // If the expression implements IMemoryLocation, then
                // we can optimize and use AddressOf on the
                // return.
                //
                // If not we have to use some temporary storage for
                // it.
                var iml = instance as IMemoryLocation;
                if (iml != null)
                {
                    iml.AddressOf(ec, AddressOp.Load);
                }
                else
                {
                    LocalTemporary temp = new LocalTemporary(instance_type);
                    instance.Emit(ec);
                    temp.Store(ec);
                    temp.AddressOf(ec, AddressOp.Load);
                }

                return;
            }

            instance.Emit(ec);

            // Only to make verifier happy
            if (boxInstance && RequiresBoxing())
            {
                ec.Emit(OpCodes.Box, instance_type);
            }
        }
Exemple #9
0
		public void EmitAssign (EmitContext ec)
		{
			var type = Expr.Type;
			if (IsByRef) {
				var ml = (IMemoryLocation) Expr;
				ml.AddressOf (ec, AddressOp.Load);
				type = ReferenceContainer.MakeType (type);
			} else {
				Expr.Emit (ec);
			}

			variable = new LocalTemporary (type);
			variable.Store (ec);

			Expr = variable;
		}
		protected virtual IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp mode)
		{
			LocalTemporary value_target = new LocalTemporary (type);

			if (is_type_parameter) {
				DoEmitTypeParameter (ec);
				value_target.Store (ec);
				value_target.AddressOf (ec, mode);
				return value_target;
			}

			if (!TypeManager.IsStruct (type)){
				//
				// We throw an exception.  So far, I believe we only need to support
				// value types:
				// foreach (int j in new StructType ())
				// see bug 42390
				//
				throw new Exception ("AddressOf should not be used for classes");
			}

			value_target.AddressOf (ec, AddressOp.Store);

			if (method == null) {
				ec.ig.Emit (OpCodes.Initobj, type);
			} else {
				if (Arguments != null)
					Arguments.Emit (ec);

				ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
			}
			
			value_target.AddressOf (ec, mode);
			return value_target;
		}
Exemple #11
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);
		}
Exemple #12
0
		//
		// if `dup_args' is true, a copy of the arguments will be left
		// on the stack and return value will contain an array of access
		// expressions
		// NOTE: It's caller responsibility is to release temporary variables
		//
		public virtual Expression[] Emit (EmitContext ec, bool dup_args)
		{
			Expression[] temps;

			if (dup_args && Count != 0)
				temps = new Expression [Count];
			else
				temps = null;

			int i = 0;
			LocalTemporary lt;
			foreach (Argument a in args) {
				a.Emit (ec);
				if (!dup_args)
					continue;

				if (a.Expr is Constant || a.Expr is This) {
					//
					// No need to create a temporary variable for constants
					//
					temps[i] = a.Expr;
				} else {
					ec.Emit (OpCodes.Dup);
					temps[i] = lt = new LocalTemporary (a.Type);
					lt.Store (ec);
				}

				++i;
			}

			return temps;
		}
Exemple #13
0
		static TypeSpec EmitCallInstance (EmitContext ec, Expression instance, TypeSpec declaringType, OpCode callOpcode)
		{
			var instance_type = instance.Type;

			//
			// Push the instance expression
			//
			if ((instance_type.IsStructOrEnum && (callOpcode == OpCodes.Callvirt || (callOpcode == OpCodes.Call && declaringType.IsStruct))) ||
				instance_type.IsGenericParameter || declaringType.IsNullableType) {
				//
				// If the expression implements IMemoryLocation, then
				// we can optimize and use AddressOf on the
				// return.
				//
				// If not we have to use some temporary storage for
				// it.
				var iml = instance as IMemoryLocation;
				if (iml != null) {
					iml.AddressOf (ec, AddressOp.Load);
				} else {
					LocalTemporary temp = new LocalTemporary (instance_type);
					instance.Emit (ec);
					temp.Store (ec);
					temp.AddressOf (ec, AddressOp.Load);
				}

				return ReferenceContainer.MakeType (ec.Module, instance_type);
			}

			if (instance_type.IsStructOrEnum) {
				instance.Emit (ec);
				ec.Emit (OpCodes.Box, instance_type);
				return ec.BuiltinTypes.Object;
			}

			instance.Emit (ec);
			return instance_type;
		}
Exemple #14
0
		public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
		{
			FieldAttributes fa = FieldInfo.Attributes;
			bool is_static = (fa & FieldAttributes.Static) != 0;
			bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
			ILGenerator ig = ec.ig;

			if (is_readonly && !ec.IsConstructor){
				Report_AssignToReadonly (source);
				return;
			}

			prepared = prepare_for_load;
			EmitInstance (ec, prepared);

			source.Emit (ec);
			if (leave_copy) {
				ec.ig.Emit (OpCodes.Dup);
				if (!FieldInfo.IsStatic) {
					temp = new LocalTemporary (this.Type);
					temp.Store (ec);
				}
			}

			FieldBase f = TypeManager.GetField (FieldInfo);
			if (f != null){
				if ((f.ModFlags & Modifiers.VOLATILE) != 0)
					ig.Emit (OpCodes.Volatile);
					
				f.SetAssigned ();
			}

			if (is_static)
				ig.Emit (OpCodes.Stsfld, GetConstructedFieldInfo ());
			else
				ig.Emit (OpCodes.Stfld, GetConstructedFieldInfo ());
			
			if (temp != null) {
				temp.Emit (ec);
				temp.Release (ec);
				temp = null;
			}
		}
Exemple #15
0
		//
		// Initializes all hoisted variables
		//
		public void EmitStoreyInstantiation (EmitContext ec)
		{
			// There can be only one instance variable for each storey type
			if (Instance != null)
				throw new InternalErrorException ();

			SymbolWriter.OpenCompilerGeneratedBlock (ec);

			//
			// Create an instance of a storey
			//
			var storey_type_expr = CreateStoreyTypeExpression (ec);

			ResolveContext rc = new ResolveContext (ec.MemberContext);
			Expression e = new New (storey_type_expr, null, Location).Resolve (rc);
			e.Emit (ec);

			Instance = new LocalTemporary (storey_type_expr.Type);
			Instance.Store (ec);

			EmitHoistedFieldsInitialization (ec);

			SymbolWriter.DefineScopeVariable (ID, Instance.Builder);
			SymbolWriter.CloseCompilerGeneratedBlock (ec);
		}
Exemple #16
0
		protected void EmitInstance (EmitContext ec, bool prepare_for_load)
		{
			if (IsStatic)
				return;

			if (InstanceExpression == EmptyExpression.Null) {
				SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
				return;
			}

			if (InstanceExpression.Type.IsValueType) {
				if (InstanceExpression is IMemoryLocation) {
					((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
				} else {
					LocalTemporary t = new LocalTemporary (InstanceExpression.Type);
					InstanceExpression.Emit (ec);
					t.Store (ec);
					t.AddressOf (ec, AddressOp.Store);
				}
			} else
				InstanceExpression.Emit (ec);

			if (prepare_for_load)
				ec.ig.Emit (OpCodes.Dup);
		}
Exemple #17
0
		public void Emit (EmitContext ec, bool leave_copy)
		{
			ILGenerator ig = ec.ig;
			bool is_volatile = false;

			FieldBase f = TypeManager.GetField (FieldInfo);
			if (f != null){
				if ((f.ModFlags & Modifiers.VOLATILE) != 0)
					is_volatile = true;

				f.SetMemberIsUsed ();
			}
			
			if (FieldInfo.IsStatic){
				if (is_volatile)
					ig.Emit (OpCodes.Volatile);

				ig.Emit (OpCodes.Ldsfld, GetConstructedFieldInfo ());
			} else {
				if (!prepared)
					EmitInstance (ec, false);

				IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
				if (ff != null) {
					ig.Emit (OpCodes.Ldflda, GetConstructedFieldInfo ());
					ig.Emit (OpCodes.Ldflda, ff.Element);
				} else {
					if (is_volatile)
						ig.Emit (OpCodes.Volatile);

					ig.Emit (OpCodes.Ldfld, GetConstructedFieldInfo ());
				}
			}

			if (leave_copy) {
				ec.ig.Emit (OpCodes.Dup);
				if (!FieldInfo.IsStatic) {
					temp = new LocalTemporary (this.Type);
					temp.Store (ec);
				}
			}
		}
Exemple #18
0
		public void EmitLoad (EmitContext ec)
		{
			var instance_type = instance.Type;

			//
			// Push the instance expression
			//
			if (addressRequired) {
				//
				// If the expression implements IMemoryLocation, then
				// we can optimize and use AddressOf on the
				// return.
				//
				// If not we have to use some temporary storage for
				// it.
				var iml = instance as IMemoryLocation;
				if (iml != null) {
					iml.AddressOf (ec, AddressOp.Load);
				} else {
					LocalTemporary temp = new LocalTemporary (instance_type);
					instance.Emit (ec);
					temp.Store (ec);
					temp.AddressOf (ec, AddressOp.Load);
				}

				return;
			}

			instance.Emit (ec);

			// Only to make verifier happy
			if (instance_type.IsGenericParameter && !(instance is This) && TypeSpec.IsReferenceType (instance_type)) {
				ec.Emit (OpCodes.Box, instance_type);
			} else if (instance_type.IsStructOrEnum) {
				ec.Emit (OpCodes.Box, instance_type);
			}
		}
		//
		// Initializes all hoisted variables
		//
		public void EmitStoreyInstantiation (EmitContext ec)
		{
			// There can be only one instance variable for each storey type
			if (Instance != null)
				throw new InternalErrorException ();

			SymbolWriter.OpenCompilerGeneratedBlock (ec.ig);

			//
			// Create an instance of storey type
			//
			Expression storey_type_expr;
			if (is_generic) {
				//
				// Use current method type parameter (MVAR) for top level storey only. All
				// nested storeys use class type parameter (VAR)
				//
				TypeParameter[] tparams = ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.Storey != null ?
					ec.CurrentAnonymousMethod.Storey.TypeParameters :
					ec.CurrentTypeParameters;

				TypeArguments targs = new TypeArguments ();

				if (tparams.Length < CountTypeParameters) {
					TypeParameter[] parent_tparams = ec.MemberContext.CurrentTypeDefinition.TypeParameters;
					for (int i = 0; i < parent_tparams.Length; ++i)
						targs.Add (new TypeParameterExpr (parent_tparams[i], Location));
				}
				
				for (int i = 0; i < tparams.Length; ++i)
					targs.Add (new TypeParameterExpr (tparams[i], Location));

				storey_type_expr = new GenericTypeExpr (TypeBuilder, targs, Location);
			} else {
				storey_type_expr = new TypeExpression (TypeBuilder, Location);
			}

			ResolveContext rc = new ResolveContext (this);
			Expression e = new New (storey_type_expr, null, Location).Resolve (rc);
			e.Emit (ec);

			Instance = new LocalTemporary (storey_type_expr.Type);
			Instance.Store (ec);

			EmitHoistedFieldsInitialization (ec);

			SymbolWriter.DefineScopeVariable (ID, Instance.Builder);
			SymbolWriter.CloseCompilerGeneratedBlock (ec.ig);
		}
		//
		// source is ignored, because we already have a copy of it from the
		// LValue resolution and we have already constructed a pre-cached
		// version of the arguments (ea.set_arguments);
		//
		public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
		{
			prepared = prepare_for_load;
			Expression value = set_expr;

			if (prepared) {
				Invocation.EmitCall (ec, is_base_indexer, instance_expr, get,
					arguments, loc, true, false);

				prepared_value = new LocalTemporary (type);
				prepared_value.Store (ec);
				source.Emit (ec);
				prepared_value.Release (ec);

				if (leave_copy) {
					ec.ig.Emit (OpCodes.Dup);
					temp = new LocalTemporary (Type);
					temp.Store (ec);
				}
			} else if (leave_copy) {
				temp = new LocalTemporary (Type);
				source.Emit (ec);
				temp.Store (ec);
				value = temp;
			}
			
			if (!prepared)
				arguments.Add (new Argument (value));

			Invocation.EmitCall (ec, is_base_indexer, instance_expr, set, arguments, loc, false, prepared);
			
			if (temp != null) {
				temp.Emit (ec);
				temp.Release (ec);
			}
		}
		public void Emit (EmitContext ec, bool leave_copy)
		{
			if (prepared) {
				prepared_value.Emit (ec);
			} else {
				Invocation.EmitCall (ec, is_base_indexer, instance_expr, get,
					arguments, loc, false, false);
			}

			if (leave_copy) {
				ec.ig.Emit (OpCodes.Dup);
				temp = new LocalTemporary (Type);
				temp.Store (ec);
			}
		}
		public void EmitPredefined (EmitContext ec, MethodSpec method, Arguments Arguments, 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 {
				if (IsVirtualCallRequired (InstanceExpression, method)) {
					call_op = OpCodes.Callvirt;
				} else {
					call_op = OpCodes.Call;
				}

				if (HasAwaitArguments) {
					instance_copy = InstanceExpression.EmitToField (ec);
					if (Arguments == null)
						EmitCallInstance (ec, instance_copy, method.DeclaringType, call_op);
				} else if (!InstanceExpressionOnStack) {
					var instance_on_stack_type = EmitCallInstance (ec, InstanceExpression, method.DeclaringType, call_op);

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

			if (Arguments != null && !InstanceExpressionOnStack) {
				EmittedArguments = Arguments.Emit (ec, DuplicateArguments, HasAwaitArguments);
				if (EmittedArguments != null) {
					if (instance_copy != null) {
						EmitCallInstance (ec, instance_copy, method.DeclaringType, call_op);

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

					EmittedArguments.Emit (ec);
				}
			}

			if (call_op == OpCodes.Callvirt && (InstanceExpression.Type.IsGenericParameter || InstanceExpression.Type.IsStruct)) {
				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
				//
				// TODO: The list is probably not comprehensive, need to do more testing
				//
				if (InstanceExpression is PropertyExpr || InstanceExpression is Invocation || InstanceExpression is IndexerExpr ||
					InstanceExpression is New || InstanceExpression is DelegateInvocation)
					ec.Mark (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);
				return;
			}

			//
			// 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);
		}
Exemple #23
0
		protected override void DoEmit (EmitContext ec)
		{
			if (IsGeneral)
				ec.BeginCatchBlock (TypeManager.object_type);
			else
				ec.BeginCatchBlock (CatchType);

			if (li != null) {
				li.CreateBuilder (ec);

				//
				// Special case hoisted catch variable, we have to use a temporary variable
				// to pass via anonymous storey initialization with the value still on top
				// of the stack
				//
				if (li.HoistedVariant != null) {
					LocalTemporary lt = new LocalTemporary (li.Type);
					SymbolWriter.OpenCompilerGeneratedBlock (ec);
					lt.Store (ec);
					SymbolWriter.CloseCompilerGeneratedBlock (ec);

					// switch to assigning from the temporary variable and not from top of the stack
					assign.UpdateSource (lt);
				}
			} else {
				SymbolWriter.OpenCompilerGeneratedBlock (ec);
				ec.Emit (OpCodes.Pop);
				SymbolWriter.CloseCompilerGeneratedBlock (ec);
			}

			Block.Emit (ec);
		}
Exemple #24
0
        public void Emit(EmitContext ec, bool leave_copy)
        {
            bool is_volatile = false;

            if ((spec.Modifiers & Modifiers.VOLATILE) != 0)
                is_volatile = true;

            spec.MemberDefinition.SetIsUsed ();

            if (IsStatic){
                if (is_volatile)
                    ec.Emit (OpCodes.Volatile);

                ec.Emit (OpCodes.Ldsfld, spec);
            } else {
                if (!prepared)
                    EmitInstance (ec, false);

                // Optimization for build-in types
                if (TypeManager.IsStruct (type) && TypeManager.IsEqual (type, ec.MemberContext.CurrentType) && TypeManager.IsEqual (InstanceExpression.Type, type)) {
                    ec.EmitLoadFromPtr (type);
                } else {
                    var ff = spec as FixedFieldSpec;
                    if (ff != null) {
                        ec.Emit (OpCodes.Ldflda, spec);
                        ec.Emit (OpCodes.Ldflda, ff.Element);
                    } else {
                        if (is_volatile)
                            ec.Emit (OpCodes.Volatile);

                        ec.Emit (OpCodes.Ldfld, spec);
                    }
                }
            }

            if (leave_copy) {
                ec.Emit (OpCodes.Dup);
                if (!IsStatic) {
                    temp = new LocalTemporary (this.Type);
                    temp.Store (ec);
                }
            }
        }
		public void Emit (EmitContext ec, bool leave_copy)
		{
			int rank = ea.Expr.Type.GetArrayRank ();
			ILGenerator ig = ec.ig;

			if (prepared) {
				LoadFromPtr (ig, this.type);
			} else {
				LoadArrayAndArguments (ec);
				EmitLoadOpcode (ig, type, rank);
			}	

			if (leave_copy) {
				ig.Emit (OpCodes.Dup);
				temp = new LocalTemporary (this.type);
				temp.Store (ec);
			}
		}
Exemple #26
0
        public void EmitAssign(EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
        {
            prepared = prepare_for_load;
            EmitInstance (ec, prepared);

            source.Emit (ec);
            if (leave_copy) {
                ec.Emit (OpCodes.Dup);
                if (!IsStatic) {
                    temp = new LocalTemporary (this.Type);
                    temp.Store (ec);
                }
            }

            if ((spec.Modifiers & Modifiers.VOLATILE) != 0)
                ec.Emit (OpCodes.Volatile);

            spec.MemberDefinition.SetIsAssigned ();

            if (IsStatic)
                ec.Emit (OpCodes.Stsfld, spec);
            else
                ec.Emit (OpCodes.Stfld, spec);

            if (temp != null) {
                temp.Emit (ec);
                temp.Release (ec);
                temp = null;
            }
        }
Exemple #27
0
		public void EmitPredefined (EmitContext ec, MethodSpec method, Arguments Arguments)
		{
			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 {
				if (IsVirtualCallRequired (InstanceExpression, method)) {
					call_op = OpCodes.Callvirt;
				} else {
					call_op = OpCodes.Call;
				}

				if (HasAwaitArguments) {
					instance_copy = InstanceExpression.EmitToField (ec);
					if (Arguments == null)
						EmitCallInstance (ec, instance_copy, method.DeclaringType, call_op);
				} else if (!InstanceExpressionOnStack) {
					var instance_on_stack_type = EmitCallInstance (ec, InstanceExpression, method.DeclaringType, call_op);

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

			if (Arguments != null && !InstanceExpressionOnStack) {
				EmittedArguments = Arguments.Emit (ec, DuplicateArguments, HasAwaitArguments);
				if (EmittedArguments != null) {
					if (instance_copy != null) {
						EmitCallInstance (ec, instance_copy, method.DeclaringType, call_op);

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

					EmittedArguments.Emit (ec);
				}
			}

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

			//
			// 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);
				return;
			}

			//
			// 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);
		}
Exemple #28
0
        protected void EmitInstance(EmitContext ec, bool prepare_for_load)
        {
            if (IsStatic)
                return;

            if (InstanceExpression == EmptyExpression.Null) {
                // FIXME: This should not be here at all
                SimpleName.Error_ObjectRefRequired (new ResolveContext (ec.MemberContext), loc, GetSignatureForError ());
                return;
            }

            if (TypeManager.IsValueType (InstanceExpression.Type)) {
                if (InstanceExpression is IMemoryLocation) {
                    ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
                } else {
                    LocalTemporary t = new LocalTemporary (InstanceExpression.Type);
                    InstanceExpression.Emit (ec);
                    t.Store (ec);
                    t.AddressOf (ec, AddressOp.Store);
                }
            } else
                InstanceExpression.Emit (ec);

            if (prepare_for_load)
                ec.Emit (OpCodes.Dup);
        }
Exemple #29
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;
            InstanceEmitter ie = new InstanceEmitter();

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

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

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

                    if (NullShortCircuit)
                    {
                        NullOperatorLabel = ie.NullOperatorLabel;
                    }

                    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)
                    {
                        ie = new InstanceEmitter(instance_copy, IsAddressCall(instance_copy, call_op, method.DeclaringType));
                        ie.Emit(ec);

                        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);
            }

            if (NullShortCircuit && !DuplicateArguments)
            {
                ie.EmitResultLift(ec, method.ReturnType, statement);
            }
        }
		public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
		{
			int rank = ea.Expr.Type.GetArrayRank ();
			ILGenerator ig = ec.ig;
			Type t = source.Type;
			prepared = prepare_for_load;

			if (prepared) {
				AddressOf (ec, AddressOp.LoadStore);
				ec.ig.Emit (OpCodes.Dup);
			} else {
				LoadArrayAndArguments (ec);
			}

			if (rank == 1) {
				bool is_stobj, has_type_arg;
				OpCode op = GetStoreOpcode (t, out is_stobj, out has_type_arg);

				if (!prepared) {
					//
					// The stobj opcode used by value types will need
					// an address on the stack, not really an array/array
					// pair
					//
					if (is_stobj)
						ig.Emit (OpCodes.Ldelema, t);
				}
				
				source.Emit (ec);
				if (leave_copy) {
					ec.ig.Emit (OpCodes.Dup);
					temp = new LocalTemporary (this.type);
					temp.Store (ec);
				}
				
				if (prepared)
					StoreFromPtr (ig, t);
				else if (is_stobj)
					ig.Emit (OpCodes.Stobj, t);
				else if (has_type_arg)
					ig.Emit (op, t);
				else
					ig.Emit (op);
			} else {
				source.Emit (ec);
				if (leave_copy) {
					ec.ig.Emit (OpCodes.Dup);
					temp = new LocalTemporary (this.type);
					temp.Store (ec);
				}

				if (prepared) {
					StoreFromPtr (ig, t);
				} else {
					int arg_count = ea.Arguments.Count;
					Type [] args = new Type [arg_count + 1];
					for (int i = 0; i < arg_count; i++) {
						//args [i++] = a.Type;
						args [i] = TypeManager.int32_type;
					}
					args [arg_count] = type;

					MethodInfo set = RootContext.ToplevelTypes.Builder.GetArrayMethod (
						ea.Expr.Type, "Set",
						CallingConventions.HasThis |
						CallingConventions.Standard,
						TypeManager.void_type, args);

					ig.Emit (OpCodes.Call, set);
				}
			}
			
			if (temp != null) {
				temp.Emit (ec);
				temp.Release (ec);
			}
		}
Exemple #31
0
		//
		// if `dup_args' is true or any of arguments contains await.
		// A copy of all arguments will be returned to the caller
		//
		public virtual Arguments Emit (EmitContext ec, bool dup_args, bool prepareAwait)
		{
			List<Argument> dups;

			if ((dup_args && Count != 0) || prepareAwait)
				dups = new List<Argument> (Count);
			else
				dups = null;

			LocalTemporary lt;
			foreach (Argument a in args) {
				if (prepareAwait) {
					dups.Add (a.EmitToField (ec, true));
					continue;
				}
				
				a.Emit (ec);

				if (!dup_args) {
					continue;
				}

				if (a.Expr.IsSideEffectFree) {
					//
					// No need to create a temporary variable for side effect free expressions. I assume
					// all side-effect free expressions are cheap, this has to be tweaked when we become
					// more aggressive on detection
					//
					dups.Add (a);
				} else {
					ec.Emit (OpCodes.Dup);

					// TODO: Release local temporary on next Emit
					// Need to add a flag to argument to indicate this
					lt = new LocalTemporary (a.Type);
					lt.Store (ec);

					dups.Add (new Argument (lt, a.ArgType));
				}
			}

			if (dups != null)
				return new Arguments (dups);

			return null;
		}
		public void Emit (EmitContext ec, bool leave_copy)
		{
			Emit (ec);
			if (leave_copy) {
				ec.ig.Emit (OpCodes.Dup);
				temporary = new LocalTemporary (expr.Type);
				temporary.Store (ec);
			}
		}
Exemple #33
0
		public void EmitLoad (EmitContext ec, bool boxInstance)
		{
			var instance_type = instance.Type;

			//
			// Push the instance expression
			//
			if (addressRequired) {
				//
				// If the expression implements IMemoryLocation, then
				// we can optimize and use AddressOf on the
				// return.
				//
				// If not we have to use some temporary storage for
				// it.
				var iml = instance as IMemoryLocation;
				if (iml != null) {
					iml.AddressOf (ec, AddressOp.Load);
				} else {
					LocalTemporary temp = new LocalTemporary (instance_type);
					instance.Emit (ec);
					temp.Store (ec);
					temp.AddressOf (ec, AddressOp.Load);
				}

				return;
			}

			instance.Emit (ec);

			// Only to make verifier happy
			if (boxInstance && RequiresBoxing ()) {
				ec.Emit (OpCodes.Box, instance_type);
			}
		}
Exemple #34
0
		protected override void DoEmit (EmitContext ec)
		{
			if (CatchType != null)
				ec.BeginCatchBlock (CatchType);
			else
				ec.BeginCatchBlock (TypeManager.object_type);

			if (VarBlock != null)
				VarBlock.Emit (ec);

			if (Name != null) {
				// TODO: Move to resolve
				LocalVariableReference lvr = new LocalVariableReference (Block, Name, loc);
				lvr.Resolve (new ResolveContext (ec.MemberContext));
				
				// Only to make verifier happy
				if (TypeManager.IsGenericParameter (lvr.Type))
					ec.Emit (OpCodes.Unbox_Any, lvr.Type);

				Expression source;
				if (lvr.IsHoisted) {
					LocalTemporary lt = new LocalTemporary (lvr.Type);
					lt.Store (ec);
					source = lt;
				} else {
					// Variable is at the top of the stack
					source = EmptyExpression.Null;
				}

				lvr.EmitAssign (ec, source, false, false);
			} else
				ec.Emit (OpCodes.Pop);

			Block.Emit (ec);
		}
		// `dup_args' leaves an extra copy of the arguments on the stack
		// `omit_args' does not leave any arguments at all.
		// So, basically, you could make one call with `dup_args' set to true,
		// and then another with `omit_args' set to true, and the two calls
		// would have the same set of arguments. However, each argument would
		// only have been evaluated once.
		public static void EmitCall (EmitContext ec, bool is_base,
					     Expression instance_expr,
					     MethodBase method, Arguments Arguments, Location loc,
		                             bool dup_args, bool omit_args)
		{
			ILGenerator ig = ec.ig;
			bool struct_call = false;
			bool this_call = false;
			LocalTemporary this_arg = null;

			Type decl_type = method.DeclaringType;

			if (IsMethodExcluded (method, loc))
				return;
			
			bool is_static = method.IsStatic;
			if (!is_static){
				this_call = instance_expr is This;
				if (TypeManager.IsStruct (decl_type) || TypeManager.IsEnumType (decl_type))
					struct_call = true;

				//
				// If this is ourselves, push "this"
				//
				if (!omit_args) {
					Type t = null;
					Type iexpr_type = instance_expr.Type;

					//
					// Push the instance expression
					//
					if (TypeManager.IsValueType (iexpr_type) || TypeManager.IsGenericParameter (iexpr_type)) {
						//
						// Special case: calls to a function declared in a 
						// reference-type with a value-type argument need
						// to have their value boxed.
						if (TypeManager.IsStruct (decl_type) ||
						    TypeManager.IsGenericParameter (iexpr_type)) {
							//
							// If the expression implements IMemoryLocation, then
							// we can optimize and use AddressOf on the
							// return.
							//
							// If not we have to use some temporary storage for
							// it.
							if (instance_expr is IMemoryLocation) {
								((IMemoryLocation)instance_expr).
									AddressOf (ec, AddressOp.LoadStore);
							} else {
								LocalTemporary temp = new LocalTemporary (iexpr_type);
								instance_expr.Emit (ec);
								temp.Store (ec);
								temp.AddressOf (ec, AddressOp.Load);
							}

							// avoid the overhead of doing this all the time.
							if (dup_args)
								t = TypeManager.GetReferenceType (iexpr_type);
						} else {
							instance_expr.Emit (ec);
							
							// FIXME: should use instance_expr is IMemoryLocation + constraint.
							// to help JIT to produce better code
							ig.Emit (OpCodes.Box, instance_expr.Type);
							t = TypeManager.object_type;
						}
					} else {
						instance_expr.Emit (ec);
						t = instance_expr.Type;
					}

					if (dup_args) {
						ig.Emit (OpCodes.Dup);
						if (Arguments != null && Arguments.Count != 0) {
							this_arg = new LocalTemporary (t);
							this_arg.Store (ec);
						}
					}
				}
			}

			if (!omit_args && Arguments != null)
				Arguments.Emit (ec, dup_args, this_arg);

			OpCode call_op;
			if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)) {
				call_op = OpCodes.Call;
			} else {
				call_op = OpCodes.Callvirt;
				
#if GMCS_SOURCE
				if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter))
					ig.Emit (OpCodes.Constrained, instance_expr.Type);
#endif
			}

			if ((method.CallingConvention & CallingConventions.VarArgs) != 0) {
				Type[] varargs_types = GetVarargsTypes (method, Arguments);
				ig.EmitCall (call_op, (MethodInfo) method, varargs_types);
				return;
			}

			//
			// If you have:
			// this.DoFoo ();
			// and DoFoo is not virtual, you can omit the callvirt,
			// because you don't need the null checking behavior.
			//
			if (method is MethodInfo)
				ig.Emit (call_op, (MethodInfo) method);
			else
				ig.Emit (call_op, (ConstructorInfo) method);
		}
Exemple #36
0
		protected override void DoEmit (EmitContext ec)
		{
			//
			// Needed to emit anonymous storey initialization
			// Otherwise it does not contain any statements for now
			//
			block.Emit (ec);

			default_target = ec.DefineLabel ();
			null_target = ec.DefineLabel ();

			// Store variable for comparission purposes
			// TODO: Don't duplicate non-captured VariableReference
			LocalTemporary value;
			if (HaveUnwrap) {
				value = new LocalTemporary (SwitchType);
				unwrap.EmitCheck (ec);
				ec.Emit (OpCodes.Brfalse, null_target);
				new_expr.Emit (ec);
				value.Store (ec);
			} else if (!is_constant) {
				value = new LocalTemporary (SwitchType);
				new_expr.Emit (ec);
				value.Store (ec);
			} else
				value = null;

			//
			// Setup the codegen context
			//
			Label old_end = ec.LoopEnd;
			Switch old_switch = ec.Switch;
			
			ec.LoopEnd = ec.DefineLabel ();
			ec.Switch = this;

			// Emit Code.
			if (is_constant) {
				if (constant_section != null)
					constant_section.Block.Emit (ec);
			} else if (string_dictionary != null) {
				DoEmitStringSwitch (value, ec);
			} else {
				TableSwitchEmit (ec, value);
			}

			if (value != null)
				value.Release (ec);

			// Restore context state. 
			ec.MarkLabel (ec.LoopEnd);

			//
			// Restore the previous context
			//
			ec.LoopEnd = old_end;
			ec.Switch = old_switch;
		}
Exemple #37
0
        public void Emit(EmitContext ec, bool leave_copy)
        {
            //
            // Special case: length of single dimension array property is turned into ldlen
            //
            if (IsSingleDimensionalArrayLength ()) {
                if (!prepared)
                    EmitInstance (ec, false);
                ec.Emit (OpCodes.Ldlen);
                ec.Emit (OpCodes.Conv_I4);
                return;
            }

            Invocation.EmitCall (ec, IsBase, InstanceExpression, spec.Get, null, loc, prepared, false);

            if (leave_copy) {
                ec.Emit (OpCodes.Dup);
                if (!IsStatic) {
                    temp = new LocalTemporary (this.Type);
                    temp.Store (ec);
                }
            }
        }
		public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
		{
			prepared = prepare_for_load;
			
			expr.Emit (ec);

			if (prepare_for_load)
				ec.ig.Emit (OpCodes.Dup);
			
			source.Emit (ec);
			if (leave_copy) {
				ec.ig.Emit (OpCodes.Dup);
				temporary = new LocalTemporary (expr.Type);
				temporary.Store (ec);
			}
			
			StoreFromPtr (ec.ig, type);
			
			if (temporary != null) {
				temporary.Emit (ec);
				temporary.Release (ec);
			}
		}
Exemple #39
0
        public void EmitPredefined(EmitContext ec, MethodSpec method, Arguments Arguments, 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
            {
                if (IsVirtualCallRequired(InstanceExpression, method))
                {
                    call_op = OpCodes.Callvirt;
                }
                else
                {
                    call_op = OpCodes.Call;
                }

                if (HasAwaitArguments)
                {
                    instance_copy = InstanceExpression.EmitToField(ec);
                    if (Arguments == null)
                    {
                        EmitCallInstance(ec, instance_copy, method.DeclaringType, call_op);
                    }
                }
                else if (!InstanceExpressionOnStack)
                {
                    var instance_on_stack_type = EmitCallInstance(ec, InstanceExpression, method.DeclaringType, call_op);

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

            if (Arguments != null && !InstanceExpressionOnStack)
            {
                EmittedArguments = Arguments.Emit(ec, DuplicateArguments, HasAwaitArguments);
                if (EmittedArguments != null)
                {
                    if (instance_copy != null)
                    {
                        EmitCallInstance(ec, instance_copy, method.DeclaringType, call_op);

                        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);
                return;
            }

            //
            // 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);
        }
Exemple #40
0
        //
        // Implements the IAssignMethod interface for assignments
        //
        public void EmitAssign(EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
        {
            Expression my_source = source;

            if (prepare_for_load) {
                prepared = true;
                source.Emit (ec);

                if (leave_copy) {
                    ec.Emit (OpCodes.Dup);
                    if (!IsStatic) {
                        temp = new LocalTemporary (this.Type);
                        temp.Store (ec);
                    }
                }
            } else if (leave_copy) {
                source.Emit (ec);
                temp = new LocalTemporary (this.Type);
                temp.Store (ec);
                my_source = temp;
            }

            Arguments args = new Arguments (1);
            args.Add (new Argument (my_source));

            Invocation.EmitCall (ec, IsBase, InstanceExpression, spec.Set, args, loc, false, prepared);

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