context: //
  // System.Reflection.Emit.DynamicMethod.cs
  //
  // Author:
  //   Paolo Molaro (lupus@ximian.com)
  //   Zoltan Varga (vargaz@freemail.hu)
  //
  // (C) 2003 Ximian, Inc.  http://www.ximian.com
  //
  
  //
  // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  //
  // Permission is hereby granted, free of charge, to any person obtaining
  // a copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to
  // permit persons to whom the Software is furnished to do so, subject to
  // the following conditions:
  // 
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  // 
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  
  #if !FULL_AOT_RUNTIME
  
  using System;
  using System.Reflection;
  using System.Reflection.Emit;
  using System.Globalization;
  using System.Runtime.CompilerServices;
  using System.Runtime.InteropServices;
  
  namespace System.Reflection.Emit {
  
  	[ComVisible (true)]
  	[StructLayout (LayoutKind.Sequential)]
  	public sealed class DynamicMethod : MethodInfo {
  
  #pragma warning disable 169, 414, 649
  		#region Sync with reflection.h
  		private RuntimeMethodHandle mhandle;
  		private string name;
  		private Type returnType;
  		private Type[] parameters;
  		private MethodAttributes attributes;
  		private CallingConventions callingConvention;
  		private Module module;
  		private bool skipVisibility;
  		private bool init_locals = true;
  		private ILGenerator ilgen;
  		private int nrefs;
  		private object[] refs;
  		private IntPtr referenced_by;
  		private Type owner;
  		#endregion
  #pragma warning restore 169, 414, 649
  		
  		private Delegate deleg;
  		private MonoMethod method;
  		private ParameterBuilder[] pinfo;
  		internal bool creating;
  		private DynamicILInfo il_info;
  
  		public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m) : this (name, returnType, parameterTypes, m, false) {
  		}
  
  		public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner) : this (name, returnType, parameterTypes, owner, false) {
  		}
  
  		public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility) : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, m, skipVisibility) {
  		}
  
  		public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility) : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, owner, skipVisibility) {
  		}
  
  		public DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility) : this (name, attributes, callingConvention, returnType, parameterTypes, owner, owner.Module, skipVisibility, false) {
  		}
  
  		public DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility) : this (name, attributes, callingConvention, returnType, parameterTypes, null, m, skipVisibility, false) {
  		}
  
  		public DynamicMethod (string name, Type returnType, Type[] parameterTypes) : this (name, returnType, parameterTypes, false) {
  		}
  
  		[MonoTODO ("Visibility is not restricted")]
  		public DynamicMethod (string name, Type returnType, Type[] parameterTypes, bool restrictedSkipVisibility)
  			: this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, null, null, restrictedSkipVisibility, true)
  		{
  		}
  
  		DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type [] parameterTypes, Type owner, Module m, bool skipVisibility, bool anonHosted)
  		{
  			if (name == null)
  				throw new ArgumentNullException ("name");
  			if (returnType == null)
  				returnType = typeof (void);
  			if ((m == null) && !anonHosted)
  				throw new ArgumentNullException ("m");
  			if (returnType.IsByRef)
  				throw new ArgumentException ("Return type can't be a byref type", "returnType");
  			if (parameterTypes != null) {
  				for (int i = 0; i < parameterTypes.Length; ++i)
  					if (parameterTypes [i] == null)
  						throw new ArgumentException ("Parameter " + i + " is null", "parameterTypes");
  			}
  			if (owner != null && (owner.IsArray || owner.IsInterface)) {
  				throw new ArgumentException ("Owner can't be an array or an interface.");
  			}
  
  			if (m == null)
  				m = AnonHostModuleHolder.AnonHostModule;
  
  			this.name = name;
  			this.attributes = attributes | MethodAttributes.Static;
  			this.callingConvention = callingConvention;
  			this.returnType = returnType;
  			this.parameters = parameterTypes;
  			this.owner = owner;
  			this.module = m;
  			this.skipVisibility = skipVisibility;
  		}
  
  		[MethodImplAttribute(MethodImplOptions.InternalCall)]
  		private extern void create_dynamic_method (DynamicMethod m);
  
  		private void CreateDynMethod () {
  			if (mhandle.Value == IntPtr.Zero) {
  				if (ilgen == null || ilgen.ILOffset == 0)
  					throw new InvalidOperationException ("Method '" + name + "' does not have a method body.");
  
  				ilgen.label_fixup (this);
  
  				// Have to create all DynamicMethods referenced by this one
  				try {
  					// Used to avoid cycles
  					creating = true;
  					if (refs != null) {
  						for (int i = 0; i < refs.Length; ++i) {
  							if (refs [i] is DynamicMethod) {
  								DynamicMethod m = (DynamicMethod)refs [i];
  								if (!m.creating)
  									m.CreateDynMethod ();
  							}
  						}
  					}
  				} finally {
  					creating = false;
  				}
  
  				create_dynamic_method (this);
  			}
  		}
  
  		[ComVisible (true)]
  #if NET_4_5
  		sealed override
  #endif
  		public Delegate CreateDelegate (Type delegateType)
  		{
  			if (delegateType == null)
  				throw new ArgumentNullException ("delegateType");
  			if (deleg != null)
  				return deleg;
  
  			CreateDynMethod ();
  
  			deleg = Delegate.CreateDelegate (delegateType, this);
  			return deleg;
  		}
  
  		[ComVisible (true)]
  #if NET_4_5
  		sealed override
  #endif
  		public Delegate CreateDelegate (Type delegateType, object target)
  		{
  			if (delegateType == null)
  				throw new ArgumentNullException ("delegateType");
  
  			CreateDynMethod ();
  
  			/* Can't cache the delegate since it is different for each target */
  			return Delegate.CreateDelegate (delegateType, target, this);
  		}
  		
  		public ParameterBuilder DefineParameter (int position, ParameterAttributes attributes, string parameterName)
  		{
  			//
  			// Extension: Mono allows position == 0 for the return attribute
  			//
  			if ((position < 0) || (position > parameters.Length))
  				throw new ArgumentOutOfRangeException ("position");
  
  			RejectIfCreated ();
  
  			ParameterBuilder pb = new ParameterBuilder (this, position, attributes, parameterName);
  			if (pinfo == null)
  				pinfo = new ParameterBuilder [parameters.Length + 1];
  			pinfo [position] = pb;
  			return pb;
  		}
  
  		public override MethodInfo GetBaseDefinition () {
  			return this;
  		}
  
  		[MonoTODO("Not implemented")]
  		public override object[] GetCustomAttributes (bool inherit) {
  			throw new NotImplementedException ();
  		}
  
  		[MonoTODO("Not implemented")]
  		public override object[] GetCustomAttributes (Type attributeType,
  													  bool inherit) {
  			throw new NotImplementedException ();
  		}
  
  		public DynamicILInfo GetDynamicILInfo () {
  			if (il_info == null)
  				il_info = new DynamicILInfo (this);
  			return il_info;
  		}
  
  		public ILGenerator GetILGenerator () {
  			return GetILGenerator (64);
  		}
  
  		public ILGenerator GetILGenerator (int streamSize) {
  			if (((GetMethodImplementationFlags () & MethodImplAttributes.CodeTypeMask) != 
  				 MethodImplAttributes.IL) ||
  				((GetMethodImplementationFlags () & MethodImplAttributes.ManagedMask) != 
  				 MethodImplAttributes.Managed))
  				throw new InvalidOperationException ("Method body should not exist.");
  			if (ilgen != null)
  				return ilgen;
  			ilgen = new ILGenerator (Module, new DynamicMethodTokenGenerator (this), streamSize);
  			return ilgen;
  		}		
  
  		public override MethodImplAttributes GetMethodImplementationFlags () {
  			return MethodImplAttributes.IL | MethodImplAttributes.Managed;
  		}
  
  		public override ParameterInfo[] GetParameters ()
  		{
  			return GetParametersInternal ();
  		}
  
  		internal override ParameterInfo[] GetParametersInternal ()
  		{
  			if (parameters == null)
  				return EmptyArray<ParameterInfo>.Value;
  
  			ParameterInfo[] retval = new ParameterInfo [parameters.Length];
  			for (int i = 0; i < parameters.Length; i++) {
  				retval [i] = ParameterInfo.New (pinfo == null ? null : pinfo [i + 1], parameters [i], this, i + 1);
  			}
  			return retval;
  		}
  		
  		internal override int GetParametersCount ()
  		{
  			return parameters == null ? 0 : parameters.Length;
  		}		
  
  		internal override Type GetParameterType (int pos) {
  			return parameters [pos];
  		}
  
  		/*
  		public override object Invoke (object obj, object[] parameters) {
  			CreateDynMethod ();
  			if (method == null)
  				method = new MonoMethod (mhandle);
  			return method.Invoke (obj, parameters);
  		}
  		*/
  
  		public override object Invoke (object obj, BindingFlags invokeAttr,
  									   Binder binder, object[] parameters,
  									   CultureInfo culture)
  		{
  			try {
  				CreateDynMethod ();
  
gt: 				if (method == null)