context: //
  // typemanager.cs: C# type manager
  //
  // Author: Miguel de Icaza (miguel@gnu.org)
  //         Ravi Pratap     (ravi@ximian.com)
  //         Marek Safar     (marek.safar@gmail.com)
  //
  // Dual licensed under the terms of the MIT X11 or GNU GPL
  //
  // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  // Copyright 2003-2011 Novell, Inc.
  // Copyright 2011 Xamarin Inc
  //
  
  using System;
  using System.Globalization;
  using System.Collections.Generic;
  using System.Text;
  using System.IO;
  
  namespace Mono.CSharp
  {
  	//
  	// All compiler built-in types (they have to exist otherwise the compiler will not work)
  	//
  	public class BuiltinTypes
  	{
  		public readonly BuiltinTypeSpec Object;
  		public readonly BuiltinTypeSpec ValueType;
  		public readonly BuiltinTypeSpec Attribute;
  
  		public readonly BuiltinTypeSpec Int;
  		public readonly BuiltinTypeSpec UInt;
  		public readonly BuiltinTypeSpec Long;
  		public readonly BuiltinTypeSpec ULong;
  		public readonly BuiltinTypeSpec Float;
  		public readonly BuiltinTypeSpec Double;
  		public readonly BuiltinTypeSpec Char;
  		public readonly BuiltinTypeSpec Short;
  		public readonly BuiltinTypeSpec Decimal;
  		public readonly BuiltinTypeSpec Bool;
  		public readonly BuiltinTypeSpec SByte;
  		public readonly BuiltinTypeSpec Byte;
  		public readonly BuiltinTypeSpec UShort;
  		public readonly BuiltinTypeSpec String;
  
  		public readonly BuiltinTypeSpec Enum;
  		public readonly BuiltinTypeSpec Delegate;
  		public readonly BuiltinTypeSpec MulticastDelegate;
  		public readonly BuiltinTypeSpec Void;
  		public readonly BuiltinTypeSpec Array;
  		public readonly BuiltinTypeSpec Type;
  		public readonly BuiltinTypeSpec IEnumerator;
  		public readonly BuiltinTypeSpec IEnumerable;
  		public readonly BuiltinTypeSpec IDisposable;
  		public readonly BuiltinTypeSpec IntPtr;
  		public readonly BuiltinTypeSpec UIntPtr;
  		public readonly BuiltinTypeSpec RuntimeFieldHandle;
  		public readonly BuiltinTypeSpec RuntimeTypeHandle;
  		public readonly BuiltinTypeSpec Exception;
  
  		//
  		// These are internal buil-in types which depend on other
  		// build-in type (mostly object)
  		//
  		public readonly BuiltinTypeSpec Dynamic;
  
  		// Predefined operators tables
  		public readonly Binary.PredefinedOperator[] OperatorsBinaryStandard;
  		public readonly Binary.PredefinedOperator[] OperatorsBinaryEquality;
  		public readonly Binary.PredefinedOperator[] OperatorsBinaryUnsafe;
  		public readonly TypeSpec[][] OperatorsUnary;
  		public readonly TypeSpec[] OperatorsUnaryMutator;
  
  		public readonly TypeSpec[] BinaryPromotionsTypes;
  		public readonly TypeSpec[] SwitchUserTypes;
  
  		readonly BuiltinTypeSpec[] types;
  
  		public BuiltinTypes ()
  		{
  			Object = new BuiltinTypeSpec (MemberKind.Class, "System", "Object", BuiltinTypeSpec.Type.Object);
  			ValueType = new BuiltinTypeSpec (MemberKind.Class, "System", "ValueType", BuiltinTypeSpec.Type.ValueType);
  			Attribute = new BuiltinTypeSpec (MemberKind.Class, "System", "Attribute", BuiltinTypeSpec.Type.Attribute);
  
  			Int = new BuiltinTypeSpec (MemberKind.Struct, "System", "Int32", BuiltinTypeSpec.Type.Int);
  			Long = new BuiltinTypeSpec (MemberKind.Struct, "System", "Int64", BuiltinTypeSpec.Type.Long);
  			UInt = new BuiltinTypeSpec (MemberKind.Struct, "System", "UInt32", BuiltinTypeSpec.Type.UInt);
  			ULong = new BuiltinTypeSpec (MemberKind.Struct, "System", "UInt64", BuiltinTypeSpec.Type.ULong);
  			Byte = new BuiltinTypeSpec (MemberKind.Struct, "System", "Byte", BuiltinTypeSpec.Type.Byte);
  			SByte = new BuiltinTypeSpec (MemberKind.Struct, "System", "SByte", BuiltinTypeSpec.Type.SByte);
  			Short = new BuiltinTypeSpec (MemberKind.Struct, "System", "Int16", BuiltinTypeSpec.Type.Short);
  			UShort = new BuiltinTypeSpec (MemberKind.Struct, "System", "UInt16", BuiltinTypeSpec.Type.UShort);
  
  			IEnumerator = new BuiltinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerator", BuiltinTypeSpec.Type.IEnumerator);
  			IEnumerable = new BuiltinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerable", BuiltinTypeSpec.Type.IEnumerable);
  			IDisposable = new BuiltinTypeSpec (MemberKind.Interface, "System", "IDisposable", BuiltinTypeSpec.Type.IDisposable);
  
  			Char = new BuiltinTypeSpec (MemberKind.Struct, "System", "Char", BuiltinTypeSpec.Type.Char);
  			String = new BuiltinTypeSpec (MemberKind.Class, "System", "String", BuiltinTypeSpec.Type.String);
  			Float = new BuiltinTypeSpec (MemberKind.Struct, "System", "Single", BuiltinTypeSpec.Type.Float);
  			Double = new BuiltinTypeSpec (MemberKind.Struct, "System", "Double", BuiltinTypeSpec.Type.Double);
  			Decimal = new BuiltinTypeSpec (MemberKind.Struct, "System", "Decimal", BuiltinTypeSpec.Type.Decimal);
  			Bool = new BuiltinTypeSpec (MemberKind.Struct, "System", "Boolean", BuiltinTypeSpec.Type.Bool);
  			IntPtr = new BuiltinTypeSpec (MemberKind.Struct, "System", "IntPtr", BuiltinTypeSpec.Type.IntPtr);
  			UIntPtr = new BuiltinTypeSpec (MemberKind.Struct, "System", "UIntPtr", BuiltinTypeSpec.Type.UIntPtr);
  
  			MulticastDelegate = new BuiltinTypeSpec (MemberKind.Class, "System", "MulticastDelegate", BuiltinTypeSpec.Type.MulticastDelegate);
  			Delegate = new BuiltinTypeSpec (MemberKind.Class, "System", "Delegate", BuiltinTypeSpec.Type.Delegate);
  			Enum = new BuiltinTypeSpec (MemberKind.Class, "System", "Enum", BuiltinTypeSpec.Type.Enum);
  			Array = new BuiltinTypeSpec (MemberKind.Class, "System", "Array", BuiltinTypeSpec.Type.Array);
  			Void = new BuiltinTypeSpec (MemberKind.Void, "System", "Void", BuiltinTypeSpec.Type.Other);
  			Type = new BuiltinTypeSpec (MemberKind.Class, "System", "Type", BuiltinTypeSpec.Type.Type);
  			Exception = new BuiltinTypeSpec (MemberKind.Class, "System", "Exception", BuiltinTypeSpec.Type.Exception);
  			RuntimeFieldHandle = new BuiltinTypeSpec (MemberKind.Struct, "System", "RuntimeFieldHandle", BuiltinTypeSpec.Type.Other);
  			RuntimeTypeHandle = new BuiltinTypeSpec (MemberKind.Struct, "System", "RuntimeTypeHandle", BuiltinTypeSpec.Type.Other);
  
  			// TODO: Maybe I should promote it to different kind for faster compares
  			Dynamic = new BuiltinTypeSpec ("dynamic", BuiltinTypeSpec.Type.Dynamic);
  
  			OperatorsBinaryStandard = Binary.CreateStandardOperatorsTable (this);
  			OperatorsBinaryEquality = Binary.CreateEqualityOperatorsTable (this);
  			OperatorsBinaryUnsafe = Binary.CreatePointerOperatorsTable (this);
  			OperatorsUnary = Unary.CreatePredefinedOperatorsTable (this);
  			OperatorsUnaryMutator = UnaryMutator.CreatePredefinedOperatorsTable (this);
  
  			BinaryPromotionsTypes = ConstantFold.CreateBinaryPromotionsTypes (this);
  			SwitchUserTypes = Switch.CreateSwitchUserTypes (this);
  
  			types = new BuiltinTypeSpec[] {
  				Object, ValueType, Attribute,
  				Int, UInt, Long, ULong, Float, Double, Char, Short, Decimal, Bool, SByte, Byte, UShort, String,
  				Enum, Delegate, MulticastDelegate, Void, Array, Type, IEnumerator, IEnumerable, IDisposable,
  				IntPtr, UIntPtr, RuntimeFieldHandle, RuntimeTypeHandle, Exception };
  		}
  
  		public BuiltinTypeSpec[] AllTypes {
  			get {
  				return types;
  			}
  		}
  
  		public bool CheckDefinitions (ModuleContainer module)
  		{
  			var ctx = module.Compiler;
  			foreach (var p in types) {
  				var found = PredefinedType.Resolve (module, p.Kind, p.Namespace, p.Name, p.Arity);
  				if (found == null || found == p)
  					continue;
  
  				var tc = found.MemberDefinition as TypeDefinition;
  				if (tc != null) {
  					var ns = module.GlobalRootNamespace.GetNamespace (p.Namespace, false);
  					ns.SetBuiltinType (p);
  
  					tc.SetPredefinedSpec (p);
  					p.SetDefinition (found);
  				}
  			}
  
  			if (ctx.Report.Errors != 0)
  				return false;
  
  			// Set internal build-in types
  			Dynamic.SetDefinition (Object);
  
  			return true;
  		}
  	}
  
  	//
  	// Compiler predefined types. Usually used for compiler generated
  	// code or for comparison against well known framework type. They
  	// may not exist as they are optional
  	//
  	class PredefinedTypes
  	{
  		public readonly PredefinedType ArgIterator;
  		public readonly PredefinedType TypedReference;
  		public readonly PredefinedType MarshalByRefObject;
  		public readonly PredefinedType RuntimeHelpers;
  		public readonly PredefinedType IAsyncResult;
  		public readonly PredefinedType AsyncCallback;
  		public readonly PredefinedType RuntimeArgumentHandle;
  		public readonly PredefinedType CharSet;
  		public readonly PredefinedType IsVolatile;
  		public readonly PredefinedType IEnumeratorGeneric;
  		public readonly PredefinedType IListGeneric;
  		public readonly PredefinedType ICollectionGeneric;
  		public readonly PredefinedType IEnumerableGeneric;
  		public readonly PredefinedType Nullable;
  		public readonly PredefinedType Activator;
  		public readonly PredefinedType Interlocked;
  		public readonly PredefinedType Monitor;
  		public readonly PredefinedType NotSupportedException;
  		public readonly PredefinedType RuntimeFieldHandle;
  		public readonly PredefinedType RuntimeMethodHandle;
  		public readonly PredefinedType SecurityAction;
  		public readonly PredefinedType Dictionary;
  		public readonly PredefinedType Hashtable;
  
  		//
  		// C# 3.0
  		//
  		public readonly PredefinedType Expression;
  		public readonly PredefinedType ExpressionGeneric;
  		public readonly PredefinedType ParameterExpression;
  		public readonly PredefinedType FieldInfo;
  		public readonly PredefinedType MethodBase;
  		public readonly PredefinedType MethodInfo;
  		public readonly PredefinedType ConstructorInfo;
  		public readonly PredefinedType MemberBinding;
  
  		//
  		// C# 4.0
  		//
  		public readonly PredefinedType Binder;
  		public readonly PredefinedType CallSite;
  		public readonly PredefinedType CallSiteGeneric;
  		public readonly PredefinedType BinderFlags;
  
  		//
  		// C# 5.0
  		//
  		public readonly PredefinedType AsyncVoidMethodBuilder;
  		public readonly PredefinedType AsyncTaskMethodBuilder;
  		public readonly PredefinedType AsyncTaskMethodBuilderGeneric;
  		public readonly PredefinedType Action;
  		public readonly PredefinedType Task;
  		public readonly PredefinedType TaskGeneric;
  
  		public PredefinedTypes (ModuleContainer module)
  		{
  			TypedReference = new PredefinedType (module, MemberKind.Struct, "System", "TypedReference");
  			ArgIterator = new PredefinedType (module, MemberKind.Struct, "System", "ArgIterator");
  
  			MarshalByRefObject = new PredefinedType (module, MemberKind.Class, "System", "MarshalByRefObject");
  			RuntimeHelpers = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "RuntimeHelpers");
  			IAsyncResult = new PredefinedType (module, MemberKind.Interface, "System", "IAsyncResult");
  			AsyncCallback = new PredefinedType (module, MemberKind.Delegate, "System", "AsyncCallback");
  			RuntimeArgumentHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeArgumentHandle");
  			CharSet = new PredefinedType (module, MemberKind.Enum, "System.Runtime.InteropServices", "CharSet");
  			IsVolatile = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "IsVolatile");
  			IEnumeratorGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerator", 1);
  			IListGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IList", 1);
  			ICollectionGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "ICollection", 1);
  			IEnumerableGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerable", 1);
  			Nullable = new PredefinedType (module, MemberKind.Struct, "System", "Nullable", 1);
  			Activator = new PredefinedType (module, MemberKind.Class, "System", "Activator");
  			Interlocked = new PredefinedType (module, MemberKind.Class, "System.Threading", "Interlocked");
  			Monitor = new PredefinedType (module, MemberKind.Class, "System.Threading", "Monitor");
  			NotSupportedException = new PredefinedType (module, MemberKind.Class, "System", "NotSupportedException");
  			RuntimeFieldHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeFieldHandle");
  			RuntimeMethodHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeMethodHandle");
  			SecurityAction = new PredefinedType (module, MemberKind.Enum, "System.Security.Permissions", "SecurityAction");
  			Dictionary = new PredefinedType (module, MemberKind.Class, "System.Collections.Generic", "Dictionary", 2);
  			Hashtable = new PredefinedType (module, MemberKind.Class, "System.Collections", "Hashtable");
  
  			Expression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression");
  			ExpressionGeneric = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression", 1);
  			MemberBinding = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "MemberBinding");
  			ParameterExpression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "ParameterExpression");
  			FieldInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "FieldInfo");
  			MethodBase = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodBase");
  			MethodInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodInfo");
  			ConstructorInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "ConstructorInfo");
  
  			CallSite = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite");
  			CallSiteGeneric = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite", 1);
  			Binder = new PredefinedType (module, MemberKind.Class, "Microsoft.CSharp.RuntimeBinder", "Binder");
  			BinderFlags = new PredefinedType (module, MemberKind.Enum, "Microsoft.CSharp.RuntimeBinder", "CSharpBinderFlags");
  
  			Action = new PredefinedType (module, MemberKind.Delegate, "System", "Action");
  			AsyncVoidMethodBuilder = new PredefinedType (module, MemberKind.Struct, "System.Runtime.CompilerServices", "AsyncVoidMethodBuilder");
  			AsyncTaskMethodBuilder = new PredefinedType (module, MemberKind.Struct, "System.Runtime.CompilerServices", "AsyncTaskMethodBuilder");
  			AsyncTaskMethodBuilderGeneric = new PredefinedType (module, MemberKind.Struct, "System.Runtime.CompilerServices", "AsyncTaskMethodBuilder", 1);
  			Task = new PredefinedType (module, MemberKind.Class, "System.Threading.Tasks", "Task");
  			TaskGeneric = new PredefinedType (module, MemberKind.Class, "System.Threading.Tasks", "Task", 1);
  
  			//
  			// Define types which are used for comparison. It does not matter
  			// if they don't exist as no error report is needed
  			//
  			if (TypedReference.Define ())
  				TypedReference.TypeSpec.IsSpecialRuntimeType = true;
  
  			if (ArgIterator.Define ())
  				ArgIterator.TypeSpec.IsSpecialRuntimeType = true;
  
  			if (IEnumerableGeneric.Define ())
  				IEnumerableGeneric.TypeSpec.IsGenericIterateInterface = true;
  
  			if (IListGeneric.Define ())
  				IListGeneric.TypeSpec.IsGenericIterateInterface = true;
  
  			if (ICollectionGeneric.Define ())
  				ICollectionGeneric.TypeSpec.IsGenericIterateInterface = true;
  
  			if (Nullable.Define ())
  				Nullable.TypeSpec.IsNullableType = true;
  
  			if (ExpressionGeneric.Define ())
  				ExpressionGeneric.TypeSpec.IsExpressionTreeType = true;
  
  			Task.Define ();
  			if (TaskGeneric.Define ())
  				TaskGeneric.TypeSpec.IsGenericTask = true;
  		}
  	}
  
  	class PredefinedMembers
  	{
  		public readonly PredefinedMember<MethodSpec> ActivatorCreateInstance;
  		public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderCreate;
  		public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderSetResult;
  		public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderSetException;
  		public readonly PredefinedMember<PropertySpec> AsyncTaskMethodBuilderTask;
  		public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderGenericCreate;
  		public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderGenericSetResult;
  		public readonly PredefinedMember<MethodSpec> AsyncTaskMethodBuilderGenericSetException;
  		public readonly PredefinedMember<PropertySpec> AsyncTaskMethodBuilderGenericTask;
  		public readonly PredefinedMember<MethodSpec> AsyncVoidMethodBuilderCreate;
  		public readonly PredefinedMember<MethodSpec> AsyncVoidMethodBuilderSetException;
  		public readonly PredefinedMember<MethodSpec> AsyncVoidMethodBuilderSetResult;
  		public readonly PredefinedMember<MethodSpec> DebuggerBrowsableAttributeCtor;
  		public readonly PredefinedMember<MethodSpec> DecimalCtor;
  		public readonly PredefinedMember<MethodSpec> DecimalCtorInt;
  		public readonly PredefinedMember<MethodSpec> DecimalCtorLong;
  		public readonly PredefinedMember<MethodSpec> DecimalConstantAttributeCtor;
  		public readonly PredefinedMember<MethodSpec> DefaultMemberAttributeCtor;
  		public readonly PredefinedMember<MethodSpec> DelegateCombine;
  		public readonly PredefinedMember<MethodSpec> DelegateEqual;
  		public readonly PredefinedMember<MethodSpec> DelegateInequal;
  		public readonly PredefinedMember<MethodSpec> DelegateRemove;
  		public readonly PredefinedMember<MethodSpec> DynamicAttributeCtor;
  		public readonly PredefinedMember<MethodSpec> FieldInfoGetFieldFromHandle;
  		public readonly PredefinedMember<MethodSpec> FieldInfoGetFieldFromHandle2;
  		public readonly PredefinedMember<MethodSpec> IDisposableDispose;
  		public readonly PredefinedMember<MethodSpec> IEnumerableGetEnumerator;
  		public readonly PredefinedMember<MethodSpec> InterlockedCompareExchange;
  		public readonly PredefinedMember<MethodSpec> InterlockedCompareExchange_T;
  		public readonly PredefinedMember<MethodSpec> FixedBufferAttributeCtor;
  		public readonly PredefinedMember<MethodSpec> MethodInfoGetMethodFromHandle;
  		public readonly PredefinedMember<MethodSpec> MethodInfoGetMethodFromHandle2;
  		public readonly PredefinedMember<MethodSpec> MonitorEnter;
  		public readonly PredefinedMember<MethodSpec> MonitorEnter_v4;
  		public readonly PredefinedMember<MethodSpec> MonitorExit;
  		public readonly PredefinedMember<PropertySpec> RuntimeCompatibilityWrapNonExceptionThrows;
  		public readonly PredefinedMember<MethodSpec> RuntimeHelpersInitializeArray;
  		public readonly PredefinedMember<PropertySpec> RuntimeHelpersOffsetToStringData;
  		public readonly PredefinedMember<ConstSpec> SecurityActionRequestMinimum;
  		public readonly PredefinedMember<FieldSpec> StringEmpty;
  		public readonly PredefinedMember<MethodSpec> StringEqual;
  		public readonly PredefinedMember<MethodSpec> StringInequal;
  		public readonly PredefinedMember<MethodSpec> StructLayoutAttributeCtor;
  		public readonly PredefinedMember<FieldSpec> StructLayoutCharSet;
  		public readonly PredefinedMember<FieldSpec> StructLayoutSize;
  		public readonly PredefinedMember<MethodSpec> TypeGetTypeFromHandle;
  
  		public PredefinedMembers (ModuleContainer module)
  		{
  			var types = module.PredefinedTypes;
  			var atypes = module.PredefinedAttributes;
  			var btypes = module.Compiler.BuiltinTypes;
  
  			ActivatorCreateInstance = new PredefinedMember<MethodSpec> (module, types.Activator,
  				MemberFilter.Method ("CreateInstance", 1, ParametersCompiled.EmptyReadOnlyParameters, null));
  
  			AsyncTaskMethodBuilderCreate = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilder,
  				MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncTaskMethodBuilder.TypeSpec));
  
  			AsyncTaskMethodBuilderSetResult = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilder,
  				MemberFilter.Method ("SetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, btypes.Void));
  
  			AsyncTaskMethodBuilderSetException = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilder,
  				MemberFilter.Method ("SetException", 0,
  				ParametersCompiled.CreateFullyResolved (btypes.Exception), btypes.Void));
  
  			AsyncTaskMethodBuilderTask = new PredefinedMember<PropertySpec> (module, types.AsyncTaskMethodBuilder,
  				MemberFilter.Property ("Task", null));
  
  			AsyncTaskMethodBuilderGenericCreate = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric,
  				MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncVoidMethodBuilder.TypeSpec));
  
  			AsyncTaskMethodBuilderGenericSetResult = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric,
  				"SetResult", MemberKind.Method, () => new TypeSpec[] {
  						types.AsyncTaskMethodBuilderGeneric.TypeSpec.MemberDefinition.TypeParameters[0]
  				});
  
  			AsyncTaskMethodBuilderGenericSetException = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric,
  				MemberFilter.Method ("SetException", 0,
  				ParametersCompiled.CreateFullyResolved (btypes.Exception), btypes.Void));
  
  			AsyncTaskMethodBuilderGenericTask = new PredefinedMember<PropertySpec> (module, types.AsyncTaskMethodBuilderGeneric,
  				MemberFilter.Property ("Task", null));
  
  			AsyncVoidMethodBuilderCreate = new PredefinedMember<MethodSpec> (module, types.AsyncVoidMethodBuilder,
  				MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncVoidMethodBuilder.TypeSpec));
  
  			AsyncVoidMethodBuilderSetException = new PredefinedMember<MethodSpec> (module, types.AsyncVoidMethodBuilder,
  				MemberFilter.Method ("SetException", 0, null, btypes.Void));
  
  			AsyncVoidMethodBuilderSetResult = new PredefinedMember<MethodSpec> (module, types.AsyncVoidMethodBuilder,
  				MemberFilter.Method ("SetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, btypes.Void));
  
  			DebuggerBrowsableAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.DebuggerBrowsable,
  				MemberFilter.Constructor (null));
  
  			DecimalCtor = new PredefinedMember<MethodSpec> (module, btypes.Decimal,
  				MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (
  					btypes.Int, btypes.Int, btypes.Int, btypes.Bool, btypes.Byte)));
  
  			DecimalCtorInt = new PredefinedMember<MethodSpec> (module, btypes.Decimal,
  				MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Int)));
  
  			DecimalCtorLong = new PredefinedMember<MethodSpec> (module, btypes.Decimal,
  				MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Long)));
  
  			DecimalConstantAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.DecimalConstant,
  				MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (
  					btypes.Byte, btypes.Byte, btypes.UInt, btypes.UInt, btypes.UInt)));
  
  			DefaultMemberAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.DefaultMember,
  				MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.String)));
  
  			DelegateCombine = new PredefinedMember<MethodSpec> (module, btypes.Delegate, "Combine", btypes.Delegate, btypes.Delegate);
  			DelegateRemove = new PredefinedMember<MethodSpec> (module, btypes.Delegate, "Remove", btypes.Delegate, btypes.Delegate);
  
  			DelegateEqual = new PredefinedMember<MethodSpec> (module, btypes.Delegate,
  				new MemberFilter (Operator.GetMetadataName (Operator.OpType.Equality), 0, MemberKind.Operator, null, btypes.Bool));
  
  			DelegateInequal = new PredefinedMember<MethodSpec> (module, btypes.Delegate,
  				new MemberFilter (Operator.GetMetadataName (Operator.OpType.Inequality), 0, MemberKind.Operator, null, btypes.Bool));
  
  			DynamicAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.Dynamic,
  				MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (
  					ArrayContainer.MakeType (module, btypes.Bool))));
  
  			FieldInfoGetFieldFromHandle = new PredefinedMember<MethodSpec> (module, types.FieldInfo,
  				"GetFieldFromHandle", MemberKind.Method, types.RuntimeFieldHandle);
  
  			FieldInfoGetFieldFromHandle2 = new PredefinedMember<MethodSpec> (module, types.FieldInfo,
  				"GetFieldFromHandle", MemberKind.Method, types.RuntimeFieldHandle, new PredefinedType (btypes.RuntimeTypeHandle));
  
  			FixedBufferAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.FixedBuffer,
  				MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Type, btypes.Int)));
  
  			IDisposableDispose = new PredefinedMember<MethodSpec> (module, btypes.IDisposable, "Dispose", TypeSpec.EmptyTypes);
  
  			IEnumerableGetEnumerator = new PredefinedMember<MethodSpec> (module, btypes.IEnumerable,
  				"GetEnumerator", TypeSpec.EmptyTypes);
  
  			InterlockedCompareExchange = new PredefinedMember<MethodSpec> (module, types.Interlocked,
  				MemberFilter.Method ("CompareExchange", 0,
  					new ParametersImported (
  						new[] {
  								new ParameterData (null, Parameter.Modifier.REF),
  								new ParameterData (null, Parameter.Modifier.NONE),
  								new ParameterData (null, Parameter.Modifier.NONE)
  							},
  						new[] {
  								btypes.Int, btypes.Int, btypes.Int
  							},
  						false),
  				btypes.Int));
  
  			InterlockedCompareExchange_T = new PredefinedMember<MethodSpec> (module, types.Interlocked,
  				MemberFilter.Method ("CompareExchange", 1,
  					new ParametersImported (
  						new[] {
  								new ParameterData (null, Parameter.Modifier.REF),
  								new ParameterData (null, Parameter.Modifier.NONE),
  								new ParameterData (null, Parameter.Modifier.NONE)
  							},
  						new[] {
  								new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null),
  								new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null),
  								new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null),
  							}, false),
  					null));
  
  			MethodInfoGetMethodFromHandle = new PredefinedMember<MethodSpec> (module, types.MethodBase,
  				"GetMethodFromHandle", MemberKind.Method, types.RuntimeMethodHandle);
  
  			MethodInfoGetMethodFromHandle2 = new PredefinedMember<MethodSpec> (module, types.MethodBase,
  				"GetMethodFromHandle", MemberKind.Method, types.RuntimeMethodHandle, new PredefinedType (btypes.RuntimeTypeHandle));
  
  			MonitorEnter = new PredefinedMember<MethodSpec> (module, types.Monitor, "Enter", btypes.Object);
  
  			MonitorEnter_v4 = new PredefinedMember<MethodSpec> (module, types.Monitor,
  				MemberFilter.Method ("Enter", 0,
  					new ParametersImported (new[] {
  							new ParameterData (null, Parameter.Modifier.NONE),
  							new ParameterData (null, Parameter.Modifier.REF)
  						},
  					new[] {
  							btypes.Object, btypes.Bool
  						}, false), null));
  
  			MonitorExit = new PredefinedMember<MethodSpec> (module, types.Monitor, "Exit", btypes.Object);
  
  			RuntimeCompatibilityWrapNonExceptionThrows = new PredefinedMember<PropertySpec> (module, atypes.RuntimeCompatibility,
  				MemberFilter.Property ("WrapNonExceptionThrows", btypes.Bool));
  
  			RuntimeHelpersInitializeArray = new PredefinedMember<MethodSpec> (module, types.RuntimeHelpers,
  				"InitializeArray", btypes.Array, btypes.RuntimeFieldHandle);
  
  			RuntimeHelpersOffsetToStringData = new PredefinedMember<PropertySpec> (module, types.RuntimeHelpers,
  				MemberFilter.Property ("OffsetToStringData", btypes.Int));
  
  			SecurityActionRequestMinimum = new PredefinedMember<ConstSpec> (module, types.SecurityAction, "RequestMinimum",
  				MemberKind.Field, types.SecurityAction);
  
  			StringEmpty = new PredefinedMember<FieldSpec> (module, btypes.String, MemberFilter.Field ("Empty", btypes.String));
  
  			StringEqual = new PredefinedMember<MethodSpec> (module, btypes.String,
  				new MemberFilter (Operator.GetMetadataName (Operator.OpType.Equality), 0, MemberKind.Operator, null, btypes.Bool));
  
  			StringInequal = new PredefinedMember<MethodSpec> (module, btypes.String,
  				new MemberFilter (Operator.GetMetadataName (Operator.OpType.Inequality), 0, MemberKind.Operator, null, btypes.Bool));
  
  			StructLayoutAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.StructLayout,
  				MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Short)));
  
  			StructLayoutCharSet = new PredefinedMember<FieldSpec> (module, atypes.StructLayout, "CharSet",
  				MemberKind.Field, types.CharSet);
  
  			StructLayoutSize = new PredefinedMember<FieldSpec> (module, atypes.StructLayout,
  				MemberFilter.Field ("Size", btypes.Int));
  
  			TypeGetTypeFromHandle = new PredefinedMember<MethodSpec> (module, btypes.Type, "GetTypeFromHandle", btypes.RuntimeTypeHandle);
  		}
  	}
  
  	public class PredefinedType
  	{
  		readonly string name;
  		readonly string ns;
  		readonly int arity;
  		readonly MemberKind kind;
  		protected readonly ModuleContainer module;
  		protected TypeSpec type;
  
  		public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name, int arity)
  			: this (module, kind, ns, name)
  		{
  			this.arity = arity;
  		}
  
  		public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name)
  		{
  			this.module = module;
  			this.kind = kind;
  			this.name = name;
  			this.ns = ns;
  		}
  
  		public PredefinedType (BuiltinTypeSpec type)
  		{
  			this.kind = type.Kind;
  			this.name = type.Name;
  			this.ns = type.Namespace;
  			this.type = type;
  		}
  
  		#region Properties
  
  		public int Arity {
  			get {
  				return arity;
  			}
  		}
  
  		public bool IsDefined {
  			get {
  				return type != null;
  			}
  		}
  
  		public string Name {
  			get {
  				return name;
  			}
  		}
  
  		public string Namespace {
  			get {
  				return ns;
  			}
  		}
  
  		public TypeSpec TypeSpec {
  			get {
  				return type;
  			}
  		}
  
  		#endregion
  
  		public bool Define ()
  		{
  			if (type != null)
  				return true;
  
  			type = Resolve (module, kind, ns, name, arity, false);
  			return type != null;
  		}
  
  		public string GetSignatureForError ()
  		{
  			return ns + "." + name;
  		}
  
  		public static TypeSpec Resolve (ModuleContainer module, MemberKind kind, string ns, string name, int arity)
  		{
  			return Resolve (module, kind, ns, name, arity, true);
  		}
  
  		public static TypeSpec Resolve (ModuleContainer module, MemberKind kind, string ns, string name, int arity, bool reportErrors)
  		{
  			Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true);
  			var found = type_ns.GetAllTypes (name);
  			if (found == null) {
  				if (reportErrors)
  					module.Compiler.Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported", ns, name);
  
  				return null;
  			}
  
  			TypeSpec best_match = null;
  			foreach (var candidate in found) {
  				if (candidate.Kind != kind) {
  					if (candidate.Kind == MemberKind.Struct && kind == MemberKind.Void && candidate.MemberDefinition is TypeContainer) {
  						// Void is declared as struct but we keep it internally as
  						// special kind, the swap will be done by caller
  					} else {
  						continue;
  					}
  				}
  
  				if (candidate.Arity != arity)
  					continue;
  
  				if ((candidate.Modifiers & Modifiers.INTERNAL) != 0 && !candidate.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly))
  					continue;
  
  				if (best_match == null) {
  					best_match = candidate;
  					continue;
  				}
  
  				var other_match = best_match;
  				if (!best_match.MemberDefinition.IsImported &&
  					module.Compiler.BuiltinTypes.Object.MemberDefinition.DeclaringAssembly == candidate.MemberDefinition.DeclaringAssembly) {
  					best_match = candidate;
  				}
  
  				string location;
  				if (best_match.MemberDefinition is MemberCore) {
  					location = ((MemberCore) best_match.MemberDefinition).Location.Name;
  				} else {
  					var assembly = (ImportedAssemblyDefinition) best_match.MemberDefinition.DeclaringAssembly;
  					location = Path.GetFileName (assembly.Location);
  				}
  
  				module.Compiler.Report.SymbolRelatedToPreviousError (other_match);
  				module.Compiler.Report.SymbolRelatedToPreviousError (candidate);
  
  				module.Compiler.Report.Warning (1685, 1,
  					"The predefined type `{0}.{1}' is defined multiple times. Using definition from `{2}'",
  					ns, name, location);
  
  				break;
  			}
  
  			if (best_match == null && reportErrors) {
  				Location loc;
  				if (found[0].MemberDefinition is MemberCore) {
  					loc = ((MemberCore) found[0].MemberDefinition).Location;
  				} else {
  					loc = Location.Null;
  					module.Compiler.Report.SymbolRelatedToPreviousError (found[0]);
  				}
  
  				module.Compiler.Report.Error (520, loc, "The predefined type `{0}.{1}' is not declared correctly", ns, name);
  			}
  
  			return best_match;
  		}
  
  		public TypeSpec Resolve ()
  		{
  
gt: 			if (type == null)