Ejemplo n.º 1
0
		public void Store (EmitContext ec)
		{
			if (builder == null)
				builder = ec.GetTemporaryLocal (type);

			ec.Emit (OpCodes.Stloc, builder);
		}
Ejemplo n.º 2
0
		public void AddressOf (EmitContext ec, AddressOp mode)
		{
			if (builder == null)
				builder = ec.GetTemporaryLocal (type);

			if (builder.LocalType.IsByRef) {
				//
				// if is_address, than this is just the address anyways,
				// so we just return this.
				//
				ec.Emit (OpCodes.Ldloc, builder);
			} else {
				ec.Emit (OpCodes.Ldloca, builder);
			}
		}
Ejemplo n.º 3
0
		public override void EmitStatement (EmitContext ec)
		{
			Emit (ec);
			// 
			// Pop the return value if there is one
			//
			if (type.Kind != MemberKind.Void)
				ec.Emit (OpCodes.Pop);
		}
Ejemplo n.º 4
0
		public override void Emit (EmitContext ec)
		{
			if (builder == null)
				throw new InternalErrorException ("Emit without Store, or after Release");

			ec.Emit (OpCodes.Ldloc, builder);
		}
Ejemplo n.º 5
0
		public override void Emit (EmitContext ec)
		{
			//
			// Emits null pointer
			//
			ec.EmitInt (0);
			ec.Emit (OpCodes.Conv_U);
		}
Ejemplo n.º 6
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);
		}
Ejemplo n.º 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);
		}
Ejemplo n.º 8
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.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);
        }
Ejemplo n.º 9
0
		public override void Emit (EmitContext ec)
		{
			ec.Emit (OpCodes.Ldc_R8, Value);
		}
Ejemplo n.º 10
0
		public override void Emit (EmitContext ec)
		{
			MethodSpec m;

			int [] words = decimal.GetBits (Value);
			int power = (words [3] >> 16) & 0xff;

			if (power == 0) {
				if (Value <= int.MaxValue && Value >= int.MinValue) {
					m = ec.Module.PredefinedMembers.DecimalCtorInt.Resolve (loc);
					if (m == null) {
						return;
					}

					ec.EmitInt ((int) Value);
					ec.Emit (OpCodes.Newobj, m);
					return;
				}

				if (Value <= long.MaxValue && Value >= long.MinValue) {
					m = ec.Module.PredefinedMembers.DecimalCtorLong.Resolve (loc);
					if (m == null) {
						return;
					}

					ec.EmitLong ((long) Value);
					ec.Emit (OpCodes.Newobj, m);
					return;
				}
			}

			ec.EmitInt (words [0]);
			ec.EmitInt (words [1]);
			ec.EmitInt (words [2]);

			// sign
			ec.EmitInt (words [3] >> 31);

			// power
			ec.EmitInt (power);

			m = ec.Module.PredefinedMembers.DecimalCtor.Resolve (loc);
			if (m != null) {
				ec.Emit (OpCodes.Newobj, m);
			}
		}
Ejemplo n.º 11
0
		protected override void DoEmit (EmitContext ec)
		{
			if (statement != null) {
				statement.EmitStatement (ec);
				if (unwind_protect)
					ec.Emit (OpCodes.Leave, ec.CreateReturnLabel ());
				else {
					ec.Emit (OpCodes.Ret);
				}
				return;
			}

			base.DoEmit (ec);
		}
Ejemplo n.º 12
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.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);
		}
Ejemplo n.º 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.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);
				}

				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;
		}
Ejemplo n.º 14
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;
		}
Ejemplo n.º 15
0
		public override void Emit (EmitContext ec)
		{
			ec.EmitNull ();

			// Only to make verifier happy
			if (type.IsGenericParameter)
				ec.Emit (OpCodes.Unbox_Any, type);
		}
Ejemplo n.º 16
0
		/// <summary>
		///   C# allows this kind of scenarios:
		///   interface I { void M (); }
		///   class X { public void M (); }
		///   class Y : X, I { }
		///
		///   For that case, we create an explicit implementation function
		///   I.M in Y.
		/// </summary>
		void DefineProxy (TypeSpec iface, MethodSpec base_method, MethodSpec iface_method)
		{
			// TODO: Handle nested iface names
			string proxy_name;
			var ns = iface.MemberDefinition.Namespace;
			if (string.IsNullOrEmpty (ns))
				proxy_name = iface.MemberDefinition.Name + "." + iface_method.Name;
			else
				proxy_name = ns + "." + iface.MemberDefinition.Name + "." + iface_method.Name;

			var param = iface_method.Parameters;

			MethodBuilder proxy = container.TypeBuilder.DefineMethod (
				proxy_name,
				MethodAttributes.Private |
				MethodAttributes.HideBySig |
				MethodAttributes.NewSlot |
				MethodAttributes.CheckAccessOnOverride |
				MethodAttributes.Virtual | MethodAttributes.Final,
				CallingConventions.Standard | CallingConventions.HasThis,
				base_method.ReturnType.GetMetaInfo (), param.GetMetaInfo ());

			if (iface_method.IsGeneric) {
				var gnames = iface_method.GenericDefinition.TypeParameters.Select (l => l.Name).ToArray ();
				proxy.DefineGenericParameters (gnames);
			}

			for (int i = 0; i < param.Count; i++) {
				string name = param.FixedParameters [i].Name;
				ParameterAttributes attr = ParametersCompiled.GetParameterAttribute (param.FixedParameters [i].ModFlags);
				proxy.DefineParameter (i + 1, attr, name);
			}

			int top = param.Count;
			var ec = new EmitContext (new ProxyMethodContext (container), proxy.GetILGenerator (), null, null);
			ec.EmitThis ();
			// TODO: GetAllParametersArguments
			for (int i = 0; i < top; i++)
				ec.EmitArgumentLoad (i);

			ec.Emit (OpCodes.Call, base_method);
			ec.Emit (OpCodes.Ret);

			container.TypeBuilder.DefineMethodOverride (proxy, (MethodInfo) iface_method.GetMetaInfo ());
		}
Ejemplo n.º 17
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);
			}
		}