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