renamed
[mono.git] / mcs / gmcs / typemanager.cs
1 //
2 // typemanager.cs: C# type manager
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //         Ravi Pratap     (ravi@ximian.com)
6 //
7 // Licensed under the terms of the GNU GPL
8 //
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
10 //
11 //
12
13 //
14 // We will eventually remove the SIMPLE_SPEEDUP, and should never change 
15 // the behavior of the compilation.  This can be removed if we rework
16 // the code to get a list of namespaces available.
17 //
18 #define SIMPLE_SPEEDUP
19
20 using System;
21 using System.IO;
22 using System.Globalization;
23 using System.Collections;
24 using System.Reflection;
25 using System.Reflection.Emit;
26 using System.Text;
27 using System.Text.RegularExpressions;
28 using System.Runtime.CompilerServices;
29 using System.Diagnostics;
30
31 namespace Mono.CSharp {
32
33 public class TypeManager {
34         //
35         // A list of core types that the compiler requires or uses
36         //
37         static public Type object_type;
38         static public Type value_type;
39         static public Type string_type;
40         static public Type int32_type;
41         static public Type uint32_type;
42         static public Type int64_type;
43         static public Type uint64_type;
44         static public Type float_type;
45         static public Type double_type;
46         static public Type char_type;
47         static public Type char_ptr_type;
48         static public Type short_type;
49         static public Type decimal_type;
50         static public Type bool_type;
51         static public Type sbyte_type;
52         static public Type byte_type;
53         static public Type ushort_type;
54         static public Type enum_type;
55         static public Type delegate_type;
56         static public Type multicast_delegate_type;
57         static public Type void_type;
58         static public Type null_type;
59         static public Type enumeration_type;
60         static public Type array_type;
61         static public Type runtime_handle_type;
62         static public Type icloneable_type;
63         static public Type type_type;
64         static public Type ienumerator_type;
65         static public Type ienumerable_type;
66         static public Type idisposable_type;
67         static public Type iconvertible_type;
68         static public Type default_member_type;
69         static public Type iasyncresult_type;
70         static public Type asynccallback_type;
71         static public Type intptr_type;
72         static public Type monitor_type;
73         static public Type runtime_field_handle_type;
74         static public Type runtime_argument_handle_type;
75         static public Type attribute_type;
76         static public Type attribute_usage_type;
77         static public Type dllimport_type;
78         static public Type unverifiable_code_type;
79         static public Type methodimpl_attr_type;
80         static public Type marshal_as_attr_type;
81         static public Type new_constraint_attr_type;
82         static public Type param_array_type;
83         static public Type guid_attr_type;
84         static public Type void_ptr_type;
85         static public Type indexer_name_type;
86         static public Type exception_type;
87         static public Type activator_type;
88         static public Type invalid_operation_exception_type;
89         static public Type not_supported_exception_type;
90         static public Type obsolete_attribute_type;
91         static public Type conditional_attribute_type;
92         static public Type in_attribute_type;
93         static public Type anonymous_method_type;
94         static public Type cls_compliant_attribute_type;
95         static public Type typed_reference_type;
96         static public Type arg_iterator_type;
97         static public Type mbr_type;
98         static public Type struct_layout_attribute_type;
99         static public Type field_offset_attribute_type;
100         static public Type security_attr_type;
101
102         static public Type generic_ienumerator_type;
103         static public Type generic_ienumerable_type;
104
105         //
106         // An empty array of types
107         //
108         static public Type [] NoTypes;
109         static public TypeExpr [] NoTypeExprs;
110
111
112         // 
113         // Expressions representing the internal types.  Used during declaration
114         // definition.
115         //
116         static public TypeExpr system_object_expr, system_string_expr; 
117         static public TypeExpr system_boolean_expr, system_decimal_expr;
118         static public TypeExpr system_single_expr, system_double_expr;
119         static public TypeExpr system_sbyte_expr, system_byte_expr;
120         static public TypeExpr system_int16_expr, system_uint16_expr;
121         static public TypeExpr system_int32_expr, system_uint32_expr;
122         static public TypeExpr system_int64_expr, system_uint64_expr;
123         static public TypeExpr system_char_expr, system_void_expr;
124         static public TypeExpr system_asynccallback_expr;
125         static public TypeExpr system_iasyncresult_expr;
126         static public TypeExpr system_valuetype_expr;
127         static public TypeExpr system_intptr_expr;
128
129         //
130         // This is only used when compiling corlib
131         //
132         static public Type system_int32_type;
133         static public Type system_array_type;
134         static public Type system_type_type;
135         static public Type system_assemblybuilder_type;
136         static public MethodInfo system_int_array_get_length;
137         static public MethodInfo system_int_array_get_rank;
138         static public MethodInfo system_object_array_clone;
139         static public MethodInfo system_int_array_get_length_int;
140         static public MethodInfo system_int_array_get_lower_bound_int;
141         static public MethodInfo system_int_array_get_upper_bound_int;
142         static public MethodInfo system_void_array_copyto_array_int;
143
144         
145         //
146         // Internal, not really used outside
147         //
148         static Type runtime_helpers_type;
149         
150         //
151         // These methods are called by code generated by the compiler
152         //
153         static public MethodInfo string_concat_string_string;
154         static public MethodInfo string_concat_string_string_string;
155         static public MethodInfo string_concat_string_string_string_string;
156         static public MethodInfo string_concat_string_dot_dot_dot;
157         static public MethodInfo string_concat_object_object;
158         static public MethodInfo string_concat_object_object_object;
159         static public MethodInfo string_concat_object_dot_dot_dot;
160         static public MethodInfo string_isinterneted_string;
161         static public MethodInfo system_type_get_type_from_handle;
162         static public MethodInfo object_getcurrent_void;
163         static public MethodInfo bool_movenext_void;
164         static public MethodInfo ienumerable_getenumerator_void;
165         static public MethodInfo void_reset_void;
166         static public MethodInfo void_dispose_void;
167         static public MethodInfo void_monitor_enter_object;
168         static public MethodInfo void_monitor_exit_object;
169         static public MethodInfo void_initializearray_array_fieldhandle;
170         static public MethodInfo int_getlength_int;
171         static public MethodInfo delegate_combine_delegate_delegate;
172         static public MethodInfo delegate_remove_delegate_delegate;
173         static public MethodInfo int_get_offset_to_string_data;
174         static public MethodInfo int_array_get_length;
175         static public MethodInfo int_array_get_rank;
176         static public MethodInfo object_array_clone;
177         static public MethodInfo int_array_get_length_int;
178         static public MethodInfo int_array_get_lower_bound_int;
179         static public MethodInfo int_array_get_upper_bound_int;
180         static public MethodInfo void_array_copyto_array_int;
181         static public MethodInfo activator_create_instance;
182         
183         //
184         // The attribute constructors.
185         //
186         static public ConstructorInfo object_ctor;
187         static public ConstructorInfo cons_param_array_attribute;
188         static public ConstructorInfo void_decimal_ctor_five_args;
189         static public ConstructorInfo unverifiable_code_ctor;
190         static public ConstructorInfo invalid_operation_ctor;
191         static public ConstructorInfo default_member_ctor;
192         
193         // <remarks>
194         //   Holds the Array of Assemblies that have been loaded
195         //   (either because it is the default or the user used the
196         //   -r command line option)
197         // </remarks>
198         static Assembly [] assemblies;
199
200         // <remarks>
201         //  Keeps a list of modules. We used this to do lookups
202         //  on the module using GetType -- needed for arrays
203         // </remarks>
204         static Module [] modules;
205
206         // <remarks>
207         //   This is the type_cache from the assemblies to avoid
208         //   hitting System.Reflection on every lookup.
209         // </summary>
210         static Hashtable types;
211
212         // <remarks>
213         //  This is used to hotld the corresponding TypeContainer objects
214         //  since we need this in FindMembers
215         // </remarks>
216         static Hashtable typecontainers;
217
218         // <remarks>
219         //   Keeps track of those types that are defined by the
220         //   user's program
221         // </remarks>
222         static ArrayList user_types;
223
224         static PtrHashtable builder_to_declspace;
225
226         static PtrHashtable builder_to_member_cache;
227
228         // <remarks>
229         //   Tracks the interfaces implemented by typebuilders.  We only
230         //   enter those who do implement or or more interfaces
231         // </remarks>
232         static PtrHashtable builder_to_ifaces;
233
234         // <remarks>
235         //   Tracks the generic parameters.
236         // </remarks>
237         static PtrHashtable builder_to_type_param;
238
239         // <remarks>
240         //   Maps MethodBase.RuntimeTypeHandle to a Type array that contains
241         //   the arguments to the method
242         // </remarks>
243         static Hashtable method_arguments;
244
245         // <remarks>
246         //   Maps PropertyBuilder to a Type array that contains
247         //   the arguments to the indexer
248         // </remarks>
249         static Hashtable indexer_arguments;
250
251         // <remarks>
252         //   Maybe `method_arguments' should be replaced and only
253         //   method_internal_params should be kept?
254         // <remarks>
255         static Hashtable method_internal_params;
256
257         // <remarks>
258         //  Keeps track of methods
259         // </remarks>
260
261         static Hashtable builder_to_method;
262
263         // <remarks>
264         //  Contains all public types from referenced assemblies.
265         //  This member is used only if CLS Compliance verification is required.
266         // </remarks>
267         public static Hashtable all_imported_types;
268
269         struct Signature {
270                 public string name;
271                 public Type [] args;
272         }
273
274         public static void CleanUp ()
275         {
276                 // Lets get everything clean so that we can collect before generating code
277                 assemblies = null;
278                 modules = null;
279                 types = null;
280                 typecontainers = null;
281                 user_types = null;
282                 builder_to_declspace = null;
283                 builder_to_member_cache = null;
284                 builder_to_ifaces = null;
285                 method_arguments = null;
286                 indexer_arguments = null;
287                 method_internal_params = null;
288                 builder_to_method = null;
289                 builder_to_type_param = null;
290                 
291                 fields = null;
292                 references = null;
293                 negative_hits = null;
294                 builder_to_constant = null;
295                 fieldbuilders_to_fields = null;
296                 events = null;
297                 priv_fields_events = null;
298                 properties = null;
299                 
300                 TypeHandle.CleanUp ();
301         }
302
303         /// <summary>
304         ///   A filter for Findmembers that uses the Signature object to
305         ///   extract objects
306         /// </summary>
307         static bool SignatureFilter (MemberInfo mi, object criteria)
308         {
309                 Signature sig = (Signature) criteria;
310
311                 if (!(mi is MethodBase))
312                         return false;
313                 
314                 if (mi.Name != sig.name)
315                         return false;
316
317                 int count = sig.args.Length;
318                 
319                 if (mi is MethodBuilder || mi is ConstructorBuilder){
320                         Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
321
322                         if (candidate_args.Length != count)
323                                 return false;
324                         
325                         for (int i = 0; i < count; i++)
326                                 if (candidate_args [i] != sig.args [i])
327                                         return false;
328                         
329                         return true;
330                 } else {
331                         ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
332
333                         if (pars.Length != count)
334                                 return false;
335
336                         for (int i = 0; i < count; i++)
337                                 if (pars [i].ParameterType != sig.args [i])
338                                         return false;
339                         return true;
340                 }
341         }
342
343         // A delegate that points to the filter above.
344         static MemberFilter signature_filter;
345
346         //
347         // These are expressions that represent some of the internal data types, used
348         // elsewhere
349         //
350         static void InitExpressionTypes ()
351         {
352                 system_object_expr  = new TypeLookupExpression ("System.Object");
353                 system_string_expr  = new TypeLookupExpression ("System.String");
354                 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
355                 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
356                 system_single_expr  = new TypeLookupExpression ("System.Single");
357                 system_double_expr  = new TypeLookupExpression ("System.Double");
358                 system_sbyte_expr   = new TypeLookupExpression ("System.SByte");
359                 system_byte_expr    = new TypeLookupExpression ("System.Byte");
360                 system_int16_expr   = new TypeLookupExpression ("System.Int16");
361                 system_uint16_expr  = new TypeLookupExpression ("System.UInt16");
362                 system_int32_expr   = new TypeLookupExpression ("System.Int32");
363                 system_uint32_expr  = new TypeLookupExpression ("System.UInt32");
364                 system_int64_expr   = new TypeLookupExpression ("System.Int64");
365                 system_uint64_expr  = new TypeLookupExpression ("System.UInt64");
366                 system_char_expr    = new TypeLookupExpression ("System.Char");
367                 system_void_expr    = new TypeLookupExpression ("System.Void");
368                 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
369                 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
370                 system_valuetype_expr  = new TypeLookupExpression ("System.ValueType");
371                 system_intptr_expr  = new TypeLookupExpression ("System.IntPtr");
372         }
373
374         static TypeManager ()
375         {
376                 assemblies = new Assembly [0];
377                 modules = null;
378                 user_types = new ArrayList ();
379                 
380                 types = new Hashtable ();
381                 typecontainers = new Hashtable ();
382                 
383                 builder_to_declspace = new PtrHashtable ();
384                 builder_to_member_cache = new PtrHashtable ();
385                 builder_to_method = new PtrHashtable ();
386                 method_arguments = new PtrHashtable ();
387                 method_internal_params = new PtrHashtable ();
388                 indexer_arguments = new PtrHashtable ();
389                 builder_to_ifaces = new PtrHashtable ();
390                 builder_to_type_param = new PtrHashtable ();
391                 
392                 NoTypes = new Type [0];
393                 NoTypeExprs = new TypeExpr [0];
394
395                 signature_filter = new MemberFilter (SignatureFilter);
396                 InitExpressionTypes ();
397         }
398
399         public static void HandleDuplicate (string name, Type t)
400         {
401                 Type prev = (Type) types [name];
402                 TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
403                 
404                 if (tc != null){
405                         //
406                         // This probably never happens, as we catch this before
407                         //
408                         Report.Error (-17, "The type `" + name + "' has already been defined.");
409                         return;
410                 }
411                 
412                 tc = builder_to_declspace [t] as TypeContainer;
413                 if (tc != null){
414                         Report.Warning (
415                                         1595, "The type `" + name + "' is defined in an existing assembly;"+
416                                         " Using the new definition from: " + tc.Location);
417                 } else {
418                         Report.Warning (
419                                         1595, "The type `" + name + "' is defined in an existing assembly;");
420                 }
421                 
422                 Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
423                 
424                 types.Remove (name);
425                 types.Add (name, t);
426         }
427         
428         public static void AddUserType (string name, TypeBuilder t)
429         {
430                 try {
431                         types.Add (name, t);
432                 } catch {
433                         HandleDuplicate (name, t); 
434                 }
435                 user_types.Add (t);
436         }
437
438         //
439         // This entry point is used by types that we define under the covers
440         // 
441         public static void RegisterBuilder (Type tb, Type [] ifaces)
442         {
443                 if (ifaces != null)
444                         builder_to_ifaces [tb] = ifaces;
445         }
446         
447         public static void AddUserType (string name, TypeBuilder t, TypeContainer tc)
448         {
449                 builder_to_declspace.Add (t, tc);
450                 typecontainers.Add (name, tc);
451                 AddUserType (name, t);
452         }
453
454         public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
455         {
456                 try {
457                         types.Add (name, t);
458                 } catch {
459                         HandleDuplicate (name, t);
460                 }
461                 
462                 builder_to_declspace.Add (t, del);
463         }
464         
465         public static void AddEnumType (string name, TypeBuilder t, Enum en)
466         {
467                 try {
468                         types.Add (name, t);
469                 } catch {
470                         HandleDuplicate (name, t);
471                 }
472                 builder_to_declspace.Add (t, en);
473         }
474
475         public static void AddMethod (MethodBase builder, IMethodData method)
476         {
477                 builder_to_method.Add (builder, method);
478         }
479
480         public static IMethodData GetMethod (MethodBase builder)
481         {
482                 return (IMethodData) builder_to_method [builder];
483         }
484
485         public static void AddTypeParameter (Type t, TypeParameter tparam)
486         {
487                 if (!builder_to_type_param.Contains (t))
488                         builder_to_type_param.Add (t, tparam);
489         }
490
491         /// <summary>
492         ///   Returns the DeclSpace whose Type is `t' or null if there is no
493         ///   DeclSpace for `t' (ie, the Type comes from a library)
494         /// </summary>
495         public static DeclSpace LookupDeclSpace (Type t)
496         {
497                 return builder_to_declspace [t] as DeclSpace;
498         }
499
500         /// <summary>
501         ///   Returns the TypeContainer whose Type is `t' or null if there is no
502         ///   TypeContainer for `t' (ie, the Type comes from a library)
503         /// </summary>
504         public static TypeContainer LookupTypeContainer (Type t)
505         {
506                 return builder_to_declspace [t] as TypeContainer;
507         }
508
509         public static TypeContainer LookupGenericTypeContainer (Type t)
510         {
511                 while (t.IsGenericInstance)
512                         t = t.GetGenericTypeDefinition ();
513
514                 return LookupTypeContainer (t);
515         }
516
517         public static MemberCache LookupMemberCache (Type t)
518         {
519                 if (t is TypeBuilder) {
520                         IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
521                         if (container != null)
522                                 return container.MemberCache;
523                 }
524
525                 if (t is GenericTypeParameterBuilder) {
526                         IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
527
528                         if (container != null)
529                                 return container.MemberCache;
530                 }
531
532                 return TypeHandle.GetMemberCache (t);
533         }
534
535         public static MemberCache LookupParentInterfacesCache (Type t)
536         {
537                 Type [] ifaces = t.GetInterfaces ();
538
539                 if (ifaces != null && ifaces.Length == 1)
540                         return LookupMemberCache (ifaces [0]);
541
542                 // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
543                 MemberCache cache = builder_to_member_cache [t] as MemberCache;
544                 if (cache != null)
545                         return cache;
546
547                 cache = new MemberCache (ifaces);
548                 builder_to_member_cache.Add (t, cache);
549                 return cache;
550         }
551
552         public static TypeContainer LookupInterface (Type t)
553         {
554                 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
555                 if ((tc == null) || (tc.Kind != Kind.Interface))
556                         return null;
557
558                 return tc;
559         }
560
561         public static Delegate LookupDelegate (Type t)
562         {
563                 return builder_to_declspace [t] as Delegate;
564         }
565
566         public static Enum LookupEnum (Type t)
567         {
568                 return builder_to_declspace [t] as Enum;
569         }
570         
571         public static Class LookupClass (Type t)
572         {
573                 return (Class) builder_to_declspace [t];
574         }
575
576         public static TypeParameter LookupTypeParameter (Type t)
577         {
578                 return (TypeParameter) builder_to_type_param [t];
579         }
580
581         public static bool HasConstructorConstraint (Type t)
582         {
583                 GenericConstraints gc = GetTypeParameterConstraints (t);
584                 if (gc == null)
585                         return false;
586
587                 return (gc.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0;
588         }
589
590         public static GenericConstraints GetTypeParameterConstraints (Type t)
591         {
592                 if (!t.IsGenericParameter)
593                         throw new InvalidOperationException ();
594
595                 TypeParameter tparam = LookupTypeParameter (t);
596                 if (tparam != null)
597                         return tparam.GenericConstraints;
598
599                 return new ReflectionConstraints (t);
600         }
601         
602         /// <summary>
603         ///   Registers an assembly to load types from.
604         /// </summary>
605         public static void AddAssembly (Assembly a)
606         {
607                 foreach (Assembly assembly in assemblies) {
608                         if (a == assembly)
609                                 return;
610                 }
611
612                 int top = assemblies.Length;
613                 Assembly [] n = new Assembly [top + 1];
614
615                 assemblies.CopyTo (n, 0);
616                 
617                 n [top] = a;
618                 assemblies = n;
619         }
620
621         public static Assembly [] GetAssemblies ()
622         {
623                 return assemblies;
624         }
625
626         /// <summary>
627         ///  Registers a module builder to lookup types from
628         /// </summary>
629         public static void AddModule (Module mb)
630         {
631                 int top = modules != null ? modules.Length : 0;
632                 Module [] n = new Module [top + 1];
633
634                 if (modules != null)
635                         modules.CopyTo (n, 0);
636                 n [top] = mb;
637                 modules = n;
638         }
639
640         public static Module[] Modules {
641                 get {
642                         return modules;
643                 }
644         }
645
646         static Hashtable references = new Hashtable ();
647         
648         //
649         // Gets the reference to T version of the Type (T&)
650         //
651         public static Type GetReferenceType (Type t)
652         {
653                 return t.MakeByRefType ();
654         }
655
656         static Hashtable pointers = new Hashtable ();
657
658         //
659         // Gets the pointer to T version of the Type  (T*)
660         //
661         public static Type GetPointerType (Type t)
662         {
663                 string tname = t.FullName + "*";
664                 
665                 Type ret = t.Assembly.GetType (tname);
666                 
667                 //
668                 // If the type comes from the assembly we are building
669                 // We need the Hashtable, because .NET 1.1 will return different instance types
670                 // every time we call ModuleBuilder.GetType.
671                 //
672                 if (ret == null){
673                         if (pointers [t] == null)
674                                 pointers [t] = CodeGen.Module.Builder.GetType (tname);
675                         
676                         ret = (Type) pointers [t];
677                 }
678
679                 return ret;
680         }
681         
682         //
683         // Low-level lookup, cache-less
684         //
685         static Type LookupTypeReflection (string name)
686         {
687                 Type t;
688
689                 foreach (Assembly a in assemblies){
690                         t = a.GetType (name);
691                         if (t == null)
692                                 continue;
693
694                         do {
695                                 TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
696                                 if (ta == TypeAttributes.NotPublic ||
697                                     ta == TypeAttributes.NestedPrivate ||
698                                     ta == TypeAttributes.NestedAssembly ||
699                                     ta == TypeAttributes.NestedFamANDAssem){
700                                         
701                                         //
702                                         // In .NET pointers turn out to be private, even if their
703                                         // element type is not
704                                         //
705                                         if (t.IsPointer){
706                                                 t = t.GetElementType ();
707                                                 continue;
708                                         } else
709                                                 t = null;
710                                 } else {
711                                         return t;
712                                 }
713                         } while (t != null);
714                 }
715
716                 foreach (Module mb in modules) {
717                         t = mb.GetType (name);
718                         if (t != null) 
719                                 return t;
720                 }
721                         
722                 return null;
723         }
724
725         static Hashtable negative_hits = new Hashtable ();
726         
727         //
728         // This function is used when you want to avoid the lookups, and want to go
729         // directly to the source.  This will use the cache.
730         //
731         // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
732         // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
733         // way to test things other than doing a fullname compare
734         //
735         public static Type LookupTypeDirect (string name)
736         {
737                 Type t = (Type) types [name];
738                 if (t != null)
739                         return t;
740
741                 t = LookupTypeReflection (name);
742                 if (t == null)
743                         return null;
744
745                 types [name] = t;
746                 return t;
747         }
748
749         static readonly char [] dot_array = { '.' };
750
751         /// <summary>
752         ///   Returns the Type associated with @name, takes care of the fact that
753         ///   reflection expects nested types to be separated from the main type
754         ///   with a "+" instead of a "."
755         /// </summary>
756         public static Type LookupType (string name)
757         {
758                 Type t;
759
760                 //
761                 // First lookup in user defined and cached values
762                 //
763
764                 t = (Type) types [name];
765                 if (t != null)
766                         return t;
767
768                 // Two thirds of the failures are caught here.
769                 if (negative_hits.Contains (name))
770                         return null;
771
772                 // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
773                 string [] elements = name.Split (dot_array);
774                 int count = elements.Length;
775
776                 for (int n = 1; n <= count; n++){
777                         string top_level_type = String.Join (".", elements, 0, n);
778
779                         // One third of the failures are caught here.
780                         if (negative_hits.Contains (top_level_type))
781                                 continue;
782                         
783                         t = (Type) types [top_level_type];
784                         if (t == null){
785                                 t = LookupTypeReflection (top_level_type);
786                                 if (t == null){
787                                         negative_hits [top_level_type] = null;
788                                         continue;
789                                 }
790                         }
791                         
792                         if (count == n){
793                                 types [name] = t;
794                                 return t;
795                         } 
796
797                         //
798                         // We know that System.Object does not have children, and since its the parent of 
799                         // all the objects, it always gets probbed for inner classes. 
800                         //
801                         if (top_level_type == "System.Object")
802                                 return null;
803                         
804                         string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
805                         //Console.WriteLine ("Looking up: " + newt + " " + name);
806                         t = LookupTypeReflection (newt);
807                         if (t == null)
808                                 negative_hits [name] = null;
809                         else
810                                 types [name] = t;
811                         return t;
812                 }
813                 negative_hits [name] = null;
814                 return null;
815         }
816
817         /// <summary>
818         ///   Computes the namespaces that we import from the assemblies we reference.
819         /// </summary>
820         public static void ComputeNamespaces ()
821         {
822                 MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces", BindingFlags.Instance|BindingFlags.NonPublic);
823
824                 //
825                 // First add the assembly namespaces
826                 //
827                 if (assembly_get_namespaces != null){
828                         int count = assemblies.Length;
829
830                         for (int i = 0; i < count; i++){
831                                 Assembly a = assemblies [i];
832                                 string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
833                                 foreach (string ns in namespaces){
834                                         if (ns == "")
835                                                 continue;
836                                         Namespace.LookupNamespace (ns, true);
837                                 }
838                         }
839                 } else {
840                         Hashtable cache = new Hashtable ();
841                         cache.Add ("", null);
842                         foreach (Assembly a in assemblies) {
843                                 foreach (Type t in a.GetExportedTypes ()) {
844                                         string ns = t.Namespace;
845                                         if (ns == null || cache.Contains (ns))
846                                                 continue;
847
848                                         Namespace.LookupNamespace (ns, true);
849                                         cache.Add (ns, null);
850                                 }
851                         }
852                 }
853         }
854
855         /// <summary>
856         /// Fills static table with exported types from all referenced assemblies.
857         /// This information is required for CLS Compliance tests.
858         /// </summary>
859         public static void LoadAllImportedTypes ()
860         {
861                 all_imported_types = new Hashtable ();
862                 foreach (Assembly a in assemblies) {
863                         foreach (Type t in a.GetExportedTypes ()) {
864                                 all_imported_types [t.FullName] = t;
865                         }
866                 }
867         }
868
869         public static bool NamespaceClash (string name, Location loc)
870         {
871                 if (Namespace.LookupNamespace (name, false) == null)
872                         return false;
873
874                 Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
875                 return true;
876         }
877
878         /// <summary>
879         ///   Returns the C# name of a type if possible, or the full type name otherwise
880         /// </summary>
881         static public string CSharpName (Type t)
882         {
883                 if (t.FullName == null)
884                         return t.Name;
885
886                 return Regex.Replace (t.FullName, 
887                         @"^System\." +
888                         @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
889                         @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
890                         @"Boolean|String|Void|Null)" +
891                         @"(\W+|\b)", 
892                         new MatchEvaluator (CSharpNameMatch));
893         }       
894         
895         static String CSharpNameMatch (Match match) 
896         {
897                 string s = match.Groups [1].Captures [0].Value;
898                 return s.ToLower ().
899                 Replace ("int32", "int").
900                 Replace ("uint32", "uint").
901                 Replace ("int16", "short").
902                 Replace ("uint16", "ushort").
903                 Replace ("int64", "long").
904                 Replace ("uint64", "ulong").
905                 Replace ("single", "float").
906                 Replace ("boolean", "bool")
907                 + match.Groups [2].Captures [0].Value;
908         }
909
910         /// <summary>
911         ///  Returns the signature of the method with full namespace classification
912         /// </summary>
913         static public string GetFullNameSignature (MemberInfo mi)
914         {
915                 return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
916         }
917                 
918         static public string GetFullNameSignature (MethodBase mb)
919         {
920                 string name = mb.Name;
921                 if (name == ".ctor")
922                         name = mb.DeclaringType.Name;
923
924                 if (mb.IsSpecialName) {
925                         if (name.StartsWith ("get_") || name.StartsWith ("set_")) {
926                                 name = name.Remove (0, 4);
927                         }
928
929                         if (name == "Item")
930                                 name = "this";
931                 }
932
933                 return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name;
934         }
935
936         static public string GetFullName (Type t)
937         {
938                 if (t.FullName == null)
939                         return t.Name;
940
941                 string name = t.FullName.Replace ('+', '.');
942
943                 DeclSpace tc = LookupDeclSpace (t);
944                 if ((tc != null) && tc.IsGeneric) {
945                         TypeParameter[] tparam = tc.TypeParameters;
946
947                         StringBuilder sb = new StringBuilder (name);
948                         sb.Append ("<");
949                         for (int i = 0; i < tparam.Length; i++) {
950                                 if (i > 0)
951                                         sb.Append (",");
952                                 sb.Append (tparam [i].Name);
953                         }
954                         sb.Append (">");
955                         return sb.ToString ();
956                 } else if (t.HasGenericArguments && !t.IsGenericInstance) {
957                         Type[] tparam = t.GetGenericArguments ();
958
959                         StringBuilder sb = new StringBuilder (name);
960                         sb.Append ("<");
961                         for (int i = 0; i < tparam.Length; i++) {
962                                 if (i > 0)
963                                         sb.Append (",");
964                                 sb.Append (tparam [i].Name);
965                         }
966                         sb.Append (">");
967                         return sb.ToString ();
968                 }
969
970                 return name;
971         }
972
973         /// <summary>
974         ///   Returns the signature of the property and indexer
975         /// </summary>
976         static public string CSharpSignature (PropertyBuilder pb, bool is_indexer) 
977         {
978                 if (!is_indexer) {
979                         return GetFullNameSignature (pb);
980                 }
981
982                 MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
983                 string signature = GetFullNameSignature (mb);
984                 string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
985                 return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
986         }
987
988         /// <summary>
989         ///   Returns the signature of the method
990         /// </summary>
991         static public string CSharpSignature (MethodBase mb)
992         {
993                 StringBuilder sig = new StringBuilder ("(");
994
995                 //
996                 // FIXME: We should really have a single function to do
997                 // everything instead of the following 5 line pattern
998                 //
999                 ParameterData iparams = LookupParametersByBuilder (mb);
1000
1001                 if (iparams == null)
1002                         iparams = new ReflectionParameters (mb);
1003                 
1004                 // Is property
1005                 if (mb.IsSpecialName && iparams.Count == 0 && !mb.IsConstructor)
1006                         return GetFullNameSignature (mb);
1007                 
1008                 for (int i = 0; i < iparams.Count; i++) {
1009                         if (i > 0) {
1010                                 sig.Append (", ");
1011                         }
1012                         sig.Append (iparams.ParameterDesc (i));
1013                 }
1014                 sig.Append (")");
1015
1016                 // Is indexer
1017                 if (mb.IsSpecialName && iparams.Count == 1 && !mb.IsConstructor) {
1018                         sig.Replace ('(', '[');
1019                         sig.Replace (')', ']');
1020                 }
1021
1022                 return GetFullNameSignature (mb) + sig.ToString ();
1023         }
1024
1025         public static string GetMethodName (MethodInfo m)
1026         {
1027                 if (!IsGenericMethod (m))
1028                         return m.Name;
1029
1030                 return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
1031         }
1032
1033         /// <summary>
1034         ///   Looks up a type, and aborts if it is not found.  This is used
1035         ///   by types required by the compiler
1036         /// </summary>
1037         static Type CoreLookupType (string name)
1038         {
1039                 Type t = LookupTypeDirect (name);
1040
1041                 if (t == null){
1042                         Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
1043                         Environment.Exit (1);
1044                 }
1045
1046                 return t;
1047         }
1048
1049         /// <summary>
1050         ///   Returns the MethodInfo for a method named `name' defined
1051         ///   in type `t' which takes arguments of types `args'
1052         /// </summary>
1053         static MethodInfo GetMethod (Type t, string name, Type [] args, bool is_private, bool report_errors)
1054         {
1055                 MemberList list;
1056                 Signature sig;
1057                 BindingFlags flags = instance_and_static | BindingFlags.Public;
1058
1059                 sig.name = name;
1060                 sig.args = args;
1061                 
1062                 if (is_private)
1063                         flags |= BindingFlags.NonPublic;
1064
1065                 list = FindMembers (t, MemberTypes.Method, flags, signature_filter, sig);
1066                 if (list.Count == 0) {
1067                         if (report_errors)
1068                                 Report.Error (-19, "Can not find the core function `" + name + "'");
1069                         return null;
1070                 }
1071
1072                 MethodInfo mi = list [0] as MethodInfo;
1073                 if (mi == null) {
1074                         if (report_errors)
1075                                 Report.Error (-19, "Can not find the core function `" + name + "'");
1076                         return null;
1077                 }
1078
1079                 return mi;
1080         }
1081
1082         static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
1083         {
1084                 return GetMethod (t, name, args, false, report_errors);
1085         }
1086
1087         static MethodInfo GetMethod (Type t, string name, Type [] args)
1088         {
1089                 return GetMethod (t, name, args, true);
1090         }
1091
1092
1093         /// <summary>
1094         ///    Returns the ConstructorInfo for "args"
1095         /// </summary>
1096         static ConstructorInfo GetConstructor (Type t, Type [] args)
1097         {
1098                 MemberList list;
1099                 Signature sig;
1100
1101                 sig.name = ".ctor";
1102                 sig.args = args;
1103                 
1104                 list = FindMembers (t, MemberTypes.Constructor,
1105                                     instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
1106                                     signature_filter, sig);
1107                 if (list.Count == 0){
1108                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1109                         return null;
1110                 }
1111
1112                 ConstructorInfo ci = list [0] as ConstructorInfo;
1113                 if (ci == null){
1114                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
1115                         return null;
1116                 }
1117
1118                 return ci;
1119         }
1120
1121         public static void InitEnumUnderlyingTypes ()
1122         {
1123
1124                 int32_type    = CoreLookupType ("System.Int32");
1125                 int64_type    = CoreLookupType ("System.Int64");
1126                 uint32_type   = CoreLookupType ("System.UInt32"); 
1127                 uint64_type   = CoreLookupType ("System.UInt64"); 
1128                 byte_type     = CoreLookupType ("System.Byte");
1129                 sbyte_type    = CoreLookupType ("System.SByte");
1130                 short_type    = CoreLookupType ("System.Int16");
1131                 ushort_type   = CoreLookupType ("System.UInt16");
1132         }
1133         
1134         /// <remarks>
1135         ///   The types have to be initialized after the initial
1136         ///   population of the type has happened (for example, to
1137         ///   bootstrap the corlib.dll
1138         /// </remarks>
1139         public static void InitCoreTypes ()
1140         {
1141                 object_type   = CoreLookupType ("System.Object");
1142                 value_type    = CoreLookupType ("System.ValueType");
1143
1144                 InitEnumUnderlyingTypes ();
1145
1146                 char_type     = CoreLookupType ("System.Char");
1147                 string_type   = CoreLookupType ("System.String");
1148                 float_type    = CoreLookupType ("System.Single");
1149                 double_type   = CoreLookupType ("System.Double");
1150                 char_ptr_type = CoreLookupType ("System.Char*");
1151                 decimal_type  = CoreLookupType ("System.Decimal");
1152                 bool_type     = CoreLookupType ("System.Boolean");
1153                 enum_type     = CoreLookupType ("System.Enum");
1154
1155                 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
1156                 delegate_type           = CoreLookupType ("System.Delegate");
1157
1158                 array_type    = CoreLookupType ("System.Array");
1159                 void_type     = CoreLookupType ("System.Void");
1160                 type_type     = CoreLookupType ("System.Type");
1161
1162                 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
1163                 runtime_argument_handle_type = CoreLookupType ("System.RuntimeArgumentHandle");
1164                 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
1165                 default_member_type  = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
1166                 runtime_handle_type  = CoreLookupType ("System.RuntimeTypeHandle");
1167                 asynccallback_type   = CoreLookupType ("System.AsyncCallback");
1168                 iasyncresult_type    = CoreLookupType ("System.IAsyncResult");
1169                 ienumerator_type     = CoreLookupType ("System.Collections.IEnumerator");
1170                 ienumerable_type     = CoreLookupType ("System.Collections.IEnumerable");
1171                 idisposable_type     = CoreLookupType ("System.IDisposable");
1172                 icloneable_type      = CoreLookupType ("System.ICloneable");
1173                 iconvertible_type    = CoreLookupType ("System.IConvertible");
1174                 monitor_type         = CoreLookupType ("System.Threading.Monitor");
1175                 intptr_type          = CoreLookupType ("System.IntPtr");
1176
1177                 attribute_type       = CoreLookupType ("System.Attribute");
1178                 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
1179                 dllimport_type       = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
1180                 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
1181                 marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
1182                 new_constraint_attr_type = CoreLookupType ("System.Runtime.CompilerServices.NewConstraintAttribute");
1183                 param_array_type     = CoreLookupType ("System.ParamArrayAttribute");
1184                 in_attribute_type    = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
1185                 typed_reference_type = CoreLookupType ("System.TypedReference");
1186                 arg_iterator_type    = CoreLookupType ("System.ArgIterator");
1187                 mbr_type             = CoreLookupType ("System.MarshalByRefObject");
1188
1189                 //
1190                 // Sigh. Remove this before the release.  Wonder what versions of Mono
1191                 // people are running.
1192                 //
1193                 guid_attr_type        = LookupType ("System.Runtime.InteropServices.GuidAttribute");
1194
1195                 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
1196
1197                 void_ptr_type         = CoreLookupType ("System.Void*");
1198
1199                 indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
1200
1201                 exception_type        = CoreLookupType ("System.Exception");
1202                 activator_type        = CoreLookupType ("System.Activator");
1203                 invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
1204                 not_supported_exception_type = CoreLookupType ("System.NotSupportedException");
1205
1206                 //
1207                 // Attribute types
1208                 //
1209                 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
1210                 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
1211                 cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
1212                 struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
1213                 field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
1214                 security_attr_type = CoreLookupType ("System.Security.Permissions.SecurityAttribute");
1215
1216                 //
1217                 // Generic types
1218                 //
1219                 generic_ienumerator_type     = CoreLookupType (MemberName.MakeName ("System.Collections.Generic.IEnumerator", 1));
1220                 generic_ienumerable_type     = CoreLookupType (MemberName.MakeName ("System.Collections.Generic.IEnumerable", 1));
1221
1222
1223                 //
1224                 // When compiling corlib, store the "real" types here.
1225                 //
1226                 if (!RootContext.StdLib) {
1227                         system_int32_type = typeof (System.Int32);
1228                         system_array_type = typeof (System.Array);
1229                         system_type_type = typeof (System.Type);
1230                         system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
1231
1232                         Type [] void_arg = {  };
1233                         system_int_array_get_length = GetMethod (
1234                                 system_array_type, "get_Length", void_arg);
1235                         system_int_array_get_rank = GetMethod (
1236                                 system_array_type, "get_Rank", void_arg);
1237                         system_object_array_clone = GetMethod (
1238                                 system_array_type, "Clone", void_arg);
1239
1240                         Type [] system_int_arg = { system_int32_type };
1241                         system_int_array_get_length_int = GetMethod (
1242                                 system_array_type, "GetLength", system_int_arg);
1243                         system_int_array_get_upper_bound_int = GetMethod (
1244                                 system_array_type, "GetUpperBound", system_int_arg);
1245                         system_int_array_get_lower_bound_int = GetMethod (
1246                                 system_array_type, "GetLowerBound", system_int_arg);
1247
1248                         Type [] system_array_int_arg = { system_array_type, system_int32_type };
1249                         system_void_array_copyto_array_int = GetMethod (
1250                                 system_array_type, "CopyTo", system_array_int_arg);
1251
1252                         Type [] system_3_type_arg = {
1253                                 system_type_type, system_type_type, system_type_type };
1254                         Type [] system_4_type_arg = {
1255                                 system_type_type, system_type_type, system_type_type, system_type_type };
1256
1257                         MethodInfo set_corlib_type_builders = GetMethod (
1258                                 system_assemblybuilder_type, "SetCorlibTypeBuilders",
1259                                 system_4_type_arg, true, false);
1260
1261                         if (set_corlib_type_builders != null) {
1262                                 object[] args = new object [4];
1263                                 args [0] = object_type;
1264                                 args [1] = value_type;
1265                                 args [2] = enum_type;
1266                                 args [3] = void_type;
1267                                 
1268                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1269                         } else {
1270                                 // Compatibility for an older version of the class libs.
1271                                 set_corlib_type_builders = GetMethod (
1272                                         system_assemblybuilder_type, "SetCorlibTypeBuilders",
1273                                         system_3_type_arg, true, true);
1274
1275                                 if (set_corlib_type_builders == null) {
1276                                         Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
1277                                         return;
1278                                 }
1279
1280                                 object[] args = new object [3];
1281                                 args [0] = object_type;
1282                                 args [1] = value_type;
1283                                 args [2] = enum_type;
1284                                 
1285                                 set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
1286                         }
1287                 }
1288
1289                 system_object_expr.Type = object_type;
1290                 system_string_expr.Type = string_type;
1291                 system_boolean_expr.Type = bool_type;
1292                 system_decimal_expr.Type = decimal_type;
1293                 system_single_expr.Type = float_type;
1294                 system_double_expr.Type = double_type;
1295                 system_sbyte_expr.Type = sbyte_type;
1296                 system_byte_expr.Type = byte_type;
1297                 system_int16_expr.Type = short_type;
1298                 system_uint16_expr.Type = ushort_type;
1299                 system_int32_expr.Type = int32_type;
1300                 system_uint32_expr.Type = uint32_type;
1301                 system_int64_expr.Type = int64_type;
1302                 system_uint64_expr.Type = uint64_type;
1303                 system_char_expr.Type = char_type;
1304                 system_void_expr.Type = void_type;
1305                 system_asynccallback_expr.Type = asynccallback_type;
1306                 system_iasyncresult_expr.Type = iasyncresult_type;
1307                 system_valuetype_expr.Type = value_type;
1308
1309                 //
1310                 // These are only used for compare purposes
1311                 //
1312                 anonymous_method_type = typeof (AnonymousMethod);
1313                 null_type = typeof (NullType);
1314         }
1315
1316         //
1317         // The helper methods that are used by the compiler
1318         //
1319         public static void InitCodeHelpers ()
1320         {
1321                 //
1322                 // Now load the default methods that we use.
1323                 //
1324                 Type [] string_string = { string_type, string_type };
1325                 string_concat_string_string = GetMethod (
1326                         string_type, "Concat", string_string);
1327                 Type [] string_string_string = { string_type, string_type, string_type };
1328                 string_concat_string_string_string = GetMethod (
1329                         string_type, "Concat", string_string_string);
1330                 Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
1331                 string_concat_string_string_string_string = GetMethod (
1332                         string_type, "Concat", string_string_string_string);
1333                 Type[] params_string = { TypeManager.LookupType ("System.String[]") };
1334                 string_concat_string_dot_dot_dot = GetMethod (
1335                         string_type, "Concat", params_string);
1336
1337                 Type [] object_object = { object_type, object_type };
1338                 string_concat_object_object = GetMethod (
1339                         string_type, "Concat", object_object);
1340                 Type [] object_object_object = { object_type, object_type, object_type };
1341                 string_concat_object_object_object = GetMethod (
1342                         string_type, "Concat", object_object_object);
1343                 Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
1344                 string_concat_object_dot_dot_dot = GetMethod (
1345                         string_type, "Concat", params_object);
1346
1347                 Type [] string_ = { string_type };
1348                 string_isinterneted_string = GetMethod (
1349                         string_type, "IsInterned", string_);
1350                 
1351                 Type [] runtime_type_handle = { runtime_handle_type };
1352                 system_type_get_type_from_handle = GetMethod (
1353                         type_type, "GetTypeFromHandle", runtime_type_handle);
1354
1355                 Type [] delegate_delegate = { delegate_type, delegate_type };
1356                 delegate_combine_delegate_delegate = GetMethod (
1357                                 delegate_type, "Combine", delegate_delegate);
1358
1359                 delegate_remove_delegate_delegate = GetMethod (
1360                                 delegate_type, "Remove", delegate_delegate);
1361
1362                 //
1363                 // Void arguments
1364                 //
1365                 Type [] void_arg = {  };
1366                 object_getcurrent_void = GetMethod (
1367                         ienumerator_type, "get_Current", void_arg);
1368                 bool_movenext_void = GetMethod (
1369                         ienumerator_type, "MoveNext", void_arg);
1370                 void_reset_void = GetMethod (
1371                         ienumerator_type, "Reset", void_arg);
1372                 void_dispose_void = GetMethod (
1373                         idisposable_type, "Dispose", void_arg);
1374                 int_get_offset_to_string_data = GetMethod (
1375                         runtime_helpers_type, "get_OffsetToStringData", void_arg);
1376                 int_array_get_length = GetMethod (
1377                         array_type, "get_Length", void_arg);
1378                 int_array_get_rank = GetMethod (
1379                         array_type, "get_Rank", void_arg);
1380                 ienumerable_getenumerator_void = GetMethod (
1381                         ienumerable_type, "GetEnumerator", void_arg);
1382                 
1383                 //
1384                 // Int32 arguments
1385                 //
1386                 Type [] int_arg = { int32_type };
1387                 int_array_get_length_int = GetMethod (
1388                         array_type, "GetLength", int_arg);
1389                 int_array_get_upper_bound_int = GetMethod (
1390                         array_type, "GetUpperBound", int_arg);
1391                 int_array_get_lower_bound_int = GetMethod (
1392                         array_type, "GetLowerBound", int_arg);
1393
1394                 //
1395                 // System.Array methods
1396                 //
1397                 object_array_clone = GetMethod (
1398                         array_type, "Clone", void_arg);
1399                 Type [] array_int_arg = { array_type, int32_type };
1400                 void_array_copyto_array_int = GetMethod (
1401                         array_type, "CopyTo", array_int_arg);
1402                 
1403                 //
1404                 // object arguments
1405                 //
1406                 Type [] object_arg = { object_type };
1407                 void_monitor_enter_object = GetMethod (
1408                         monitor_type, "Enter", object_arg);
1409                 void_monitor_exit_object = GetMethod (
1410                         monitor_type, "Exit", object_arg);
1411
1412                 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
1413                 
1414                 void_initializearray_array_fieldhandle = GetMethod (
1415                         runtime_helpers_type, "InitializeArray", array_field_handle_arg);
1416
1417                 //
1418                 // Array functions
1419                 //
1420                 int_getlength_int = GetMethod (
1421                         array_type, "GetLength", int_arg);
1422
1423                 //
1424                 // Decimal constructors
1425                 //
1426                 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
1427                 void_decimal_ctor_five_args = GetConstructor (
1428                         decimal_type, dec_arg);
1429                 
1430                 //
1431                 // Attributes
1432                 //
1433                 cons_param_array_attribute = GetConstructor (
1434                         param_array_type, void_arg);
1435
1436                 unverifiable_code_ctor = GetConstructor (
1437                         unverifiable_code_type, void_arg);
1438
1439                 default_member_ctor = GetConstructor (default_member_type, string_);
1440
1441                 //
1442                 // InvalidOperationException
1443                 //
1444                 invalid_operation_ctor = GetConstructor (
1445                         invalid_operation_exception_type, void_arg);
1446
1447
1448                 // Object
1449                 object_ctor = GetConstructor (object_type, void_arg);
1450
1451                 // Activator
1452                 Type [] type_arg = { type_type };
1453                 activator_create_instance = GetMethod (
1454                         activator_type, "CreateInstance", type_arg);
1455         }
1456
1457         const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
1458
1459         /// <remarks>
1460         ///   This is the "old", non-cache based FindMembers() function.  We cannot use
1461         ///   the cache here because there is no member name argument.
1462         /// </remarks>
1463         public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1464                                               MemberFilter filter, object criteria)
1465         {
1466                 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1467
1468                 //
1469                 // `builder_to_declspace' contains all dynamic types.
1470                 //
1471                 if (decl != null) {
1472                         MemberList list;
1473                         Timer.StartTimer (TimerType.FindMembers);
1474                         list = decl.FindMembers (mt, bf, filter, criteria);
1475                         Timer.StopTimer (TimerType.FindMembers);
1476                         return list;
1477                 }
1478
1479                 //
1480                 // We have to take care of arrays specially, because GetType on
1481                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1482                 // and we can not call FindMembers on this type.
1483                 //
1484                 if (t.IsSubclassOf (TypeManager.array_type))
1485                         return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
1486
1487                 if (t is GenericTypeParameterBuilder) {
1488                         TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1489
1490                         Timer.StartTimer (TimerType.FindMembers);
1491                         MemberList list = tparam.FindMembers (
1492                                 mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
1493                         Timer.StopTimer (TimerType.FindMembers);
1494                         return list;
1495                 }
1496
1497                 //
1498                 // Since FindMembers will not lookup both static and instance
1499                 // members, we emulate this behaviour here.
1500                 //
1501                 if ((bf & instance_and_static) == instance_and_static){
1502                         MemberInfo [] i_members = t.FindMembers (
1503                                 mt, bf & ~BindingFlags.Static, filter, criteria);
1504
1505                         int i_len = i_members.Length;
1506                         if (i_len == 1){
1507                                 MemberInfo one = i_members [0];
1508
1509                                 //
1510                                 // If any of these are present, we are done!
1511                                 //
1512                                 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
1513                                         return new MemberList (i_members);
1514                         }
1515                                 
1516                         MemberInfo [] s_members = t.FindMembers (
1517                                 mt, bf & ~BindingFlags.Instance, filter, criteria);
1518
1519                         int s_len = s_members.Length;
1520                         if (i_len > 0 || s_len > 0)
1521                                 return new MemberList (i_members, s_members);
1522                         else {
1523                                 if (i_len > 0)
1524                                         return new MemberList (i_members);
1525                                 else
1526                                         return new MemberList (s_members);
1527                         }
1528                 }
1529
1530                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1531         }
1532
1533
1534         /// <summary>
1535         ///   This method is only called from within MemberLookup.  It tries to use the member
1536         ///   cache if possible and falls back to the normal FindMembers if not.  The `used_cache'
1537         ///   flag tells the caller whether we used the cache or not.  If we used the cache, then
1538         ///   our return value will already contain all inherited members and the caller don't need
1539         ///   to check base classes and interfaces anymore.
1540         /// </summary>
1541         private static MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1542                                                             string name, out bool used_cache)
1543         {
1544                 MemberCache cache;
1545
1546                 //
1547                 // We have to take care of arrays specially, because GetType on
1548                 // a TypeBuilder array will return a Type, not a TypeBuilder,
1549                 // and we can not call FindMembers on this type.
1550                 //
1551                 if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
1552                         used_cache = true;
1553                         return TypeHandle.ArrayType.MemberCache.FindMembers (
1554                                 mt, bf, name, FilterWithClosure_delegate, null);
1555                 }
1556
1557                 //
1558                 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
1559                 // and we can ask the DeclSpace for the MemberCache.
1560                 //
1561                 if (t is TypeBuilder) {
1562                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
1563                         cache = decl.MemberCache;
1564
1565                         //
1566                         // If this DeclSpace has a MemberCache, use it.
1567                         //
1568
1569                         if (cache != null) {
1570                                 used_cache = true;
1571                                 return cache.FindMembers (
1572                                         mt, bf, name, FilterWithClosure_delegate, null);
1573                         }
1574
1575                         // If there is no MemberCache, we need to use the "normal" FindMembers.
1576                         // Note, this is a VERY uncommon route!
1577
1578                         MemberList list;
1579                         Timer.StartTimer (TimerType.FindMembers);
1580                         list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1581                                                  FilterWithClosure_delegate, name);
1582                         Timer.StopTimer (TimerType.FindMembers);
1583                         used_cache = false;
1584                         return (MemberInfo []) list;
1585                 }
1586
1587                 if (t is GenericTypeParameterBuilder) {
1588                         TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
1589
1590                         MemberList list;
1591                         Timer.StartTimer (TimerType.FindMembers);
1592                         list = tparam.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
1593                                                    FilterWithClosure_delegate, name);
1594                         Timer.StopTimer (TimerType.FindMembers);
1595                         used_cache = false;
1596                         return (MemberInfo []) list;
1597                 }
1598
1599                 //
1600                 // This call will always succeed.  There is exactly one TypeHandle instance per
1601                 // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
1602                 // the corresponding MemberCache.
1603                 //
1604                 cache = TypeHandle.GetMemberCache (t);
1605
1606                 used_cache = true;
1607                 return cache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
1608         }
1609
1610         public static bool IsBuiltinType (Type t)
1611         {
1612                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
1613                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1614                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
1615                     t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
1616                         return true;
1617                 else
1618                         return false;
1619         }
1620
1621         public static bool IsBuiltinType (TypeContainer tc)
1622         {
1623                 return IsBuiltinType (tc.TypeBuilder);
1624         }
1625
1626         //
1627         // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
1628         // the pieces in the code where we use IsBuiltinType and special case decimal_type.
1629         // 
1630         public static bool IsCLRType (Type t)
1631         {
1632                 if (t == object_type || t == int32_type || t == uint32_type ||
1633                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
1634                     t == char_type || t == short_type || t == bool_type ||
1635                     t == sbyte_type || t == byte_type || t == ushort_type)
1636                         return true;
1637                 else
1638                         return false;
1639         }
1640
1641         public static bool IsDelegateType (Type t)
1642         {
1643                 if (t.IsGenericInstance)
1644                         t = t.GetGenericTypeDefinition ();
1645
1646                 if (t.IsSubclassOf (TypeManager.delegate_type))
1647                         return true;
1648                 else
1649                         return false;
1650         }
1651         
1652         public static bool IsEnumType (Type t)
1653         {
1654                 if (t.IsSubclassOf (TypeManager.enum_type))
1655                         return true;
1656                 else
1657                         return false;
1658         }
1659         public static bool IsBuiltinOrEnum (Type t)
1660         {
1661                 if (IsBuiltinType (t))
1662                         return true;
1663                 
1664                 if (IsEnumType (t))
1665                         return true;
1666
1667                 return false;
1668         }
1669
1670         public static bool IsNullType (Type t)
1671         {
1672                 return t == null_type;
1673         }
1674
1675         //
1676         // Only a quick hack to get things moving, while real runtime support appears
1677         //
1678         public static bool IsGeneric (Type t)
1679         {
1680                 DeclSpace ds = (DeclSpace) builder_to_declspace [t];
1681
1682                 return ds.IsGeneric;
1683         }
1684
1685         public static bool HasGenericArguments (Type t)
1686         {
1687                 return GetNumberOfTypeArguments (t) > 0;
1688         }
1689
1690         public static int GetNumberOfTypeArguments (Type t)
1691         {
1692                 DeclSpace tc = LookupDeclSpace (t);
1693                 if (tc != null)
1694                         return tc.IsGeneric ? tc.CountTypeParameters : 0;
1695                 else
1696                         return t.HasGenericArguments ? t.GetGenericArguments ().Length : 0;
1697         }
1698
1699         public static Type[] GetTypeArguments (Type t)
1700         {
1701                 DeclSpace tc = LookupDeclSpace (t);
1702                 if (tc != null) {
1703                         if (!tc.IsGeneric)
1704                                 throw new InvalidOperationException ();
1705
1706                         TypeParameter[] tparam = tc.TypeParameters;
1707                         Type[] ret = new Type [tparam.Length];
1708                         for (int i = 0; i < tparam.Length; i++) {
1709                                 ret [i] = tparam [i].Type;
1710                                 if (ret [i] == null)
1711                                         throw new InternalErrorException ();
1712                         }
1713
1714                         return ret;
1715                 } else
1716                         return t.GetGenericArguments ();
1717         }
1718         
1719         //
1720         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
1721         //
1722         public static bool IsUnmanagedType (Type t)
1723         {
1724                 if (IsBuiltinType (t) && t != TypeManager.string_type)
1725                         return true;
1726
1727                 if (IsEnumType (t))
1728                         return true;
1729
1730                 if (t.IsPointer)
1731                         return true;
1732
1733                 if (IsValueType (t)){
1734                         if (t is TypeBuilder){
1735                                 TypeContainer tc = LookupTypeContainer (t);
1736
1737                                 if (tc.Fields != null){
1738                                 foreach (Field f in tc.Fields){
1739                                         if (f.FieldBuilder.IsStatic)
1740                                                 continue;
1741                                         if (!IsUnmanagedType (f.FieldBuilder.FieldType))
1742                                                 return false;
1743                                 }
1744                                 } else
1745                                         return true;
1746                         } else {
1747                                 FieldInfo [] fields = t.GetFields ();
1748
1749                                 foreach (FieldInfo f in fields){
1750                                         if (f.IsStatic)
1751                                                 continue;
1752                                         if (!IsUnmanagedType (f.FieldType))
1753                                                 return false;
1754                                 }
1755                         }
1756                         return true;
1757                 }
1758
1759                 return false;
1760         }
1761                 
1762         public static bool IsValueType (Type t)
1763         {
1764                 return t.IsGenericParameter || t.IsValueType;
1765         }
1766         
1767         public static bool IsInterfaceType (Type t)
1768         {
1769                 TypeContainer tc = (TypeContainer) builder_to_declspace [t];
1770                 if (tc == null)
1771                         return false;
1772
1773                 return tc.Kind == Kind.Interface;
1774         }
1775
1776         public static bool IsEqual (Type a, Type b)
1777         {
1778                 if (a.Equals (b))
1779                         return true;
1780
1781                 if ((a is TypeBuilder) && a.IsGenericTypeDefinition && b.IsGenericInstance) {
1782                         //
1783                         // `a' is a generic type definition's TypeBuilder and `b' is a
1784                         // generic instance of the same type.
1785                         //
1786                         // Example:
1787                         //
1788                         // class Stack<T>
1789                         // {
1790                         //     void Test (Stack<T> stack) { }
1791                         // }
1792                         //
1793                         // The first argument of `Test' will be the generic instance
1794                         // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
1795                         //
1796                         //
1797                         // We hit this via Closure.Filter() for gen-82.cs.
1798                         //
1799                         if (a != b.GetGenericTypeDefinition ())
1800                                 return false;
1801
1802                         Type[] aparams = a.GetGenericArguments ();
1803                         Type[] bparams = b.GetGenericArguments ();
1804
1805                         if (aparams.Length != bparams.Length)
1806                                 return false;
1807
1808                         for (int i = 0; i < aparams.Length; i++)
1809                                 if (!IsEqual (aparams [i], bparams [i]))
1810                                         return false;
1811
1812                         return true;
1813                 }
1814
1815                 if (a.IsGenericParameter && b.IsGenericParameter) {
1816                         if ((a.DeclaringMethod == null) || (b.DeclaringMethod == null))
1817                                 return false;
1818                         return a.GenericParameterPosition == b.GenericParameterPosition;
1819                 }
1820
1821                 if (a.IsArray && b.IsArray) {
1822                         if (a.GetArrayRank () != b.GetArrayRank ())
1823                                 return false;
1824                         return IsEqual (a.GetElementType (), b.GetElementType ());
1825                 }
1826
1827                 if (a.IsGenericInstance && b.IsGenericInstance) {
1828                         Type at = a.GetGenericTypeDefinition ();
1829                         Type bt = b.GetGenericTypeDefinition ();
1830
1831                         if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
1832                                 return false;
1833
1834                         Type[] aargs = a.GetGenericArguments ();
1835                         Type[] bargs = b.GetGenericArguments ();
1836
1837                         if (aargs.Length != bargs.Length)
1838                                 return false;
1839
1840                         for (int i = 0; i < aargs.Length; i++) {
1841                                 if (!IsEqual (aargs [i], bargs [i]))
1842                                         return false;
1843                         }
1844
1845                         return true;
1846                 }
1847
1848                 return false;
1849         }
1850
1851         public static bool MayBecomeEqualGenericTypes (Type a, Type b)
1852         {
1853                 if (a.IsGenericParameter) {
1854                         //
1855                         // If a is an array of a's type, they may never
1856                         // become equal.
1857                         //
1858                         while (b.IsArray) {
1859                                 b = b.GetElementType ();
1860                                 if (a.Equals (b))
1861                                         return false;
1862                         }
1863
1864                         //
1865                         // If b is a generic parameter or an actual type,
1866                         // they may become equal:
1867                         //
1868                         //    class X<T,U> : I<T>, I<U>
1869                         //    class X<T> : I<T>, I<float>
1870                         // 
1871                         if (b.IsGenericParameter || !b.IsGenericInstance)
1872                                 return true;
1873
1874                         //
1875                         // We're now comparing a type parameter with a
1876                         // generic instance.  They may become equal unless
1877                         // the type parameter appears anywhere in the
1878                         // generic instance:
1879                         //
1880                         //    class X<T,U> : I<T>, I<X<U>>
1881                         //        -> error because you could instanciate it as
1882                         //           X<X<int>,int>
1883                         //
1884                         //    class X<T> : I<T>, I<X<T>> -> ok
1885                         //
1886
1887                         Type[] bargs = GetTypeArguments (b);
1888                         for (int i = 0; i < bargs.Length; i++) {
1889                                 if (a.Equals (bargs [i]))
1890                                         return false;
1891                         }
1892
1893                         return true;
1894                 }
1895
1896                 if (b.IsGenericParameter)
1897                         return MayBecomeEqualGenericTypes (b, a);
1898
1899                 //
1900                 // At this point, neither a nor b are a type parameter.
1901                 //
1902                 // If one of them is a generic instance, let
1903                 // MayBecomeEqualGenericInstances() compare them (if the
1904                 // other one is not a generic instance, they can never
1905                 // become equal).
1906                 //
1907
1908                 if (a.IsGenericInstance || b.IsGenericInstance)
1909                         return MayBecomeEqualGenericInstances (a, b);
1910
1911                 //
1912                 // If both of them are arrays.
1913                 //
1914
1915                 if (a.IsArray && b.IsArray) {
1916                         if (a.GetArrayRank () != b.GetArrayRank ())
1917                                 return false;
1918                         
1919                         a = a.GetElementType ();
1920                         b = b.GetElementType ();
1921
1922                         return MayBecomeEqualGenericTypes (a, b);
1923                 }
1924
1925                 //
1926                 // Ok, two ordinary types.
1927                 //
1928
1929                 return a.Equals (b);
1930         }
1931
1932         //
1933         // Checks whether two generic instances may become equal for some
1934         // particular instantiation (26.3.1).
1935         //
1936         public static bool MayBecomeEqualGenericInstances (Type a, Type b)
1937         {
1938                 if (!a.IsGenericInstance || !b.IsGenericInstance)
1939                         return false;
1940                 if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
1941                         return false;
1942
1943                 Type[] aargs = GetTypeArguments (a);
1944                 Type[] bargs = GetTypeArguments (b);
1945
1946                 if (aargs.Length != bargs.Length)
1947                         return false;
1948
1949                 for (int i = 0; i < aargs.Length; i++) {
1950                         if (MayBecomeEqualGenericTypes (aargs [i], bargs [i]))
1951                                 return true;
1952                 }
1953
1954                 return false;
1955         }
1956
1957         public static bool IsEqualGenericInstance (Type type, Type parent)
1958         {
1959                 int tcount = GetNumberOfTypeArguments (type);
1960                 int pcount = GetNumberOfTypeArguments (parent);
1961
1962                 if (type.IsGenericInstance)
1963                         type = type.GetGenericTypeDefinition ();
1964                 if (parent.IsGenericInstance)
1965                         parent = parent.GetGenericTypeDefinition ();
1966
1967                 if (tcount != pcount)
1968                         return false;
1969
1970                 return type.Equals (parent);
1971         }
1972
1973         public static bool IsSubclassOf (Type type, Type parent)
1974         {
1975                 TypeParameter tparam = LookupTypeParameter (type);
1976                 TypeParameter pparam = LookupTypeParameter (parent);
1977
1978                 if ((tparam != null) && (pparam != null)) {
1979                         if (tparam == pparam)
1980                                 return true;
1981
1982                         return tparam.IsSubclassOf (parent);
1983                 }
1984
1985                 do {
1986                         if (type.Equals (parent))
1987                                 return true;
1988
1989                         type = type.BaseType;
1990                 } while (type != null);
1991
1992                 return false;
1993         }
1994
1995         public static bool IsPrivateAccessible (Type type, Type parent)
1996         {
1997                 if (type.Equals (parent))
1998                         return true;
1999
2000                 if ((type is TypeBuilder) && type.IsGenericTypeDefinition && parent.IsGenericInstance) {
2001                         //
2002                         // `a' is a generic type definition's TypeBuilder and `b' is a
2003                         // generic instance of the same type.
2004                         //
2005                         // Example:
2006                         //
2007                         // class Stack<T>
2008                         // {
2009                         //     void Test (Stack<T> stack) { }
2010                         // }
2011                         //
2012                         // The first argument of `Test' will be the generic instance
2013                         // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
2014                         //
2015                         //
2016                         // We hit this via Closure.Filter() for gen-82.cs.
2017                         //
2018                         if (type != parent.GetGenericTypeDefinition ())
2019                                 return false;
2020
2021                         return true;
2022                 }
2023
2024                 if (type.IsGenericInstance && parent.IsGenericInstance) {
2025                         Type tdef = type.GetGenericTypeDefinition ();
2026                         Type pdef = parent.GetGenericTypeDefinition ();
2027
2028                         if (type.GetGenericTypeDefinition () != parent.GetGenericTypeDefinition ())
2029                                 return false;
2030
2031                         return true;
2032                 }
2033
2034                 return false;
2035         }
2036
2037         public static bool IsFamilyAccessible (Type type, Type parent)
2038         {
2039                 TypeParameter tparam = LookupTypeParameter (type);
2040                 TypeParameter pparam = LookupTypeParameter (parent);
2041
2042                 if ((tparam != null) && (pparam != null)) {
2043                         if (tparam == pparam)
2044                                 return true;
2045
2046                         return tparam.IsSubclassOf (parent);
2047                 }
2048
2049                 do {
2050                         if (IsEqualGenericInstance (type, parent))
2051                                 return true;
2052
2053                         type = type.BaseType;
2054                 } while (type != null);
2055
2056                 return false;
2057         }
2058
2059         //
2060         // Checks whether `type' is a subclass or nested child of `parent'.
2061         //
2062         public static bool IsNestedFamilyAccessible (Type type, Type parent)
2063         {
2064                 do {
2065                         if (IsFamilyAccessible (type, parent))
2066                                 return true;
2067
2068                         // Handle nested types.
2069                         type = type.DeclaringType;
2070                 } while (type != null);
2071
2072                 return false;
2073         }
2074
2075         //
2076         // Checks whether `type' is a nested child of `parent'.
2077         //
2078         public static bool IsNestedChildOf (Type type, Type parent)
2079         {
2080                 if (IsEqual (type, parent))
2081                         return false;
2082
2083                 type = type.DeclaringType;
2084                 while (type != null) {
2085                         if (IsEqual (type, parent))
2086                                 return true;
2087
2088                         type = type.DeclaringType;
2089                 }
2090
2091                 return false;
2092         }
2093
2094         //
2095         // Do the right thing when returning the element type of an
2096         // array type based on whether we are compiling corlib or not
2097         //
2098         public static Type GetElementType (Type t)
2099         {
2100                 if (RootContext.StdLib)
2101                         return t.GetElementType ();
2102                 else
2103                         return TypeToCoreType (t.GetElementType ());
2104         }
2105
2106         /// <summary>
2107         ///   Returns the User Defined Types
2108         /// </summary>
2109         public static ArrayList UserTypes {
2110                 get {
2111                         return user_types;
2112                 }
2113         }
2114
2115         public static Hashtable TypeContainers {
2116                 get {
2117                         return typecontainers;
2118                 }
2119         }
2120
2121         static Hashtable builder_to_constant;
2122
2123         public static void RegisterConstant (FieldBuilder fb, Const c)
2124         {
2125                 if (builder_to_constant == null)
2126                         builder_to_constant = new PtrHashtable ();
2127
2128                 if (builder_to_constant.Contains (fb))
2129                         return;
2130
2131                 builder_to_constant.Add (fb, c);
2132         }
2133
2134         public static Const LookupConstant (FieldBuilder fb)
2135         {
2136                 if (builder_to_constant == null)
2137                         return null;
2138                 
2139                 return (Const) builder_to_constant [fb];
2140         }
2141         
2142         /// <summary>
2143         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
2144         /// </summary>
2145         ///
2146         /// <remarks>
2147         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
2148         ///   for anything which is dynamic, and we need this in a number of places,
2149         ///   we register this information here, and use it afterwards.
2150         /// </remarks>
2151         static public void RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
2152         {
2153                 if (args == null)
2154                         args = NoTypes;
2155                                 
2156                 method_arguments.Add (mb, args);
2157                 method_internal_params.Add (mb, ip);
2158         }
2159         
2160         static public InternalParameters LookupParametersByBuilder (MethodBase mb)
2161         {
2162                 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
2163                         return null;
2164                 
2165                 if (method_internal_params.Contains (mb))
2166                         return (InternalParameters) method_internal_params [mb];
2167                 else
2168                         throw new Exception ("Argument for Method not registered" + mb);
2169         }
2170
2171         /// <summary>
2172         ///    Returns the argument types for a method based on its methodbase
2173         ///
2174         ///    For dynamic methods, we use the compiler provided types, for
2175         ///    methods from existing assemblies we load them from GetParameters,
2176         ///    and insert them into the cache
2177         /// </summary>
2178         static public Type [] GetArgumentTypes (MethodBase mb)
2179         {
2180                 object t = method_arguments [mb];
2181                 if (t != null)
2182                         return (Type []) t;
2183
2184                         ParameterInfo [] pi = mb.GetParameters ();
2185                         int c = pi.Length;
2186                 Type [] types;
2187                         
2188                 if (c == 0) {
2189                         types = NoTypes;
2190                 } else {
2191                         types = new Type [c];
2192                         for (int i = 0; i < c; i++)
2193                                 types [i] = pi [i].ParameterType;
2194                 }
2195                         method_arguments.Add (mb, types);
2196                         return types;
2197                 }
2198
2199         /// <summary>
2200         ///    Returns the argument types for an indexer based on its PropertyInfo
2201         ///
2202         ///    For dynamic indexers, we use the compiler provided types, for
2203         ///    indexers from existing assemblies we load them from GetParameters,
2204         ///    and insert them into the cache
2205         /// </summary>
2206         static public Type [] GetArgumentTypes (PropertyInfo indexer)
2207         {
2208                 if (indexer_arguments.Contains (indexer))
2209                         return (Type []) indexer_arguments [indexer];
2210                 else if (indexer is PropertyBuilder)
2211                         // If we're a PropertyBuilder and not in the
2212                         // `indexer_arguments' hash, then we're a property and
2213                         // not an indexer.
2214                         return NoTypes;
2215                 else {
2216                         ParameterInfo [] pi = indexer.GetIndexParameters ();
2217                         // Property, not an indexer.
2218                         if (pi == null)
2219                                 return NoTypes;
2220                         int c = pi.Length;
2221                         Type [] types = new Type [c];
2222                         
2223                         for (int i = 0; i < c; i++)
2224                                 types [i] = pi [i].ParameterType;
2225
2226                         indexer_arguments.Add (indexer, types);
2227                         return types;
2228                 }
2229         }
2230         
2231         // <remarks>
2232         //  This is a workaround the fact that GetValue is not
2233         //  supported for dynamic types
2234         // </remarks>
2235         static Hashtable fields = new Hashtable ();
2236         static public bool RegisterFieldValue (FieldBuilder fb, object value)
2237         {
2238                 if (fields.Contains (fb))
2239                         return false;
2240
2241                 fields.Add (fb, value);
2242
2243                 return true;
2244         }
2245
2246         static public object GetValue (FieldBuilder fb)
2247         {
2248                 return fields [fb];
2249         }
2250
2251         static Hashtable fieldbuilders_to_fields = new Hashtable ();
2252         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
2253         {
2254                 if (fieldbuilders_to_fields.Contains (fb))
2255                         return false;
2256
2257                 fieldbuilders_to_fields.Add (fb, f);
2258                 return true;
2259         }
2260
2261         //
2262         // The return value can be null;  This will be the case for
2263         // auxiliary FieldBuilders created by the compiler that have no
2264         // real field being declared on the source code
2265         //
2266         static public FieldBase GetField (FieldInfo fb)
2267         {
2268                 return (FieldBase) fieldbuilders_to_fields [fb];
2269         }
2270         
2271         static Hashtable events;
2272
2273         static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
2274         {
2275                 if (events == null)
2276                         events = new Hashtable ();
2277
2278                 if (!events.Contains (eb)) {
2279                 events.Add (eb, new Pair (add, remove));
2280                 }
2281         }
2282
2283         static public MethodInfo GetAddMethod (EventInfo ei)
2284         {
2285                 if (ei is MyEventBuilder) {
2286                         Pair pair = (Pair) events [ei];
2287
2288                         return (MethodInfo) pair.First;
2289                 }
2290                 return ei.GetAddMethod (true);
2291         }
2292
2293         static public MethodInfo GetRemoveMethod (EventInfo ei)
2294         {
2295                 if (ei is MyEventBuilder) {
2296                         Pair pair = (Pair) events [ei];
2297
2298                         return (MethodInfo) pair.Second;
2299                 }
2300                 return ei.GetRemoveMethod (true);
2301         }
2302
2303         static Hashtable priv_fields_events;
2304
2305         static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
2306         {
2307                 if (priv_fields_events == null)
2308                         priv_fields_events = new Hashtable ();
2309
2310                 if (priv_fields_events.Contains (einfo))
2311                         return false;
2312
2313                 priv_fields_events.Add (einfo, builder);
2314
2315                 return true;
2316         }
2317
2318         static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
2319         {
2320                 if (priv_fields_events == null)
2321                         return null;
2322                 else
2323                         return (MemberInfo) priv_fields_events [ei];
2324         }
2325                 
2326         static Hashtable properties;
2327         
2328         static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
2329         {
2330                 if (properties == null)
2331                         properties = new Hashtable ();
2332
2333                 if (properties.Contains (pb))
2334                         return false;
2335
2336                 properties.Add (pb, new Pair (get, set));
2337
2338                 return true;
2339         }
2340
2341         static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
2342                                             MethodBase set, Type[] args)
2343         {
2344                 if (!RegisterProperty (pb, get,set))
2345                         return false;
2346
2347                 indexer_arguments.Add (pb, args);
2348
2349                 return true;
2350         }
2351
2352         public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
2353         {
2354                 Hashtable hash = new Hashtable ();
2355                 return CheckStructCycles (tc, seen, hash);
2356         }
2357
2358         public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
2359                                               Hashtable hash)
2360         {
2361                 if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
2362                         return true;
2363
2364                 //
2365                 // `seen' contains all types we've already visited.
2366                 //
2367                 if (seen.Contains (tc))
2368                         return true;
2369                 seen.Add (tc, null);
2370
2371                 if (tc.Fields == null)
2372                         return true;
2373
2374                 foreach (Field field in tc.Fields) {
2375                         if (field.FieldBuilder.IsStatic)
2376                                 continue;
2377
2378                         Type ftype = field.FieldBuilder.FieldType;
2379                         TypeContainer ftc = LookupTypeContainer (ftype);
2380                         if (ftc == null)
2381                                 continue;
2382
2383                         if (hash.Contains (ftc)) {
2384                                 Report.Error (523, tc.Location,
2385                                               "Struct member `{0}.{1}' of type `{2}' " +
2386                                               "causes a cycle in the struct layout",
2387                                               tc.Name, field.Name, ftc.Name);
2388                                 return false;
2389                         }
2390
2391                         //
2392                         // `hash' contains all types in the current path.
2393                         //
2394                         hash.Add (tc, null);
2395
2396                         bool ok = CheckStructCycles (ftc, seen, hash);
2397
2398                         hash.Remove (tc);
2399
2400                         if (!ok)
2401                                 return false;
2402
2403                         if (!seen.Contains (ftc))
2404                                 seen.Add (ftc, null);
2405                 }
2406
2407                 return true;
2408         }
2409
2410         /// <summary>
2411         ///   Given an array of interface types, expand and eliminate repeated ocurrences
2412         ///   of an interface.  
2413         /// </summary>
2414         ///
2415         /// <remarks>
2416         ///   This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
2417         ///   be IA, IB, IC.
2418         /// </remarks>
2419         public static Type[] ExpandInterfaces (EmitContext ec, TypeExpr [] base_interfaces)
2420         {
2421                 ArrayList new_ifaces = new ArrayList ();
2422                 
2423                 foreach (TypeExpr iface in base_interfaces){
2424                         TypeExpr texpr = iface.ResolveAsTypeTerminal (ec);
2425                         if (texpr == null)
2426                                 return null;
2427
2428                         if (!new_ifaces.Contains (texpr.Type))
2429                                 new_ifaces.Add (texpr.Type);
2430                         
2431                         Type [] implementing = texpr.Type.GetInterfaces ();
2432                         
2433                         foreach (Type imp in implementing){
2434                                 if (!new_ifaces.Contains (imp))
2435                                         new_ifaces.Add (imp);
2436                         }
2437                 }
2438                 Type [] ret = new Type [new_ifaces.Count];
2439                 new_ifaces.CopyTo (ret, 0);
2440                 return ret;
2441         }
2442                 
2443         static PtrHashtable iface_cache = new PtrHashtable ();
2444                 
2445         /// <summary>
2446         ///   This function returns the interfaces in the type `t'.  Works with
2447         ///   both types and TypeBuilders.
2448         /// </summary>
2449         public static Type [] GetInterfaces (Type t)
2450         {
2451                 
2452                 Type [] cached = iface_cache [t] as Type [];
2453                 if (cached != null)
2454                         return cached;
2455                 
2456                 //
2457                 // The reason for catching the Array case is that Reflection.Emit
2458                 // will not return a TypeBuilder for Array types of TypeBuilder types,
2459                 // but will still throw an exception if we try to call GetInterfaces
2460                 // on the type.
2461                 //
2462                 // Since the array interfaces are always constant, we return those for
2463                 // the System.Array
2464                 //
2465                 
2466                 if (t.IsArray)
2467                         t = TypeManager.array_type;
2468                 
2469                 if (t is TypeBuilder){
2470                         Type[] parent_ifaces;
2471                         
2472                         if (t.BaseType == null)
2473                                 parent_ifaces = NoTypes;
2474                         else
2475                                 parent_ifaces = GetInterfaces (t.BaseType);
2476                         Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2477                         if (type_ifaces == null)
2478                                 type_ifaces = NoTypes;
2479
2480                         int parent_count = parent_ifaces.Length;
2481                         Type[] result = new Type [parent_count + type_ifaces.Length];
2482                         parent_ifaces.CopyTo (result, 0);
2483                         type_ifaces.CopyTo (result, parent_count);
2484
2485                         iface_cache [t] = result;
2486                         return result;
2487                 } else if (t is GenericTypeParameterBuilder){
2488                         Type[] type_ifaces = (Type []) builder_to_ifaces [t];
2489                         if (type_ifaces == null)
2490                                 type_ifaces = NoTypes;
2491
2492                         iface_cache [t] = type_ifaces;
2493                         return type_ifaces;
2494                 } else {
2495                         Type[] ifaces = t.GetInterfaces ();
2496                         iface_cache [t] = ifaces;
2497                         return ifaces;
2498                 }
2499         }
2500         
2501         //
2502         // gets the interfaces that are declared explicitly on t
2503         //
2504         public static Type [] GetExplicitInterfaces (TypeBuilder t)
2505         {
2506                 return (Type []) builder_to_ifaces [t];
2507         }
2508         
2509         /// <remarks>
2510         ///  The following is used to check if a given type implements an interface.
2511         ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
2512         /// </remarks>
2513         public static bool ImplementsInterface (Type t, Type iface)
2514         {
2515                 Type [] interfaces;
2516
2517                 //
2518                 // FIXME OPTIMIZATION:
2519                 // as soon as we hit a non-TypeBuiler in the interface
2520                 // chain, we could return, as the `Type.GetInterfaces'
2521                 // will return all the interfaces implement by the type
2522                 // or its parents.
2523                 //
2524                 do {
2525                         interfaces = GetInterfaces (t);
2526
2527                         if (interfaces != null){
2528                                 foreach (Type i in interfaces){
2529                                         if (i == iface)
2530                                                 return true;
2531                                 }
2532                         }
2533                         
2534                         t = t.BaseType;
2535                 } while (t != null);
2536                 
2537                 return false;
2538         }
2539
2540         static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
2541
2542         // This is a custom version of Convert.ChangeType() which works
2543         // with the TypeBuilder defined types when compiling corlib.
2544         public static object ChangeType (object value, Type conversionType, out bool error)
2545         {
2546                 IConvertible convert_value = value as IConvertible;
2547                 
2548                 if (convert_value == null){
2549                         error = true;
2550                         return null;
2551                 }
2552                 
2553                 //
2554                 // We must use Type.Equals() here since `conversionType' is
2555                 // the TypeBuilder created version of a system type and not
2556                 // the system type itself.  You cannot use Type.GetTypeCode()
2557                 // on such a type - it'd always return TypeCode.Object.
2558                 //
2559                 error = false;
2560                 try {
2561                         if (conversionType.Equals (typeof (Boolean)))
2562                                 return (object)(convert_value.ToBoolean (nf_provider));
2563                         else if (conversionType.Equals (typeof (Byte)))
2564                                 return (object)(convert_value.ToByte (nf_provider));
2565                         else if (conversionType.Equals (typeof (Char)))
2566                                 return (object)(convert_value.ToChar (nf_provider));
2567                         else if (conversionType.Equals (typeof (DateTime)))
2568                                 return (object)(convert_value.ToDateTime (nf_provider));
2569                         else if (conversionType.Equals (typeof (Decimal)))
2570                                 return (object)(convert_value.ToDecimal (nf_provider));
2571                         else if (conversionType.Equals (typeof (Double)))
2572                                 return (object)(convert_value.ToDouble (nf_provider));
2573                         else if (conversionType.Equals (typeof (Int16)))
2574                                 return (object)(convert_value.ToInt16 (nf_provider));
2575                         else if (conversionType.Equals (typeof (Int32)))
2576                                 return (object)(convert_value.ToInt32 (nf_provider));
2577                         else if (conversionType.Equals (typeof (Int64)))
2578                                 return (object)(convert_value.ToInt64 (nf_provider));
2579                         else if (conversionType.Equals (typeof (SByte)))
2580                                 return (object)(convert_value.ToSByte (nf_provider));
2581                         else if (conversionType.Equals (typeof (Single)))
2582                                 return (object)(convert_value.ToSingle (nf_provider));
2583                         else if (conversionType.Equals (typeof (String)))
2584                                 return (object)(convert_value.ToString (nf_provider));
2585                         else if (conversionType.Equals (typeof (UInt16)))
2586                                 return (object)(convert_value.ToUInt16 (nf_provider));
2587                         else if (conversionType.Equals (typeof (UInt32)))
2588                                 return (object)(convert_value.ToUInt32 (nf_provider));
2589                         else if (conversionType.Equals (typeof (UInt64)))
2590                                 return (object)(convert_value.ToUInt64 (nf_provider));
2591                         else if (conversionType.Equals (typeof (Object)))
2592                                 return (object)(value);
2593                         else 
2594                                 error = true;
2595                 } catch {
2596                         error = true;
2597                 }
2598                 return null;
2599         }
2600
2601         //
2602         // This is needed, because enumerations from assemblies
2603         // do not report their underlyingtype, but they report
2604         // themselves
2605         //
2606         public static Type EnumToUnderlying (Type t)
2607         {
2608                 if (t == TypeManager.enum_type)
2609                         return t;
2610
2611                 t = t.UnderlyingSystemType;
2612                 if (!TypeManager.IsEnumType (t))
2613                         return t;
2614         
2615                 if (t is TypeBuilder) {
2616                         // slow path needed to compile corlib
2617                         if (t == TypeManager.bool_type ||
2618                                         t == TypeManager.byte_type ||
2619                                         t == TypeManager.sbyte_type ||
2620                                         t == TypeManager.char_type ||
2621                                         t == TypeManager.short_type ||
2622                                         t == TypeManager.ushort_type ||
2623                                         t == TypeManager.int32_type ||
2624                                         t == TypeManager.uint32_type ||
2625                                         t == TypeManager.int64_type ||
2626                                         t == TypeManager.uint64_type)
2627                                 return t;
2628                         throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
2629                 }
2630                 TypeCode tc = Type.GetTypeCode (t);
2631
2632                 switch (tc){
2633                 case TypeCode.Boolean:
2634                         return TypeManager.bool_type;
2635                 case TypeCode.Byte:
2636                         return TypeManager.byte_type;
2637                 case TypeCode.SByte:
2638                         return TypeManager.sbyte_type;
2639                 case TypeCode.Char:
2640                         return TypeManager.char_type;
2641                 case TypeCode.Int16:
2642                         return TypeManager.short_type;
2643                 case TypeCode.UInt16:
2644                         return TypeManager.ushort_type;
2645                 case TypeCode.Int32:
2646                         return TypeManager.int32_type;
2647                 case TypeCode.UInt32:
2648                         return TypeManager.uint32_type;
2649                 case TypeCode.Int64:
2650                         return TypeManager.int64_type;
2651                 case TypeCode.UInt64:
2652                         return TypeManager.uint64_type;
2653                 }
2654                 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
2655         }
2656
2657         //
2658         // When compiling corlib and called with one of the core types, return
2659         // the corresponding typebuilder for that type.
2660         //
2661         public static Type TypeToCoreType (Type t)
2662         {
2663                 if (RootContext.StdLib || (t is TypeBuilder))
2664                         return t;
2665
2666                 TypeCode tc = Type.GetTypeCode (t);
2667
2668                 switch (tc){
2669                 case TypeCode.Boolean:
2670                         return TypeManager.bool_type;
2671                 case TypeCode.Byte:
2672                         return TypeManager.byte_type;
2673                 case TypeCode.SByte:
2674                         return TypeManager.sbyte_type;
2675                 case TypeCode.Char:
2676                         return TypeManager.char_type;
2677                 case TypeCode.Int16:
2678                         return TypeManager.short_type;
2679                 case TypeCode.UInt16:
2680                         return TypeManager.ushort_type;
2681                 case TypeCode.Int32:
2682                         return TypeManager.int32_type;
2683                 case TypeCode.UInt32:
2684                         return TypeManager.uint32_type;
2685                 case TypeCode.Int64:
2686                         return TypeManager.int64_type;
2687                 case TypeCode.UInt64:
2688                         return TypeManager.uint64_type;
2689                 case TypeCode.Single:
2690                         return TypeManager.float_type;
2691                 case TypeCode.Double:
2692                         return TypeManager.double_type;
2693                 case TypeCode.String:
2694                         return TypeManager.string_type;
2695                 default:
2696                         if (t == typeof (void))
2697                                 return TypeManager.void_type;
2698                         if (t == typeof (object))
2699                                 return TypeManager.object_type;
2700                         if (t == typeof (System.Type))
2701                                 return TypeManager.type_type;
2702                         if (t == typeof (System.IntPtr))
2703                                 return TypeManager.intptr_type;
2704                         return t;
2705                 }
2706         }
2707
2708         /// <summary>
2709         ///   Utility function that can be used to probe whether a type
2710         ///   is managed or not.  
2711         /// </summary>
2712         public static bool VerifyUnManaged (Type t, Location loc)
2713         {
2714                 if (t.IsValueType || t.IsPointer){
2715                         //
2716                         // FIXME: this is more complex, we actually need to
2717                         // make sure that the type does not contain any
2718                         // classes itself
2719                         //
2720                         return true;
2721                 }
2722
2723                 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
2724                         // We need this explicit check here to make it work when
2725                         // compiling corlib.
2726                         return true;
2727
2728                 Report.Error (
2729                         208, loc,
2730                         "Cannot take the address or size of a variable of a managed type ('" +
2731                         CSharpName (t) + "')");
2732                 return false;   
2733         }
2734         
2735         /// <summary>
2736         ///   Returns the name of the indexer in a given type.
2737         /// </summary>
2738         /// <remarks>
2739         ///   The default is not always `Item'.  The user can change this behaviour by
2740         ///   using the IndexerNameAttribute in the container.
2741         ///
2742         ///   For example, the String class indexer is named `Chars' not `Item' 
2743         /// </remarks>
2744         public static string IndexerPropertyName (Type t)
2745         {
2746                 if (t.IsGenericInstance)
2747                         t = t.GetGenericTypeDefinition ();
2748
2749                 if (t is TypeBuilder) {
2750                         TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
2751                         return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
2752                 }
2753                 
2754                 System.Attribute attr = System.Attribute.GetCustomAttribute (
2755                         t, TypeManager.default_member_type);
2756                 if (attr != null){
2757                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
2758                         return dma.MemberName;
2759                 }
2760
2761                 return TypeContainer.DefaultIndexerName;
2762         }
2763
2764         static MethodInfo declare_local_method = null;
2765         
2766         public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
2767         {
2768                 if (declare_local_method == null){
2769                         declare_local_method = typeof (ILGenerator).GetMethod (
2770                                 "DeclareLocal",
2771                                 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
2772                                 null, 
2773                                 new Type [] { typeof (Type), typeof (bool)},
2774                                 null);
2775                         if (declare_local_method == null){
2776                                 Report.Warning (-24, new Location (-1),
2777                                                 "This version of the runtime does not support making pinned local variables.  " +
2778                                         "This code may cause errors on a runtime with a moving GC");
2779                                 return ig.DeclareLocal (t);
2780                         }
2781                 }
2782                 return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
2783         }
2784
2785         //
2786         // Returns whether the array of memberinfos contains the given method
2787         //
2788         public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
2789         {
2790                 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
2791                 
2792                 foreach (MethodBase method in array) {
2793                         if (method.Name != new_method.Name)
2794                                 continue;
2795
2796                         if (method is MethodInfo && new_method is MethodInfo)
2797                                 if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
2798                                         continue;
2799
2800                         
2801                         Type [] old_args = TypeManager.GetArgumentTypes (method);
2802                         int old_count = old_args.Length;
2803                         int i;
2804                         
2805                         if (new_args.Length != old_count)
2806                                 continue;
2807                         
2808                         for (i = 0; i < old_count; i++){
2809                                 if (old_args [i] != new_args [i])
2810                                         break;
2811                         }
2812                         if (i != old_count)
2813                                 continue;
2814
2815                         return true;
2816                 }
2817                 
2818                 return false;
2819         }
2820         
2821         //
2822         // We copy methods from `new_members' into `target_list' if the signature
2823         // for the method from in the new list does not exist in the target_list
2824         //
2825         // The name is assumed to be the same.
2826         //
2827         public static ArrayList CopyNewMethods (ArrayList target_list, IList new_members)
2828         {
2829                 if (target_list == null){
2830                         target_list = new ArrayList ();
2831
2832                         foreach (MemberInfo mi in new_members){
2833                                 if (mi is MethodBase)
2834                                         target_list.Add (mi);
2835                         }
2836                         return target_list;
2837                 }
2838                 
2839                 MemberInfo [] target_array = new MemberInfo [target_list.Count];
2840                 target_list.CopyTo (target_array, 0);
2841                 
2842                 foreach (MemberInfo mi in new_members){
2843                         MethodBase new_method = (MethodBase) mi;
2844                         
2845                         if (!ArrayContainsMethod (target_array, new_method))
2846                                 target_list.Add (new_method);
2847                 }
2848                 return target_list;
2849         }
2850
2851         static public bool IsGenericMethod (MethodBase mb)
2852         {
2853                 if (mb.DeclaringType is TypeBuilder) {
2854                         IMethodData method = (IMethodData) builder_to_method [mb];
2855                         if (method == null)
2856                                 return false;
2857
2858                         return method.GenericMethod != null;
2859                 }
2860
2861                 return mb.IsGenericMethodDefinition;
2862         }
2863         
2864 #region MemberLookup implementation
2865         
2866         //
2867         // Whether we allow private members in the result (since FindMembers
2868         // uses NonPublic for both protected and private), we need to distinguish.
2869         //
2870
2871         static internal bool FilterNone (MemberInfo m, object filter_criteria)
2872         {
2873                 return true;
2874         }
2875
2876         internal class Closure {
2877                 internal bool     private_ok;
2878
2879                 // Who is invoking us and which type is being queried currently.
2880                 internal Type     invocation_type;
2881                 internal Type     qualifier_type;
2882
2883                 // The assembly that defines the type is that is calling us
2884                 internal Assembly invocation_assembly;
2885                 internal IList almost_match;
2886
2887                 private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
2888                 {
2889                         if (invocation_type == null)
2890                                 return false;
2891
2892                         if (is_static)
2893                                 return true;
2894                         
2895                         // A nested class has access to all the protected members visible
2896                         // to its parent.
2897                         if (qualifier_type != null
2898                             && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2899                                 return true;
2900
2901                         if (invocation_type == m.DeclaringType
2902                             || invocation_type.IsSubclassOf (m.DeclaringType)) {
2903                                 // Although a derived class can access protected members of
2904                                 // its base class it cannot do so through an instance of the
2905                                 // base class (CS1540).
2906                                 // => Ancestry should be: declaring_type ->* invocation_type
2907                                 //      ->*  qualified_type
2908                                 if (qualifier_type == null
2909                                     || qualifier_type == invocation_type
2910                                     || qualifier_type.IsSubclassOf (invocation_type))
2911                                         return true;
2912                         }
2913         
2914                         if (almost_match != null)
2915                                 almost_match.Add (m);
2916                         return false;
2917                 }
2918
2919                 bool Filter (MethodBase mb, object filter_criteria)
2920                 {
2921                         MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
2922
2923                         if (ma == MethodAttributes.Private)
2924                                 return private_ok ||
2925                                         IsPrivateAccessible (invocation_type, mb.DeclaringType) ||
2926                                         IsNestedChildOf (invocation_type, mb.DeclaringType);
2927
2928                         //
2929                         // FamAndAssem requires that we not only derivate, but we are on the
2930                         // same assembly.  
2931                         //
2932                         if (ma == MethodAttributes.FamANDAssem){
2933                                 if (invocation_assembly != mb.DeclaringType.Assembly)
2934                                         return false;
2935                         }
2936
2937                         // Assembly and FamORAssem succeed if we're in the same assembly.
2938                         if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
2939                                 if (invocation_assembly == mb.DeclaringType.Assembly)
2940                                         return true;
2941                         }
2942
2943                         // We already know that we aren't in the same assembly.
2944                         if (ma == MethodAttributes.Assembly)
2945                                 return false;
2946
2947                         // Family and FamANDAssem require that we derive.
2948                         if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
2949                                 if (invocation_type == null)
2950                                         return false;
2951
2952                                 if (!IsNestedFamilyAccessible (invocation_type, mb.DeclaringType))
2953                                         return false;
2954
2955                                 // Although a derived class can access protected members of its base class
2956                                 // it cannot do so through an instance of the base class (CS1540).
2957                                 if (!mb.IsStatic && (qualifier_type != null) &&
2958                                     !IsEqualGenericInstance (invocation_type, qualifier_type) &&
2959                                     TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
2960                                     !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
2961                                         return false;
2962
2963                                 return true;
2964                         }
2965
2966                         // Public.
2967                         return true;
2968                 }
2969
2970                 bool Filter (FieldInfo fi, object filter_criteria)
2971                 {
2972                         FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
2973
2974                         if (fa == FieldAttributes.Private)
2975                                 return private_ok ||
2976                                         IsPrivateAccessible (invocation_type, fi.DeclaringType) ||
2977                                         IsNestedChildOf (invocation_type, fi.DeclaringType);
2978
2979                         //
2980                         // FamAndAssem requires that we not only derivate, but we are on the
2981                         // same assembly.  
2982                         //
2983                         if (fa == FieldAttributes.FamANDAssem){
2984                                 if (invocation_assembly != fi.DeclaringType.Assembly)
2985                                         return false;
2986                         }
2987
2988                         // Assembly and FamORAssem succeed if we're in the same assembly.
2989                         if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
2990                                 if (invocation_assembly == fi.DeclaringType.Assembly)
2991                                         return true;
2992                         }
2993
2994                         // We already know that we aren't in the same assembly.
2995                         if (fa == FieldAttributes.Assembly)
2996                                 return false;
2997
2998                         // Family and FamANDAssem require that we derive.
2999                         if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
3000                                 if (invocation_type == null)
3001                                         return false;
3002
3003                                 if (!IsNestedFamilyAccessible (invocation_type, fi.DeclaringType))
3004                                         return false;
3005
3006                                 // Although a derived class can access protected members of its base class
3007                                 // it cannot do so through an instance of the base class (CS1540).
3008                                 if (!fi.IsStatic && (qualifier_type != null) &&
3009                                     !IsEqualGenericInstance (invocation_type, qualifier_type) &&
3010                                     TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
3011                                     !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
3012                                         return false;
3013
3014                                 return true;
3015                         }
3016
3017                         // Public.
3018                         return true;
3019                 }
3020                 
3021                 //
3022                 // This filter filters by name + whether it is ok to include private
3023                 // members in the search
3024                 //
3025                 internal bool Filter (MemberInfo m, object filter_criteria)
3026                 {
3027                         //
3028                         // Hack: we know that the filter criteria will always be in the
3029                         // `closure' // fields. 
3030                         //
3031
3032                         if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
3033                                 return false;
3034
3035                         if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
3036                             (invocation_type != null) &&
3037                             IsPrivateAccessible (m.DeclaringType, invocation_type))
3038                                 return true;
3039
3040                         //
3041                         // Ugly: we need to find out the type of `m', and depending
3042                         // on this, tell whether we accept or not
3043                         //
3044                         if (m is MethodBase)
3045                                 return Filter ((MethodBase) m, filter_criteria);
3046
3047                         if (m is FieldInfo)
3048                                 return Filter ((FieldInfo) m, filter_criteria);
3049
3050                         //
3051                         // EventInfos and PropertyInfos, return true because they lack
3052                         // permission information, so we need to check later on the methods.
3053                         //
3054                         return true;
3055                 }
3056         }
3057
3058         static Closure closure = new Closure ();
3059         static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
3060
3061         //
3062         // Looks up a member called `name' in the `queried_type'.  This lookup
3063         // is done by code that is contained in the definition for `invocation_type'
3064         // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
3065         //
3066         // `invocation_type' is used to check whether we're allowed to access the requested
3067         // member wrt its protection level.
3068         //
3069         // When called from MemberAccess, `qualifier_type' is the type which is used to access
3070         // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
3071         // is B and qualifier_type is A).  This is used to do the CS1540 check.
3072         //
3073         // When resolving a SimpleName, `qualifier_type' is null.
3074         //
3075         // The `qualifier_type' is used for the CS1540 check; it's normally either null or
3076         // the same than `queried_type' - except when we're being called from BaseAccess;
3077         // in this case, `invocation_type' is the current type and `queried_type' the base
3078         // type, so this'd normally trigger a CS1540.
3079         //
3080         // The binding flags are `bf' and the kind of members being looked up are `mt'
3081         //
3082         // The return value always includes private members which code in `invocation_type'
3083         // is allowed to access (using the specified `qualifier_type' if given); only use
3084         // BindingFlags.NonPublic to bypass the permission check.
3085         //
3086         // The 'almost_match' argument is used for reporting error CS1540.
3087         //
3088         // Returns an array of a single element for everything but Methods/Constructors
3089         // that might return multiple matches.
3090         //
3091         public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
3092                                                   Type queried_type, MemberTypes mt,
3093                                                   BindingFlags original_bf, string name, IList almost_match)
3094         {
3095                 Timer.StartTimer (TimerType.MemberLookup);
3096
3097                 MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
3098                                                         queried_type, mt, original_bf, name, almost_match);
3099
3100                 Timer.StopTimer (TimerType.MemberLookup);
3101
3102                 return retval;
3103         }
3104
3105         static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
3106                                                Type queried_type, MemberTypes mt,
3107                                                BindingFlags original_bf, string name, IList almost_match)
3108         {
3109                 BindingFlags bf = original_bf;
3110                 
3111                 ArrayList method_list = null;
3112                 Type current_type = queried_type;
3113                 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
3114                 bool skip_iface_check = true, used_cache = false;
3115                 bool always_ok_flag = false;
3116
3117                 closure.invocation_type = invocation_type;
3118                 closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
3119                 closure.qualifier_type = qualifier_type;
3120                 closure.almost_match = almost_match;
3121
3122                 //
3123                 // If we are a nested class, we always have access to our container
3124                 // type names
3125                 //
3126                 if (invocation_type != null){
3127                         string invocation_name = invocation_type.FullName;
3128                         if ((invocation_name != null) && (invocation_name.IndexOf ('+') != -1)){
3129                                 string container = queried_type.FullName + "+";
3130                                 int container_length = container.Length;
3131
3132                                 if (invocation_name.Length > container_length){
3133                                         string shared = invocation_name.Substring (0, container_length);
3134                                 
3135                                         if (shared == container)
3136                                                 always_ok_flag = true;
3137                                 }
3138                         }
3139                 }
3140                 
3141                 // This is from the first time we find a method
3142                 // in most cases, we do not actually find a method in the base class
3143                 // so we can just ignore it, and save the arraylist allocation
3144                 MemberInfo [] first_members_list = null;
3145                 bool use_first_members_list = false;
3146                 
3147                 do {
3148                         MemberInfo [] list;
3149
3150                         //
3151                         // `NonPublic' is lame, because it includes both protected and
3152                         // private methods, so we need to control this behavior by
3153                         // explicitly tracking if a private method is ok or not.
3154                         //
3155                         // The possible cases are:
3156                         //    public, private and protected (internal does not come into the
3157                         //    equation)
3158                         //
3159                         if ((invocation_type != null) &&
3160                             ((invocation_type == current_type) ||
3161                              IsNestedChildOf (invocation_type, current_type)) ||
3162                             always_ok_flag)
3163                                 bf = original_bf | BindingFlags.NonPublic;
3164                         else
3165                                 bf = original_bf;
3166
3167                         closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
3168
3169                         Timer.StopTimer (TimerType.MemberLookup);
3170
3171                         list = MemberLookup_FindMembers (
3172                                 current_type, mt, bf, name, out used_cache);
3173
3174                         Timer.StartTimer (TimerType.MemberLookup);
3175
3176                         //
3177                         // When queried for an interface type, the cache will automatically check all
3178                         // inherited members, so we don't need to do this here.  However, this only
3179                         // works if we already used the cache in the first iteration of this loop.
3180                         //
3181                         // If we used the cache in any further iteration, we can still terminate the
3182                         // loop since the cache always looks in all parent classes.
3183                         //
3184
3185                         if (used_cache)
3186                                 searching = false;
3187                         else
3188                                 skip_iface_check = false;
3189
3190                         if (current_type == TypeManager.object_type)
3191                                 searching = false;
3192                         else {
3193                                 current_type = current_type.BaseType;
3194                                 
3195                                 //
3196                                 // This happens with interfaces, they have a null
3197                                 // basetype.  Look members up in the Object class.
3198                                 //
3199                                 if (current_type == null) {
3200                                         current_type = TypeManager.object_type;
3201                                         searching = true;
3202                                 }
3203                         }
3204                         
3205                         if (list.Length == 0)
3206                                 continue;
3207
3208                         //
3209                         // Events and types are returned by both `static' and `instance'
3210                         // searches, which means that our above FindMembers will
3211                         // return two copies of the same.
3212                         //
3213                         if (list.Length == 1 && !(list [0] is MethodBase)){
3214                                 return list;
3215                         }
3216
3217                         //
3218                         // Multiple properties: we query those just to find out the indexer
3219                         // name
3220                         //
3221                         if (list [0] is PropertyInfo)
3222                                 return list;
3223
3224                         //
3225                         // We found an event: the cache lookup returns both the event and
3226                         // its private field.
3227                         //
3228                         if (list [0] is EventInfo) {
3229                                 if ((list.Length == 2) && (list [1] is FieldInfo))
3230                                         return new MemberInfo [] { list [0] };
3231
3232                                 // Oooops
3233                                 return null;
3234                         }
3235
3236                         //
3237                         // We found methods, turn the search into "method scan"
3238                         // mode.
3239                         //
3240
3241                         if (first_members_list != null) {
3242                                 if (use_first_members_list) {
3243                                         method_list = CopyNewMethods (method_list, first_members_list);
3244                                         use_first_members_list = false;
3245                                 }
3246                                 
3247                                 method_list = CopyNewMethods (method_list, list);
3248                         } else {
3249                                 first_members_list = list;
3250                                 use_first_members_list = true;
3251
3252                                 mt &= (MemberTypes.Method | MemberTypes.Constructor);
3253                         }
3254                 } while (searching);
3255
3256                 if (use_first_members_list) {
3257                         foreach (MemberInfo mi in first_members_list) {
3258                                 if (! (mi is MethodBase)) {
3259                                         method_list = CopyNewMethods (method_list, first_members_list);
3260                                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3261                                 }
3262                         }
3263                         return (MemberInfo []) first_members_list;
3264                 }
3265
3266                 if (method_list != null && method_list.Count > 0) {
3267                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
3268                 }
3269                 //
3270                 // This happens if we already used the cache in the first iteration, in this case
3271                 // the cache already looked in all interfaces.
3272                 //
3273                 if (skip_iface_check)
3274                         return null;
3275
3276                 //
3277                 // Interfaces do not list members they inherit, so we have to
3278                 // scan those.
3279                 // 
3280                 if (!queried_type.IsInterface)
3281                         return null;
3282
3283                 if (queried_type.IsArray)
3284                         queried_type = TypeManager.array_type;
3285                 
3286                 Type [] ifaces = GetInterfaces (queried_type);
3287                 if (ifaces == null)
3288                         return null;
3289                 
3290                 foreach (Type itype in ifaces){
3291                         MemberInfo [] x;
3292
3293                         x = MemberLookup (null, null, itype, mt, bf, name, null);
3294                         if (x != null)
3295                                 return x;
3296                 }
3297                                         
3298                 return null;
3299         }
3300
3301         // Tests whether external method is really special
3302         public static bool IsSpecialMethod (MethodBase mb)
3303         {
3304                 string name = mb.Name;
3305                 if (name.StartsWith ("get_") || name.StartsWith ("set_"))
3306                         return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
3307                                 
3308                 if (name.StartsWith ("add_"))
3309                         return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
3310
3311                 if (name.StartsWith ("remove_"))
3312                         return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
3313
3314                 if (name.StartsWith ("op_")){
3315                         foreach (string oname in Unary.oper_names) {
3316                                 if (oname == name)
3317                                         return true;
3318                         }
3319
3320                         foreach (string oname in Binary.oper_names) {
3321                                 if (oname == name)
3322                                         return true;
3323                         }
3324                 }
3325                 return false;
3326         }
3327                 
3328 #endregion
3329         
3330 }
3331
3332 /// <summary>
3333 ///   There is exactly one instance of this class per type.
3334 /// </summary>
3335 public sealed class TypeHandle : IMemberContainer {
3336         public readonly TypeHandle BaseType;
3337
3338         readonly int id = ++next_id;
3339         static int next_id = 0;
3340
3341         /// <summary>
3342         ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
3343         ///   a TypeHandle yet, a new instance of it is created.  This static method
3344         ///   ensures that we'll only have one TypeHandle instance per type.
3345         /// </summary>
3346         private static TypeHandle GetTypeHandle (Type t)
3347         {
3348                 TypeHandle handle = (TypeHandle) type_hash [t];
3349                 if (handle != null)
3350                         return handle;
3351
3352                 handle = new TypeHandle (t);
3353                 type_hash.Add (t, handle);
3354                 return handle;
3355         }
3356
3357         public static MemberCache GetMemberCache (Type t)
3358         {
3359                 return GetTypeHandle (t).MemberCache;
3360         }
3361         
3362         public static void CleanUp ()
3363         {
3364                 type_hash = null;
3365         }
3366
3367         /// <summary>
3368         ///   Returns the TypeHandle for TypeManager.object_type.
3369         /// </summary>
3370         public static IMemberContainer ObjectType {
3371                 get {
3372                         if (object_type != null)
3373                                 return object_type;
3374
3375                         object_type = GetTypeHandle (TypeManager.object_type);
3376
3377                         return object_type;
3378                 }
3379         }
3380
3381         /// <summary>
3382         ///   Returns the TypeHandle for TypeManager.array_type.
3383         /// </summary>
3384         public static IMemberContainer ArrayType {
3385                 get {
3386                         if (array_type != null)
3387                                 return array_type;
3388
3389                         array_type = GetTypeHandle (TypeManager.array_type);
3390
3391                         return array_type;
3392                 }
3393         }
3394
3395         private static PtrHashtable type_hash = new PtrHashtable ();
3396
3397         private static TypeHandle object_type = null;
3398         private static TypeHandle array_type = null;
3399
3400         private Type type;
3401         private string full_name;
3402         private bool is_interface;
3403         private MemberCache member_cache;
3404         private MemberCache parent_cache;
3405
3406         private TypeHandle (Type type)
3407         {
3408                 this.type = type;
3409                 full_name = type.FullName != null ? type.FullName : type.Name;
3410                 if (type.BaseType != null) {
3411                         BaseType = GetTypeHandle (type.BaseType);
3412                         parent_cache = BaseType.MemberCache;
3413                 } else if (type.IsInterface)
3414                         parent_cache = TypeManager.LookupParentInterfacesCache (type);
3415                 this.is_interface = type.IsInterface || type.IsGenericParameter;
3416                 this.member_cache = new MemberCache (this);
3417         }
3418
3419         // IMemberContainer methods
3420
3421         public string Name {
3422                 get {
3423                         return full_name;
3424                 }
3425         }
3426
3427         public Type Type {
3428                 get {
3429                         return type;
3430                 }
3431         }
3432
3433         public MemberCache ParentCache {
3434                 get {
3435                         return parent_cache;
3436                 }
3437         }
3438
3439         public bool IsInterface {
3440                 get {
3441                         return is_interface;
3442                 }
3443         }
3444
3445         public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
3446         {
3447                 MemberInfo [] members;
3448                 if (type is GenericTypeParameterBuilder)
3449                         return MemberList.Empty;
3450                 if (mt == MemberTypes.Event)
3451                         members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
3452                 else
3453                         members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
3454                                                     null, null);
3455                 Array.Reverse (members);
3456
3457                 return new MemberList (members);
3458         }
3459
3460         // IMemberFinder methods
3461
3462         public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
3463                                        MemberFilter filter, object criteria)
3464         {
3465                 return new MemberList (member_cache.FindMembers (mt, bf, name, filter, criteria));
3466         }
3467
3468         public MemberCache MemberCache {
3469                 get {
3470                         return member_cache;
3471                 }
3472         }
3473
3474         public override string ToString ()
3475         {
3476                 if (BaseType != null)
3477                         return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
3478                 else
3479                         return "TypeHandle (" + id + "," + Name + ")";
3480         }
3481 }
3482
3483 }