2002-08-20 Martin Baulig <martin@gnome.org>
[mono.git] / mcs / mcs / 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 using System;
13 using System.Globalization;
14 using System.Collections;
15 using System.Reflection;
16 using System.Reflection.Emit;
17 using System.Text.RegularExpressions;
18 using System.Runtime.CompilerServices;
19 using System.Diagnostics;
20
21 namespace Mono.CSharp {
22
23 public class TypeManager {
24         //
25         // A list of core types that the compiler requires or uses
26         //
27         static public Type object_type;
28         static public Type value_type;
29         static public Type string_type;
30         static public Type int32_type;
31         static public Type uint32_type;
32         static public Type int64_type;
33         static public Type uint64_type;
34         static public Type float_type;
35         static public Type double_type;
36         static public Type char_type;
37         static public Type char_ptr_type;
38         static public Type short_type;
39         static public Type decimal_type;
40         static public Type bool_type;
41         static public Type sbyte_type;
42         static public Type byte_type;
43         static public Type ushort_type;
44         static public Type enum_type;
45         static public Type delegate_type;
46         static public Type multicast_delegate_type;
47         static public Type void_type;
48         static public Type enumeration_type;
49         static public Type array_type;
50         static public Type runtime_handle_type;
51         static public Type icloneable_type;
52         static public Type type_type;
53         static public Type ienumerator_type;
54         static public Type idisposable_type;
55         static public Type default_member_type;
56         static public Type iasyncresult_type;
57         static public Type asynccallback_type;
58         static public Type intptr_type;
59         static public Type monitor_type;
60         static public Type runtime_field_handle_type;
61         static public Type attribute_type;
62         static public Type attribute_usage_type;
63         static public Type dllimport_type;
64         static public Type unverifiable_code_type;
65         static public Type methodimpl_attr_type;
66         static public Type marshal_as_attr_type;
67         static public Type param_array_type;
68         static public Type void_ptr_type;
69         static public Type indexer_name_type;
70         static public Type exception_type;
71         static public object obsolete_attribute_type;
72         static public object conditional_attribute_type;
73
74         //
75         // An empty array of types
76         //
77         static public Type [] NoTypes;
78
79
80         // 
81         // Expressions representing the internal types.  Used during declaration
82         // definition.
83         //
84         static public Expression system_object_expr, system_string_expr; 
85         static public Expression system_boolean_expr, system_decimal_expr;
86         static public Expression system_single_expr, system_double_expr;
87         static public Expression system_sbyte_expr, system_byte_expr;
88         static public Expression system_int16_expr, system_uint16_expr;
89         static public Expression system_int32_expr, system_uint32_expr;
90         static public Expression system_int64_expr, system_uint64_expr;
91         static public Expression system_char_expr, system_void_expr;
92         static public Expression system_asynccallback_expr;
93         static public Expression system_iasyncresult_expr;
94
95         //
96         // This is only used when compiling corlib
97         //
98         static public Type system_int32_type;
99         static public Type system_array_type;
100         static public Type system_type_type;
101         static public Type system_assemblybuilder_type;
102         static public MethodInfo system_int_array_get_length;
103         static public MethodInfo system_int_array_get_rank;
104         static public MethodInfo system_object_array_clone;
105         static public MethodInfo system_int_array_get_length_int;
106         static public MethodInfo system_int_array_get_lower_bound_int;
107         static public MethodInfo system_int_array_get_upper_bound_int;
108         static public MethodInfo system_void_array_copyto_array_int;
109         static public MethodInfo system_void_set_corlib_type_builders;
110
111         
112         //
113         // Internal, not really used outside
114         //
115         static Type runtime_helpers_type;
116         
117         //
118         // These methods are called by code generated by the compiler
119         //
120         static public MethodInfo string_concat_string_string;
121         static public MethodInfo string_concat_object_object;
122         static public MethodInfo string_isinterneted_string;
123         static public MethodInfo system_type_get_type_from_handle;
124         static public MethodInfo object_getcurrent_void;
125         static public MethodInfo bool_movenext_void;
126         static public MethodInfo void_dispose_void;
127         static public MethodInfo void_monitor_enter_object;
128         static public MethodInfo void_monitor_exit_object;
129         static public MethodInfo void_initializearray_array_fieldhandle;
130         static public MethodInfo int_getlength_int;
131         static public MethodInfo delegate_combine_delegate_delegate;
132         static public MethodInfo delegate_remove_delegate_delegate;
133         static public MethodInfo int_get_offset_to_string_data;
134         static public MethodInfo int_array_get_length;
135         static public MethodInfo int_array_get_rank;
136         static public MethodInfo object_array_clone;
137         static public MethodInfo int_array_get_length_int;
138         static public MethodInfo int_array_get_lower_bound_int;
139         static public MethodInfo int_array_get_upper_bound_int;
140         static public MethodInfo void_array_copyto_array_int;
141         
142         //
143         // The attribute constructors.
144         //
145         static public ConstructorInfo cons_param_array_attribute;
146         static public ConstructorInfo void_decimal_ctor_five_args;
147         static public ConstructorInfo unverifiable_code_ctor;
148         
149         // <remarks>
150         //   Holds the Array of Assemblies that have been loaded
151         //   (either because it is the default or the user used the
152         //   -r command line option)
153         // </remarks>
154         static Assembly [] assemblies;
155
156         // <remarks>
157         //  Keeps a list of module builders. We used this to do lookups
158         //  on the modulebuilder using GetType -- needed for arrays
159         // </remarks>
160         static ModuleBuilder [] modules;
161
162         // <remarks>
163         //   This is the type_cache from the assemblies to avoid
164         //   hitting System.Reflection on every lookup.
165         // </summary>
166         static Hashtable types;
167
168         // <remarks>
169         //  This is used to hotld the corresponding TypeContainer objects
170         //  since we need this in FindMembers
171         // </remarks>
172         static Hashtable typecontainers;
173
174         // <remarks>
175         //   Keeps track of those types that are defined by the
176         //   user's program
177         // </remarks>
178         static ArrayList user_types;
179
180         static PtrHashtable builder_to_declspace;
181
182         // <remarks>
183         //   Tracks the interfaces implemented by typebuilders.  We only
184         //   enter those who do implement or or more interfaces
185         // </remarks>
186         static PtrHashtable builder_to_ifaces;
187
188         // <remarks>
189         //   Maps MethodBase.RuntimeTypeHandle to a Type array that contains
190         //   the arguments to the method
191         // </remarks>
192         static Hashtable method_arguments;
193
194         // <remarks>
195         //   Maps PropertyBuilder to a Type array that contains
196         //   the arguments to the indexer
197         // </remarks>
198         static Hashtable indexer_arguments;
199
200         // <remarks>
201         //   Maybe `method_arguments' should be replaced and only
202         //   method_internal_params should be kept?
203         // <remarks>
204         static Hashtable method_internal_params;
205
206         // <remarks>
207         //  Keeps track of attribute types
208         // </remarks>
209
210         static Hashtable builder_to_attr;
211
212         // <remarks>
213         //  Keeps track of methods
214         // </remarks>
215
216         static Hashtable builder_to_method;
217
218         struct Signature {
219                 public string name;
220                 public Type [] args;
221         }
222
223         /// <summary>
224         ///   A filter for Findmembers that uses the Signature object to
225         ///   extract objects
226         /// </summary>
227         static bool SignatureFilter (MemberInfo mi, object criteria)
228         {
229                 Signature sig = (Signature) criteria;
230
231                 if (!(mi is MethodBase))
232                         return false;
233                 
234                 if (mi.Name != sig.name)
235                         return false;
236
237                 int count = sig.args.Length;
238                 
239                 if (mi is MethodBuilder || mi is ConstructorBuilder){
240                         Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
241
242                         if (candidate_args.Length != count)
243                                 return false;
244                         
245                         for (int i = 0; i < count; i++)
246                                 if (candidate_args [i] != sig.args [i])
247                                         return false;
248                         
249                         return true;
250                 } else {
251                         ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
252
253                         if (pars.Length != count)
254                                 return false;
255
256                         for (int i = 0; i < count; i++)
257                                 if (pars [i].ParameterType != sig.args [i])
258                                         return false;
259                         return true;
260                 }
261         }
262
263         // A delegate that points to the filter above.
264         static MemberFilter signature_filter;
265
266         //
267         // These are expressions that represent some of the internal data types, used
268         // elsewhere
269         //
270         static void InitExpressionTypes ()
271         {
272                 system_object_expr  = new TypeLookupExpression ("System.Object");
273                 system_string_expr  = new TypeLookupExpression ("System.String");
274                 system_boolean_expr = new TypeLookupExpression ("System.Boolean");
275                 system_decimal_expr = new TypeLookupExpression ("System.Decimal");
276                 system_single_expr  = new TypeLookupExpression ("System.Single");
277                 system_double_expr  = new TypeLookupExpression ("System.Double");
278                 system_sbyte_expr   = new TypeLookupExpression ("System.SByte");
279                 system_byte_expr    = new TypeLookupExpression ("System.Byte");
280                 system_int16_expr   = new TypeLookupExpression ("System.Int16");
281                 system_uint16_expr  = new TypeLookupExpression ("System.UInt16");
282                 system_int32_expr   = new TypeLookupExpression ("System.Int32");
283                 system_uint32_expr  = new TypeLookupExpression ("System.UInt32");
284                 system_int64_expr   = new TypeLookupExpression ("System.Int64");
285                 system_uint64_expr  = new TypeLookupExpression ("System.UInt64");
286                 system_char_expr    = new TypeLookupExpression ("System.Char");
287                 system_void_expr    = new TypeLookupExpression ("System.Void");
288                 system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
289                 system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
290         }
291         
292         static TypeManager ()
293         {
294                 assemblies = new Assembly [0];
295                 modules = null;
296                 user_types = new ArrayList ();
297                 
298                 types = new Hashtable ();
299                 typecontainers = new Hashtable ();
300                 
301                 builder_to_declspace = new PtrHashtable ();
302                 builder_to_attr = new PtrHashtable ();
303                 builder_to_method = new PtrHashtable ();
304                 method_arguments = new PtrHashtable ();
305                 method_internal_params = new PtrHashtable ();
306                 indexer_arguments = new PtrHashtable ();
307                 builder_to_ifaces = new PtrHashtable ();
308                 
309                 NoTypes = new Type [0];
310
311                 signature_filter = new MemberFilter (SignatureFilter);
312                 InitExpressionTypes ();
313         }
314
315         public static void AddUserType (string name, TypeBuilder t, Type [] ifaces)
316         {
317                 try {
318                         types.Add (name, t);
319                 } catch {
320                         Type prev = (Type) types [name];
321                         TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
322
323                         if (tc != null){
324                                 //
325                                 // This probably never happens, as we catch this before
326                                 //
327                                 Report.Error (-17, "The type `" + name + "' has already been defined.");
328                                 return;
329                         }
330
331                         tc = builder_to_declspace [t] as TypeContainer;
332                         
333                         Report.Warning (
334                                 1595, "The type `" + name + "' is defined in an existing assembly;"+
335                                 " Using the new definition from: " + tc.Location);
336                         Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
337                         
338                         types.Remove (name);
339                         types.Add (name, t);
340                 }
341                 user_types.Add (t);
342                         
343                 if (ifaces != null)
344                         builder_to_ifaces [t] = ifaces;
345         }
346
347         //
348         // This entry point is used by types that we define under the covers
349         // 
350         public static void RegisterBuilder (TypeBuilder tb, Type [] ifaces)
351         {
352                 if (ifaces != null)
353                         builder_to_ifaces [tb] = ifaces;
354         }
355         
356         public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, Type [] ifaces)
357         {
358                 builder_to_declspace.Add (t, tc);
359                 typecontainers.Add (name, tc);
360                 AddUserType (name, t, ifaces);
361         }
362
363         public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
364         {
365                 types.Add (name, t);
366                 builder_to_declspace.Add (t, del);
367         }
368         
369         public static void AddEnumType (string name, TypeBuilder t, Enum en)
370         {
371                 types.Add (name, t);
372                 builder_to_declspace.Add (t, en);
373         }
374
375         public static void AddUserInterface (string name, TypeBuilder t, Interface i, Type [] ifaces)
376         {
377                 AddUserType (name, t, ifaces);
378                 builder_to_declspace.Add (t, i);
379         }
380
381         public static void AddMethod (MethodBuilder builder, MethodData method)
382         {
383                 builder_to_method.Add (builder, method);
384         }
385
386         public static void RegisterAttrType (Type t, TypeContainer tc)
387         {
388                 builder_to_attr.Add (t, tc);
389         }
390
391         /// <summary>
392         ///   Returns the TypeContainer whose Type is `t' or null if there is no
393         ///   TypeContainer for `t' (ie, the Type comes from a library)
394         /// </summary>
395         public static TypeContainer LookupTypeContainer (Type t)
396         {
397                 return builder_to_declspace [t] as TypeContainer;
398         }
399
400         public static IMemberContainer LookupMemberContainer (Type t)
401         {
402                 if (t is TypeBuilder) {
403                         IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
404                         if (container != null)
405                                 return container;
406                 }
407
408                 return TypeHandle.GetTypeHandle (t);
409         }
410
411         public static Interface LookupInterface (Type t)
412         {
413                 return builder_to_declspace [t] as Interface;
414         }
415
416         public static Delegate LookupDelegate (Type t)
417         {
418                 return builder_to_declspace [t] as Delegate;
419         }
420
421         public static Enum LookupEnum (Type t)
422         {
423                 return builder_to_declspace [t] as Enum;
424         }
425         
426         public static TypeContainer LookupAttr (Type t)
427         {
428                 return (TypeContainer) builder_to_attr [t];
429         }
430         
431         /// <summary>
432         ///   Registers an assembly to load types from.
433         /// </summary>
434         public static void AddAssembly (Assembly a)
435         {
436                 int top = assemblies.Length;
437                 Assembly [] n = new Assembly [top + 1];
438
439                 assemblies.CopyTo (n, 0);
440                 
441                 n [top] = a;
442                 assemblies = n;
443         }
444
445         /// <summary>
446         ///  Registers a module builder to lookup types from
447         /// </summary>
448         public static void AddModule (ModuleBuilder mb)
449         {
450                 int top = modules != null ? modules.Length : 0;
451                 ModuleBuilder [] n = new ModuleBuilder [top + 1];
452
453                 if (modules != null)
454                         modules.CopyTo (n, 0);
455                 n [top] = mb;
456                 modules = n;
457         }
458
459         /// <summary>
460         ///   Returns the Type associated with @name
461         /// </summary>
462         public static Type LookupType (string name)
463         {
464                 Type t;
465
466                 //
467                 // First lookup in user defined and cached values
468                 //
469
470                 t = (Type) types [name];
471                 if (t != null)
472                         return t;
473
474                 foreach (Assembly a in assemblies){
475                         t = a.GetType (name);
476                         if (t != null){
477                                 types [name] = t;
478
479                                 return t;
480                         }
481                 }
482
483                 foreach (ModuleBuilder mb in modules) {
484                         t = mb.GetType (name);
485                         if (t != null) {
486                                 types [name] = t;
487                                 return t;
488                         }
489                 }
490                 
491                 return null;
492         }
493
494         /// <summary>
495         ///   Returns the C# name of a type if possible, or the full type name otherwise
496         /// </summary>
497         static public string CSharpName (Type t)
498         {
499                 return Regex.Replace (t.FullName, 
500                         @"^System\." +
501                         @"(Int32|UInt32|Int16|Uint16|Int64|UInt64|" +
502                         @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
503                         @"Boolean|String|Void)" +
504                         @"(\W+|\b)", 
505                         new MatchEvaluator (CSharpNameMatch));
506         }       
507         
508         static String CSharpNameMatch (Match match) 
509         {
510                 string s = match.Groups [1].Captures [0].Value;
511                 return s.ToLower ().
512                 Replace ("int32", "int").
513                 Replace ("uint32", "uint").
514                 Replace ("int16", "short").
515                 Replace ("uint16", "ushort").
516                 Replace ("int64", "long").
517                 Replace ("uint64", "ulong").
518                 Replace ("single", "float").
519                 Replace ("boolean", "bool")
520                 + match.Groups [2].Captures [0].Value;
521         }
522
523         /// <summary>
524         ///   Returns the signature of the method
525         /// </summary>
526         static public string CSharpSignature (MethodBase mb)
527         {
528                 string sig = "(";
529
530                 //
531                 // FIXME: We should really have a single function to do
532                 // everything instead of the following 5 line pattern
533                 //
534                 ParameterData iparams = LookupParametersByBuilder (mb);
535
536                 if (iparams == null){
537                         ParameterInfo [] pi = mb.GetParameters ();
538                         iparams = new ReflectionParameters (pi);
539                 }
540                 
541                 for (int i = 0; i < iparams.Count; i++) {
542                         if (i > 0) {
543                                 sig += ", ";
544                         }
545                         sig += iparams.ParameterDesc(i);
546                 }
547                 sig += ")";
548
549                 return mb.DeclaringType.Name + "." + mb.Name + sig;
550         }
551
552         /// <summary>
553         ///   Looks up a type, and aborts if it is not found.  This is used
554         ///   by types required by the compiler
555         /// </summary>
556         static Type CoreLookupType (string name)
557         {
558                 Type t = LookupType (name);
559
560                 if (t == null){
561                         Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
562                         Environment.Exit (0);
563                 }
564
565                 return t;
566         }
567
568         /// <summary>
569         ///   Returns the MethodInfo for a method named `name' defined
570         ///   in type `t' which takes arguments of types `args'
571         /// </summary>
572         static MethodInfo GetMethod (Type t, string name, Type [] args)
573         {
574                 MemberList list;
575                 Signature sig;
576
577                 sig.name = name;
578                 sig.args = args;
579                 
580                 list = FindMembers (t, MemberTypes.Method, instance_and_static | BindingFlags.Public,
581                                     signature_filter, sig);
582                 if (list.Count == 0) {
583                         Report.Error (-19, "Can not find the core function `" + name + "'");
584                         return null;
585                 }
586
587                 MethodInfo mi = list [0] as MethodInfo;
588                 if (mi == null) {
589                         Report.Error (-19, "Can not find the core function `" + name + "'");
590                         return null;
591                 }
592
593                 return mi;
594         }
595
596         /// <summary>
597         ///    Returns the ConstructorInfo for "args"
598         /// </summary>
599         static ConstructorInfo GetConstructor (Type t, Type [] args)
600         {
601                 MemberList list;
602                 Signature sig;
603
604                 sig.name = ".ctor";
605                 sig.args = args;
606                 
607                 list = FindMembers (t, MemberTypes.Constructor,
608                                     instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
609                                     signature_filter, sig);
610                 if (list.Count == 0){
611                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
612                         return null;
613                 }
614
615                 ConstructorInfo ci = list [0] as ConstructorInfo;
616                 if (ci == null){
617                         Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
618                         return null;
619                 }
620
621                 return ci;
622         }
623
624         public static void InitEnumUnderlyingTypes ()
625         {
626
627                 int32_type    = CoreLookupType ("System.Int32");
628                 int64_type    = CoreLookupType ("System.Int64");
629                 uint32_type   = CoreLookupType ("System.UInt32"); 
630                 uint64_type   = CoreLookupType ("System.UInt64"); 
631                 byte_type     = CoreLookupType ("System.Byte");
632                 sbyte_type    = CoreLookupType ("System.SByte");
633                 short_type    = CoreLookupType ("System.Int16");
634                 ushort_type   = CoreLookupType ("System.UInt16");
635         }
636         
637         /// <remarks>
638         ///   The types have to be initialized after the initial
639         ///   population of the type has happened (for example, to
640         ///   bootstrap the corlib.dll
641         /// </remarks>
642         public static void InitCoreTypes ()
643         {
644                 object_type   = CoreLookupType ("System.Object");
645                 value_type    = CoreLookupType ("System.ValueType");
646
647                 InitEnumUnderlyingTypes ();
648
649                 char_type     = CoreLookupType ("System.Char");
650                 string_type   = CoreLookupType ("System.String");
651                 float_type    = CoreLookupType ("System.Single");
652                 double_type   = CoreLookupType ("System.Double");
653                 char_ptr_type = CoreLookupType ("System.Char*");
654                 decimal_type  = CoreLookupType ("System.Decimal");
655                 bool_type     = CoreLookupType ("System.Boolean");
656                 enum_type     = CoreLookupType ("System.Enum");
657
658                 multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
659                 delegate_type           = CoreLookupType ("System.Delegate");
660
661                 array_type    = CoreLookupType ("System.Array");
662                 void_type     = CoreLookupType ("System.Void");
663                 type_type     = CoreLookupType ("System.Type");
664
665                 runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
666                 runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
667                 default_member_type  = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
668                 runtime_handle_type  = CoreLookupType ("System.RuntimeTypeHandle");
669                 asynccallback_type   = CoreLookupType ("System.AsyncCallback");
670                 iasyncresult_type    = CoreLookupType ("System.IAsyncResult");
671                 ienumerator_type     = CoreLookupType ("System.Collections.IEnumerator");
672                 idisposable_type     = CoreLookupType ("System.IDisposable");
673                 icloneable_type      = CoreLookupType ("System.ICloneable");
674                 monitor_type         = CoreLookupType ("System.Threading.Monitor");
675                 intptr_type          = CoreLookupType ("System.IntPtr");
676
677                 attribute_type       = CoreLookupType ("System.Attribute");
678                 attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
679                 dllimport_type       = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
680                 methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
681                 marshal_as_attr_type  = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
682                 param_array_type      = CoreLookupType ("System.ParamArrayAttribute");
683
684                 unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
685
686                 void_ptr_type         = CoreLookupType ("System.Void*");
687
688                 indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
689
690                 exception_type        = CoreLookupType ("System.Exception");
691
692                 //
693                 // Attribute types
694                 //
695                 obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
696                 conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
697
698                 //
699                 // When compiling corlib, store the "real" types here.
700                 //
701                 if (!RootContext.StdLib) {
702                         system_int32_type = typeof (System.Int32);
703                         system_array_type = typeof (System.Array);
704                         system_type_type = typeof (System.Type);
705                         system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
706
707                         Type [] void_arg = {  };
708                         system_int_array_get_length = GetMethod (
709                                 system_array_type, "get_Length", void_arg);
710                         system_int_array_get_rank = GetMethod (
711                                 system_array_type, "get_Rank", void_arg);
712                         system_object_array_clone = GetMethod (
713                                 system_array_type, "Clone", void_arg);
714
715                         Type [] system_int_arg = { system_int32_type };
716                         system_int_array_get_length_int = GetMethod (
717                                 system_array_type, "GetLength", system_int_arg);
718                         system_int_array_get_upper_bound_int = GetMethod (
719                                 system_array_type, "GetUpperBound", system_int_arg);
720                         system_int_array_get_lower_bound_int = GetMethod (
721                                 system_array_type, "GetLowerBound", system_int_arg);
722
723                         Type [] system_array_int_arg = { system_array_type, system_int32_type };
724                         system_void_array_copyto_array_int = GetMethod (
725                                 system_array_type, "CopyTo", system_array_int_arg);
726
727                         Type [] system_type_type_arg = { system_type_type, system_type_type, system_type_type };
728
729                         try {
730                         system_void_set_corlib_type_builders = GetMethod (
731                                 system_assemblybuilder_type, "SetCorlibTypeBuilders",
732                                 system_type_type_arg);
733
734                         object[] args = new object [3];
735                         args [0] = object_type;
736                         args [1] = value_type;
737                         args [2] = enum_type;
738
739                         system_void_set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args);
740                         } catch {
741                                 Console.WriteLine ("Corlib compilation is not supported in Microsoft.NET due to bugs in it");
742                         }
743                 }
744         }
745
746         //
747         // The helper methods that are used by the compiler
748         //
749         public static void InitCodeHelpers ()
750         {
751                 //
752                 // Now load the default methods that we use.
753                 //
754                 Type [] string_string = { string_type, string_type };
755                 string_concat_string_string = GetMethod (
756                         string_type, "Concat", string_string);
757
758                 Type [] object_object = { object_type, object_type };
759                 string_concat_object_object = GetMethod (
760                         string_type, "Concat", object_object);
761
762                 Type [] string_ = { string_type };
763                 string_isinterneted_string = GetMethod (
764                         string_type, "IsInterned", string_);
765                 
766                 Type [] runtime_type_handle = { runtime_handle_type };
767                 system_type_get_type_from_handle = GetMethod (
768                         type_type, "GetTypeFromHandle", runtime_type_handle);
769
770                 Type [] delegate_delegate = { delegate_type, delegate_type };
771                 delegate_combine_delegate_delegate = GetMethod (
772                                 delegate_type, "Combine", delegate_delegate);
773
774                 delegate_remove_delegate_delegate = GetMethod (
775                                 delegate_type, "Remove", delegate_delegate);
776
777                 //
778                 // Void arguments
779                 //
780                 Type [] void_arg = {  };
781                 object_getcurrent_void = GetMethod (
782                         ienumerator_type, "get_Current", void_arg);
783                 bool_movenext_void = GetMethod (
784                         ienumerator_type, "MoveNext", void_arg);
785                 void_dispose_void = GetMethod (
786                         idisposable_type, "Dispose", void_arg);
787                 int_get_offset_to_string_data = GetMethod (
788                         runtime_helpers_type, "get_OffsetToStringData", void_arg);
789                 int_array_get_length = GetMethod (
790                         array_type, "get_Length", void_arg);
791                 int_array_get_rank = GetMethod (
792                         array_type, "get_Rank", void_arg);
793
794                 //
795                 // Int32 arguments
796                 //
797                 Type [] int_arg = { int32_type };
798                 int_array_get_length_int = GetMethod (
799                         array_type, "GetLength", int_arg);
800                 int_array_get_upper_bound_int = GetMethod (
801                         array_type, "GetUpperBound", int_arg);
802                 int_array_get_lower_bound_int = GetMethod (
803                         array_type, "GetLowerBound", int_arg);
804
805                 //
806                 // System.Array methods
807                 //
808                 object_array_clone = GetMethod (
809                         array_type, "Clone", void_arg);
810                 Type [] array_int_arg = { array_type, int32_type };
811                 void_array_copyto_array_int = GetMethod (
812                         array_type, "CopyTo", array_int_arg);
813                 
814                 //
815                 // object arguments
816                 //
817                 Type [] object_arg = { object_type };
818                 void_monitor_enter_object = GetMethod (
819                         monitor_type, "Enter", object_arg);
820                 void_monitor_exit_object = GetMethod (
821                         monitor_type, "Exit", object_arg);
822
823                 Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
824                 
825                 void_initializearray_array_fieldhandle = GetMethod (
826                         runtime_helpers_type, "InitializeArray", array_field_handle_arg);
827
828                 //
829                 // Array functions
830                 //
831                 int_getlength_int = GetMethod (
832                         array_type, "GetLength", int_arg);
833
834                 //
835                 // Decimal constructors
836                 //
837                 Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
838                 void_decimal_ctor_five_args = GetConstructor (
839                         decimal_type, dec_arg);
840                 
841                 //
842                 // Attributes
843                 //
844                 cons_param_array_attribute = GetConstructor (
845                         param_array_type, void_arg);
846
847                 unverifiable_code_ctor = GetConstructor (
848                         unverifiable_code_type, void_arg);
849                 
850         }
851
852         const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
853
854         static Hashtable type_hash = new Hashtable ();
855
856         /// <remarks>
857         ///   This is the "old", non-cache based FindMembers() function.  We cannot use
858         ///   the cache here because there is no member name argument.
859         /// </remarks>
860         public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
861                                               MemberFilter filter, object criteria)
862         {
863                 DeclSpace decl = (DeclSpace) builder_to_declspace [t];
864
865                 //
866                 // `builder_to_declspace' contains all dynamic types.
867                 //
868                 if (decl != null) {
869                         MemberList list;
870                         Timer.StartTimer (TimerType.FindMembers);
871                         list = decl.FindMembers (mt, bf, filter, criteria);
872                         Timer.StopTimer (TimerType.FindMembers);
873                         return list;
874                 }
875
876                 //
877                 // We have to take care of arrays specially, because GetType on
878                 // a TypeBuilder array will return a Type, not a TypeBuilder,
879                 // and we can not call FindMembers on this type.
880                 //
881                 if (t.IsSubclassOf (TypeManager.array_type))
882                         return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
883
884                 //
885                 // Since FindMembers will not lookup both static and instance
886                 // members, we emulate this behaviour here.
887                 //
888                 if ((bf & instance_and_static) == instance_and_static){
889                         MemberInfo [] i_members = t.FindMembers (
890                                 mt, bf & ~BindingFlags.Static, filter, criteria);
891
892                         int i_len = i_members.Length;
893                         if (i_len == 1){
894                                 MemberInfo one = i_members [0];
895
896                                 //
897                                 // If any of these are present, we are done!
898                                 //
899                                 if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
900                                         return new MemberList (i_members);
901                         }
902                                 
903                         MemberInfo [] s_members = t.FindMembers (
904                                 mt, bf & ~BindingFlags.Instance, filter, criteria);
905
906                         int s_len = s_members.Length;
907                         if (i_len > 0 || s_len > 0)
908                                 return new MemberList (i_members, s_members);
909                         else {
910                                 if (i_len > 0)
911                                         return new MemberList (i_members);
912                                 else
913                                         return new MemberList (s_members);
914                         }
915                 }
916
917                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
918         }
919
920
921         /// <summary>
922         ///   This method is only called from within MemberLookup.  It tries to use the member
923         ///   cache if possible and falls back to the normal FindMembers if not.  The `used_cache'
924         ///   flag tells the caller whether we used the cache or not.  If we used the cache, then
925         ///   our return value will already contain all inherited members and the caller don't need
926         ///   to check base classes and interfaces anymore.
927         /// </summary>
928         private static MemberList MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
929                                                             string name, out bool used_cache)
930         {
931                 //
932                 // We have to take care of arrays specially, because GetType on
933                 // a TypeBuilder array will return a Type, not a TypeBuilder,
934                 // and we can not call FindMembers on this type.
935                 //
936                 if (t.IsSubclassOf (TypeManager.array_type)) {
937                         used_cache = true;
938                         return TypeHandle.ArrayType.MemberCache.FindMembers (
939                                 mt, bf, name, FilterWithClosure_delegate, null);
940                 }
941
942                 //
943                 // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
944                 // and we can ask the DeclSpace for the MemberCache.
945                 //
946                 if (t is TypeBuilder) {
947                         DeclSpace decl = (DeclSpace) builder_to_declspace [t];
948                         MemberCache cache = decl.MemberCache;
949
950                         //
951                         // If this DeclSpace has a MemberCache, use it.
952                         //
953
954                         if (cache != null) {
955                                 used_cache = true;
956                                 return cache.FindMembers (
957                                         mt, bf, name, FilterWithClosure_delegate, null);
958                         }
959
960                         // If there is no MemberCache, we need to use the "normal" FindMembers.
961
962                         MemberList list;
963                         Timer.StartTimer (TimerType.FindMembers);
964                         list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
965                                                  FilterWithClosure_delegate, name);
966                         Timer.StopTimer (TimerType.FindMembers);
967                         used_cache = false;
968                         return list;
969                 }
970
971                 //
972                 // This call will always succeed.  There is exactly one TypeHandle instance per
973                 // type, TypeHandle.GetTypeHandle() will either return it or create a new one
974                 // if it didn't already exist.
975                 //
976                 TypeHandle handle = TypeHandle.GetTypeHandle (t);
977
978                 used_cache = true;
979                 return handle.MemberCache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
980         }
981
982         public static bool IsBuiltinType (Type t)
983         {
984                 if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
985                     t == int64_type || t == uint64_type || t == float_type || t == double_type ||
986                     t == char_type || t == short_type || t == decimal_type || t == bool_type ||
987                     t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
988                         return true;
989                 else
990                         return false;
991         }
992
993         public static bool IsDelegateType (Type t)
994         {
995                 if (t.IsSubclassOf (TypeManager.delegate_type))
996                         return true;
997                 else
998                         return false;
999         }
1000         
1001         public static bool IsEnumType (Type t)
1002         {
1003                 if (t.IsSubclassOf (TypeManager.enum_type))
1004                         return true;
1005                 else
1006                         return false;
1007         }
1008         
1009         public static bool IsValueType (Type t)
1010         {
1011                 if (t.IsSubclassOf (TypeManager.value_type))
1012                         return true;
1013                 else
1014                         return false;
1015         }
1016         
1017         public static bool IsInterfaceType (Type t)
1018         {
1019                 Interface iface = builder_to_declspace [t] as Interface;
1020
1021                 if (iface != null)
1022                         return true;
1023                 else
1024                         return false;
1025         }
1026
1027         //
1028         // Checks whether `type' is a subclass or nested child of `parent'.
1029         //
1030         public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
1031         {
1032                 do {
1033                         if ((type == parent) || type.IsSubclassOf (parent))
1034                                 return true;
1035
1036                         // Handle nested types.
1037                         type = type.DeclaringType;
1038                 } while (type != null);
1039
1040                 return false;
1041         }
1042
1043         /// <summary>
1044         ///   Returns the User Defined Types
1045         /// </summary>
1046         public static ArrayList UserTypes {
1047                 get {
1048                         return user_types;
1049                 }
1050         }
1051
1052         public static Hashtable TypeContainers {
1053                 get {
1054                         return typecontainers;
1055                 }
1056         }
1057
1058         static Hashtable builder_to_constant;
1059
1060         public static void RegisterConstant (FieldBuilder fb, Const c)
1061         {
1062                 if (builder_to_constant == null)
1063                         builder_to_constant = new PtrHashtable ();
1064
1065                 if (builder_to_constant.Contains (fb))
1066                         return;
1067
1068                 builder_to_constant.Add (fb, c);
1069         }
1070
1071         public static Const LookupConstant (FieldBuilder fb)
1072         {
1073                 if (builder_to_constant == null)
1074                         return null;
1075                 
1076                 return (Const) builder_to_constant [fb];
1077         }
1078         
1079         /// <summary>
1080         ///   Gigantic work around for missing features in System.Reflection.Emit follows.
1081         /// </summary>
1082         ///
1083         /// <remarks>
1084         ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
1085         ///   for anything which is dynamic, and we need this in a number of places,
1086         ///   we register this information here, and use it afterwards.
1087         /// </remarks>
1088         static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
1089         {
1090                 if (args == null)
1091                         args = NoTypes;
1092                                 
1093                 method_arguments.Add (mb, args);
1094                 method_internal_params.Add (mb, ip);
1095                 
1096                 return true;
1097         }
1098         
1099         static public InternalParameters LookupParametersByBuilder (MethodBase mb)
1100         {
1101                 if (! (mb is ConstructorBuilder || mb is MethodBuilder))
1102                         return null;
1103                 
1104                 if (method_internal_params.Contains (mb))
1105                         return (InternalParameters) method_internal_params [mb];
1106                 else
1107                         throw new Exception ("Argument for Method not registered" + mb);
1108         }
1109
1110         /// <summary>
1111         ///    Returns the argument types for a method based on its methodbase
1112         ///
1113         ///    For dynamic methods, we use the compiler provided types, for
1114         ///    methods from existing assemblies we load them from GetParameters,
1115         ///    and insert them into the cache
1116         /// </summary>
1117         static public Type [] GetArgumentTypes (MethodBase mb)
1118         {
1119                 if (method_arguments.Contains (mb))
1120                         return (Type []) method_arguments [mb];
1121                 else {
1122                         ParameterInfo [] pi = mb.GetParameters ();
1123                         int c = pi.Length;
1124                         Type [] types = new Type [c];
1125                         
1126                         for (int i = 0; i < c; i++)
1127                                 types [i] = pi [i].ParameterType;
1128
1129                         method_arguments.Add (mb, types);
1130                         return types;
1131                 }
1132         }
1133
1134         /// <summary>
1135         ///    Returns the argument types for an indexer based on its PropertyInfo
1136         ///
1137         ///    For dynamic indexers, we use the compiler provided types, for
1138         ///    indexers from existing assemblies we load them from GetParameters,
1139         ///    and insert them into the cache
1140         /// </summary>
1141         static public Type [] GetArgumentTypes (PropertyInfo indexer)
1142         {
1143                 if (indexer_arguments.Contains (indexer))
1144                         return (Type []) indexer_arguments [indexer];
1145                 else if (indexer is PropertyBuilder)
1146                         // If we're a PropertyBuilder and not in the
1147                         // `indexer_arguments' hash, then we're a property and
1148                         // not an indexer.
1149                         return NoTypes;
1150                 else {
1151                         ParameterInfo [] pi = indexer.GetIndexParameters ();
1152                         // Property, not an indexer.
1153                         if (pi == null)
1154                                 return NoTypes;
1155                         int c = pi.Length;
1156                         Type [] types = new Type [c];
1157                         
1158                         for (int i = 0; i < c; i++)
1159                                 types [i] = pi [i].ParameterType;
1160
1161                         indexer_arguments.Add (indexer, types);
1162                         return types;
1163                 }
1164         }
1165         
1166         // <remarks>
1167         //  This is a workaround the fact that GetValue is not
1168         //  supported for dynamic types
1169         // </remarks>
1170         static Hashtable fields = new Hashtable ();
1171         static public bool RegisterFieldValue (FieldBuilder fb, object value)
1172         {
1173                 if (fields.Contains (fb))
1174                         return false;
1175
1176                 fields.Add (fb, value);
1177
1178                 return true;
1179         }
1180
1181         static public object GetValue (FieldBuilder fb)
1182         {
1183                 return fields [fb];
1184         }
1185
1186         static Hashtable fieldbuilders_to_fields = new Hashtable ();
1187         static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
1188         {
1189                 if (fieldbuilders_to_fields.Contains (fb))
1190                         return false;
1191
1192                 fieldbuilders_to_fields.Add (fb, f);
1193                 return true;
1194         }
1195
1196         static public FieldBase GetField (FieldInfo fb)
1197         {
1198                 return (FieldBase) fieldbuilders_to_fields [fb];
1199         }
1200         
1201         static Hashtable events;
1202
1203         static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
1204         {
1205                 if (events == null)
1206                         events = new Hashtable ();
1207
1208                 if (events.Contains (eb))
1209                         return false;
1210
1211                 events.Add (eb, new Pair (add, remove));
1212
1213                 return true;
1214         }
1215
1216         static public MethodInfo GetAddMethod (EventInfo ei)
1217         {
1218                 if (ei is MyEventBuilder) {
1219                         Pair pair = (Pair) events [ei];
1220
1221                         return (MethodInfo) pair.First;
1222                 } else
1223                         return ei.GetAddMethod ();
1224         }
1225
1226         static public MethodInfo GetRemoveMethod (EventInfo ei)
1227         {
1228                 if (ei is MyEventBuilder) {
1229                         Pair pair = (Pair) events [ei];
1230
1231                         return (MethodInfo) pair.Second;
1232                 } else
1233                         return ei.GetAddMethod ();
1234         }
1235
1236         static Hashtable priv_fields_events;
1237
1238         static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
1239         {
1240                 if (priv_fields_events == null)
1241                         priv_fields_events = new Hashtable ();
1242
1243                 if (priv_fields_events.Contains (einfo))
1244                         return false;
1245
1246                 priv_fields_events.Add (einfo, builder);
1247
1248                 return true;
1249         }
1250
1251         static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
1252         {
1253                 return (MemberInfo) priv_fields_events [ei];
1254         }
1255                 
1256         static Hashtable properties;
1257         
1258         static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
1259         {
1260                 if (properties == null)
1261                         properties = new Hashtable ();
1262
1263                 if (properties.Contains (pb))
1264                         return false;
1265
1266                 properties.Add (pb, new Pair (get, set));
1267
1268                 return true;
1269         }
1270
1271         static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get, MethodBase set, Type[] args)
1272         {
1273                 if (!RegisterProperty (pb, get,set))
1274                         return false;
1275
1276                 indexer_arguments.Add (pb, args);
1277
1278                 return true;
1279         }
1280
1281         //
1282         // FIXME: we need to return the accessors depending on whether
1283         // they are visible or not.
1284         //
1285         static public MethodInfo [] GetAccessors (PropertyInfo pi)
1286         {
1287                 MethodInfo [] ret;
1288
1289                 if (pi is PropertyBuilder){
1290                         Pair pair = (Pair) properties [pi];
1291
1292                         ret = new MethodInfo [2];
1293                         ret [0] = (MethodInfo) pair.First;
1294                         ret [1] = (MethodInfo) pair.Second;
1295
1296                         return ret;
1297                 } else {
1298                         MethodInfo [] mi = new MethodInfo [2];
1299
1300                         //
1301                         // Why this and not pi.GetAccessors?
1302                         // Because sometimes index 0 is the getter
1303                         // sometimes it is 1
1304                         //
1305                         mi [0] = pi.GetGetMethod (true);
1306                         mi [1] = pi.GetSetMethod (true);
1307
1308                         return mi;
1309                 }
1310         }
1311
1312         static public MethodInfo GetPropertyGetter (PropertyInfo pi)
1313         {
1314                 if (pi is PropertyBuilder){
1315                         Pair de = (Pair) properties [pi];
1316
1317                         return (MethodInfo) de.Second;
1318                 } else
1319                         return pi.GetSetMethod ();
1320         }
1321
1322         static public MethodInfo GetPropertySetter (PropertyInfo pi)
1323         {
1324                 if (pi is PropertyBuilder){
1325                         Pair de = (Pair) properties [pi];
1326
1327                         return (MethodInfo) de.First;
1328                 } else
1329                         return pi.GetGetMethod ();
1330         }
1331
1332         /// <summary>
1333         ///   Given an array of interface types, expand and eliminate repeated ocurrences
1334         ///   of an interface.  
1335         /// </summary>
1336         ///
1337         /// <remarks>
1338         ///   This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
1339         ///   be IA, IB, IC.
1340         /// </remarks>
1341         public static Type [] ExpandInterfaces (Type [] base_interfaces)
1342         {
1343                 ArrayList new_ifaces = new ArrayList ();
1344                 
1345                 foreach (Type iface in base_interfaces){
1346                         if (!new_ifaces.Contains (iface))
1347                                 new_ifaces.Add (iface);
1348                         
1349                         Type [] implementing = TypeManager.GetInterfaces (iface);
1350                         
1351                         foreach (Type imp in implementing){
1352                                 if (!new_ifaces.Contains (imp))
1353                                         new_ifaces.Add (imp);
1354                         }
1355                 }
1356                 Type [] ret = new Type [new_ifaces.Count];
1357                 new_ifaces.CopyTo (ret, 0);
1358                 return ret;
1359         }
1360                 
1361         /// <summary>
1362         ///   This function returns the interfaces in the type `t'.  Works with
1363         ///   both types and TypeBuilders.
1364         /// </summary>
1365         public static Type [] GetInterfaces (Type t)
1366         {
1367                 //
1368                 // The reason for catching the Array case is that Reflection.Emit
1369                 // will not return a TypeBuilder for Array types of TypeBuilder types,
1370                 // but will still throw an exception if we try to call GetInterfaces
1371                 // on the type.
1372                 //
1373                 // Since the array interfaces are always constant, we return those for
1374                 // the System.Array
1375                 //
1376                 
1377                 if (t.IsArray)
1378                         t = TypeManager.array_type;
1379                 
1380                 if (t is TypeBuilder){
1381                         Type [] parent_ifaces;
1382                         
1383                         if (t.BaseType == null)
1384                                 parent_ifaces = NoTypes;
1385                         else
1386                                 parent_ifaces = GetInterfaces (t.BaseType);
1387                         Type [] type_ifaces = (Type []) builder_to_ifaces [t];
1388                         if (type_ifaces == null)
1389                                 type_ifaces = NoTypes;
1390
1391                         int parent_count = parent_ifaces.Length;
1392                         Type [] result = new Type [parent_count + type_ifaces.Length];
1393                         parent_ifaces.CopyTo (result, 0);
1394                         type_ifaces.CopyTo (result, parent_count);
1395
1396                         return result;
1397                 } else
1398                         return t.GetInterfaces ();
1399         }
1400         
1401         /// <remarks>
1402         ///  The following is used to check if a given type implements an interface.
1403         ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
1404         /// </remarks>
1405         public static bool ImplementsInterface (Type t, Type iface)
1406         {
1407                 Type [] interfaces;
1408
1409                 //
1410                 // FIXME OPTIMIZATION:
1411                 // as soon as we hit a non-TypeBuiler in the interface
1412                 // chain, we could return, as the `Type.GetInterfaces'
1413                 // will return all the interfaces implement by the type
1414                 // or its parents.
1415                 //
1416                 do {
1417                         interfaces = GetInterfaces (t);
1418
1419                         if (interfaces != null){
1420                                 foreach (Type i in interfaces){
1421                                         if (i == iface)
1422                                                 return true;
1423                                 }
1424                         }
1425                         
1426                         t = t.BaseType;
1427                 } while (t != null);
1428                 
1429                 return false;
1430         }
1431
1432         // This is a custom version of Convert.ChangeType() which works
1433         // with the TypeBuilder defined types when compiling corlib.
1434         public static object ChangeType (object value, Type conversionType)
1435         {
1436                 if (!(value is IConvertible))
1437                         throw new ArgumentException ();
1438
1439                 IConvertible convertValue = (IConvertible) value;
1440                 CultureInfo ci = CultureInfo.CurrentCulture;
1441                 NumberFormatInfo provider = ci.NumberFormat;
1442
1443                 //
1444                 // We must use Type.Equals() here since `conversionType' is
1445                 // the TypeBuilder created version of a system type and not
1446                 // the system type itself.  You cannot use Type.GetTypeCode()
1447                 // on such a type - it'd always return TypeCode.Object.
1448                 //
1449                 if (conversionType.Equals (typeof (Boolean)))
1450                         return (object)(convertValue.ToBoolean (provider));
1451                 else if (conversionType.Equals (typeof (Byte)))
1452                         return (object)(convertValue.ToByte (provider));
1453                 else if (conversionType.Equals (typeof (Char)))
1454                         return (object)(convertValue.ToChar (provider));
1455                 else if (conversionType.Equals (typeof (DateTime)))
1456                         return (object)(convertValue.ToDateTime (provider));
1457                 else if (conversionType.Equals (typeof (Decimal)))
1458                         return (object)(convertValue.ToDecimal (provider));
1459                 else if (conversionType.Equals (typeof (Double)))
1460                         return (object)(convertValue.ToDouble (provider));
1461                 else if (conversionType.Equals (typeof (Int16)))
1462                         return (object)(convertValue.ToInt16 (provider));
1463                 else if (conversionType.Equals (typeof (Int32)))
1464                         return (object)(convertValue.ToInt32 (provider));
1465                 else if (conversionType.Equals (typeof (Int64)))
1466                         return (object)(convertValue.ToInt64 (provider));
1467                 else if (conversionType.Equals (typeof (SByte)))
1468                         return (object)(convertValue.ToSByte (provider));
1469                 else if (conversionType.Equals (typeof (Single)))
1470                         return (object)(convertValue.ToSingle (provider));
1471                 else if (conversionType.Equals (typeof (String)))
1472                         return (object)(convertValue.ToString (provider));
1473                 else if (conversionType.Equals (typeof (UInt16)))
1474                         return (object)(convertValue.ToUInt16 (provider));
1475                 else if (conversionType.Equals (typeof (UInt32)))
1476                         return (object)(convertValue.ToUInt32 (provider));
1477                 else if (conversionType.Equals (typeof (UInt64)))
1478                         return (object)(convertValue.ToUInt64 (provider));
1479                 else if (conversionType.Equals (typeof (Object)))
1480                         return (object)(value);
1481                 else 
1482                         throw new InvalidCastException ();
1483         }
1484
1485         //
1486         // This is needed, because enumerations from assemblies
1487         // do not report their underlyingtype, but they report
1488         // themselves
1489         //
1490         public static Type EnumToUnderlying (Type t)
1491         {
1492                 if (t == TypeManager.enum_type)
1493                         return t;
1494
1495                 t = t.UnderlyingSystemType;
1496                 if (!TypeManager.IsEnumType (t))
1497                         return t;
1498         
1499                 if (t is TypeBuilder) {
1500                         // slow path needed to compile corlib
1501                         if (t == TypeManager.bool_type ||
1502                                         t == TypeManager.byte_type ||
1503                                         t == TypeManager.sbyte_type ||
1504                                         t == TypeManager.char_type ||
1505                                         t == TypeManager.short_type ||
1506                                         t == TypeManager.ushort_type ||
1507                                         t == TypeManager.int32_type ||
1508                                         t == TypeManager.uint32_type ||
1509                                         t == TypeManager.int64_type ||
1510                                         t == TypeManager.uint64_type)
1511                                 return t;
1512                         throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
1513                 }
1514                 TypeCode tc = Type.GetTypeCode (t);
1515
1516                 switch (tc){
1517                 case TypeCode.Boolean:
1518                         return TypeManager.bool_type;
1519                 case TypeCode.Byte:
1520                         return TypeManager.byte_type;
1521                 case TypeCode.SByte:
1522                         return TypeManager.sbyte_type;
1523                 case TypeCode.Char:
1524                         return TypeManager.char_type;
1525                 case TypeCode.Int16:
1526                         return TypeManager.short_type;
1527                 case TypeCode.UInt16:
1528                         return TypeManager.ushort_type;
1529                 case TypeCode.Int32:
1530                         return TypeManager.int32_type;
1531                 case TypeCode.UInt32:
1532                         return TypeManager.uint32_type;
1533                 case TypeCode.Int64:
1534                         return TypeManager.int64_type;
1535                 case TypeCode.UInt64:
1536                         return TypeManager.uint64_type;
1537                 }
1538                 throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
1539         }
1540
1541         //
1542         // When compiling corlib and called with one of the core types, return
1543         // the corresponding typebuilder for that type.
1544         //
1545         public static Type TypeToCoreType (Type t)
1546         {
1547                 if (RootContext.StdLib || (t is TypeBuilder))
1548                         return t;
1549
1550                 TypeCode tc = Type.GetTypeCode (t);
1551
1552                 switch (tc){
1553                 case TypeCode.Boolean:
1554                         return TypeManager.bool_type;
1555                 case TypeCode.Byte:
1556                         return TypeManager.byte_type;
1557                 case TypeCode.SByte:
1558                         return TypeManager.sbyte_type;
1559                 case TypeCode.Char:
1560                         return TypeManager.char_type;
1561                 case TypeCode.Int16:
1562                         return TypeManager.short_type;
1563                 case TypeCode.UInt16:
1564                         return TypeManager.ushort_type;
1565                 case TypeCode.Int32:
1566                         return TypeManager.int32_type;
1567                 case TypeCode.UInt32:
1568                         return TypeManager.uint32_type;
1569                 case TypeCode.Int64:
1570                         return TypeManager.int64_type;
1571                 case TypeCode.UInt64:
1572                         return TypeManager.uint64_type;
1573                 case TypeCode.String:
1574                         return TypeManager.string_type;
1575                 default:
1576                         if (t == typeof (void))
1577                                 return TypeManager.void_type;
1578                         if (t == typeof (object))
1579                                 return TypeManager.object_type;
1580                         if (t == typeof (System.Type))
1581                                 return TypeManager.type_type;
1582                         return t;
1583                 }
1584         }
1585
1586         /// <summary>
1587         ///   Utility function that can be used to probe whether a type
1588         ///   is managed or not.  
1589         /// </summary>
1590         public static bool VerifyUnManaged (Type t, Location loc)
1591         {
1592                 if (t.IsValueType || t.IsPointer){
1593                         //
1594                         // FIXME: this is more complex, we actually need to
1595                         // make sure that the type does not contain any
1596                         // classes itself
1597                         //
1598                         return true;
1599                 }
1600
1601                 if (!RootContext.StdLib && (t == TypeManager.decimal_type))
1602                         // We need this explicit check here to make it work when
1603                         // compiling corlib.
1604                         return true;
1605
1606                 Report.Error (
1607                         208, loc,
1608                         "Cannot take the address or size of a variable of a managed type ('" +
1609                         CSharpName (t) + "')");
1610                 return false;   
1611         }
1612         
1613         /// <summary>
1614         ///   Returns the name of the indexer in a given type.
1615         /// </summary>
1616         /// <remarks>
1617         ///   The default is not always `Item'.  The user can change this behaviour by
1618         ///   using the DefaultMemberAttribute in the class.
1619         ///
1620         ///   For example, the String class indexer is named `Chars' not `Item' 
1621         /// </remarks>
1622         public static string IndexerPropertyName (Type t)
1623         {
1624                 if (t is TypeBuilder) {
1625                         if (t.IsInterface) {
1626                                 Interface i = LookupInterface (t);
1627
1628                                 if ((i == null) || (i.IndexerName == null))
1629                                         return "Item";
1630
1631                                 return i.IndexerName;
1632                         } else {
1633                                 TypeContainer tc = LookupTypeContainer (t);
1634
1635                                 if ((tc == null) || (tc.IndexerName == null))
1636                                         return "Item";
1637
1638                                 return tc.IndexerName;
1639                         }
1640                 }
1641                 
1642                 System.Attribute attr = System.Attribute.GetCustomAttribute (
1643                         t, TypeManager.default_member_type);
1644                 if (attr != null){
1645                         DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
1646                         return dma.MemberName;
1647                 }
1648
1649                 return "Item";
1650         }
1651
1652         public static void MakePinned (LocalBuilder builder)
1653         {
1654                 //
1655                 // FIXME: Flag the "LocalBuilder" type as being
1656                 // pinned.  Figure out API.
1657                 //
1658         }
1659
1660
1661         //
1662         // Returns whether the array of memberinfos contains the given method
1663         //
1664         static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
1665         {
1666                 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
1667                 
1668                 foreach (MethodBase method in array){
1669                         if (method.Name != new_method.Name)
1670                                 continue;
1671                         
1672                         Type [] old_args = TypeManager.GetArgumentTypes (method);
1673                         int old_count = old_args.Length;
1674                         int i;
1675                         
1676                         if (new_args.Length != old_count)
1677                                 continue;
1678                         
1679                         for (i = 0; i < old_count; i++){
1680                                 if (old_args [i] != new_args [i])
1681                                         break;
1682                         }
1683                         if (i != old_count)
1684                                 continue;
1685
1686                         return true;
1687                 }
1688                 return false;
1689         }
1690         
1691         //
1692         // We copy methods from `new_members' into `target_list' if the signature
1693         // for the method from in the new list does not exist in the target_list
1694         //
1695         // The name is assumed to be the same.
1696         //
1697         public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members)
1698         {
1699                 if (target_list == null){
1700                         target_list = new ArrayList ();
1701
1702                         foreach (MemberInfo mi in new_members){
1703                                 if (mi is MethodBase)
1704                                         target_list.Add (mi);
1705                         }
1706                         return target_list;
1707                 }
1708                 
1709                 MemberInfo [] target_array = new MemberInfo [target_list.Count];
1710                 target_list.CopyTo (target_array, 0);
1711                 
1712                 foreach (MemberInfo mi in new_members){
1713                         MethodBase new_method = (MethodBase) mi;
1714                         
1715                         if (!ArrayContainsMethod (target_array, new_method))
1716                                 target_list.Add (new_method);
1717                 }
1718                 return target_list;
1719         }
1720
1721         [Flags]
1722         public enum MethodFlags {
1723                 IsObsolete = 1,
1724                 IsObsoleteError = 2,
1725                 ShouldIgnore = 3
1726         }
1727         
1728         //
1729         // Returns the TypeManager.MethodFlags for this method.
1730         // This emits an error 619 / warning 618 if the method is obsolete.
1731         // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
1732         //
1733         static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
1734         {
1735                 MethodFlags flags = 0;
1736                 
1737                 if (mb.DeclaringType is TypeBuilder){
1738                         MethodData method = (MethodData) builder_to_method [mb];
1739                         if (method == null) {
1740                                 // FIXME: implement Obsolete attribute on Property,
1741                                 //        Indexer and Event.
1742                                 return 0;
1743                         }
1744
1745                         return method.GetMethodFlags (loc);
1746                 }
1747
1748                 object [] attrs = mb.GetCustomAttributes (true);
1749                 foreach (object ta in attrs){
1750                         if (!(ta is System.Attribute)){
1751                                 Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
1752                                 continue;
1753                         }
1754                         System.Attribute a = (System.Attribute) ta;
1755                         if (a.TypeId == TypeManager.obsolete_attribute_type){
1756                                 ObsoleteAttribute oa = (ObsoleteAttribute) a;
1757
1758                                 string method_desc = TypeManager.CSharpSignature (mb);
1759
1760                                 if (oa.IsError) {
1761                                         Report.Error (619, loc, "Method `" + method_desc +
1762                                                       "' is obsolete: `" + oa.Message + "'");
1763                                         return MethodFlags.IsObsoleteError;
1764                                 } else
1765                                         Report.Warning (618, loc, "Method `" + method_desc +
1766                                                         "' is obsolete: `" + oa.Message + "'");
1767
1768                                 flags |= MethodFlags.IsObsolete;
1769
1770                                 continue;
1771                         }
1772                         
1773                         //
1774                         // Skip over conditional code.
1775                         //
1776                         if (a.TypeId == TypeManager.conditional_attribute_type){
1777                                 ConditionalAttribute ca = (ConditionalAttribute) a;
1778
1779                                 if (RootContext.AllDefines [ca.ConditionString] == null)
1780                                         flags |= MethodFlags.ShouldIgnore;
1781                         }
1782                 }
1783
1784                 return flags;
1785         }
1786         
1787 #region MemberLookup implementation
1788         
1789         //
1790         // Name of the member
1791         //
1792         static string   closure_name;
1793
1794         //
1795         // Whether we allow private members in the result (since FindMembers
1796         // uses NonPublic for both protected and private), we need to distinguish.
1797         //
1798         static bool     closure_private_ok;
1799
1800         //
1801         // Who is invoking us and which type is being queried currently.
1802         //
1803         static Type     closure_invocation_type;
1804         static Type     closure_queried_type;
1805         static Type     closure_start_type;
1806
1807         //
1808         // The assembly that defines the type is that is calling us
1809         //
1810         static Assembly closure_invocation_assembly;
1811
1812         //
1813         // This filter filters by name + whether it is ok to include private
1814         // members in the search
1815         //
1816         static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
1817         {
1818                 //
1819                 // Hack: we know that the filter criteria will always be in the `closure'
1820                 // fields. 
1821                 //
1822
1823                 if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
1824                                 return false;
1825
1826                 if (closure_start_type == closure_invocation_type)
1827                         return true;
1828
1829                 //
1830                 // Ugly: we need to find out the type of `m', and depending
1831                 // on this, tell whether we accept or not
1832                 //
1833                 if (m is MethodBase){
1834                         MethodBase mb = (MethodBase) m;
1835                         MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
1836
1837                         if (ma == MethodAttributes.Private)
1838                                 return closure_private_ok || (closure_invocation_type == m.DeclaringType);
1839
1840                         //
1841                         // FamAndAssem requires that we not only derivate, but we are on the
1842                         // same assembly.  
1843                         //
1844                         if (ma == MethodAttributes.FamANDAssem){
1845                                 if (closure_invocation_assembly != mb.DeclaringType.Assembly)
1846                                         return false;
1847                         }
1848
1849                         // Assembly and FamORAssem succeed if we're in the same assembly.
1850                         if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
1851                                 if (closure_invocation_assembly == mb.DeclaringType.Assembly)
1852                                         return true;
1853                         }
1854
1855                         // We already know that we aren't in the same assembly.
1856                         if (ma == MethodAttributes.Assembly)
1857                                 return false;
1858
1859                         // Family and FamANDAssem require that we derive.
1860                         if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
1861                                 if (closure_invocation_type == null)
1862                                         return false;
1863
1864                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
1865                                         return false;
1866
1867                                 // Although a derived class can access protected members of its base class
1868                                 // it cannot do so through an instance of the base class (CS1540).
1869                                 if ((closure_invocation_type != closure_start_type) &&
1870                                     closure_invocation_type.IsSubclassOf (closure_start_type))
1871                                         return false;
1872
1873                                 return true;
1874                         }
1875
1876                         // Public.
1877                         return true;
1878                 }
1879
1880                 if (m is FieldInfo){
1881                         FieldInfo fi = (FieldInfo) m;
1882                         FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
1883
1884                         if (fa == FieldAttributes.Private)
1885                                 return closure_private_ok || (closure_invocation_type == m.DeclaringType);
1886
1887                         //
1888                         // FamAndAssem requires that we not only derivate, but we are on the
1889                         // same assembly.  
1890                         //
1891                         if (fa == FieldAttributes.FamANDAssem){
1892                                 if (closure_invocation_assembly != fi.DeclaringType.Assembly)
1893                                         return false;
1894                         }
1895
1896                         // Assembly and FamORAssem succeed if we're in the same assembly.
1897                         if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
1898                                 if (closure_invocation_assembly == fi.DeclaringType.Assembly)
1899                                         return true;
1900                         }
1901
1902                         // We already know that we aren't in the same assembly.
1903                         if (fa == FieldAttributes.Assembly)
1904                                 return false;
1905
1906                         // Family and FamANDAssem require that we derive.
1907                         if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
1908                                 if (closure_invocation_type == null)
1909                                         return false;
1910
1911                                 if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
1912                                         return false;
1913
1914                                 // Although a derived class can access protected members of its base class
1915                                 // it cannot do so through an instance of the base class (CS1540).
1916                                 if ((closure_invocation_type != closure_start_type) &&
1917                                     closure_invocation_type.IsSubclassOf (closure_start_type))
1918                                         return false;
1919
1920                                 return true;
1921                         }
1922
1923                         // Public.
1924                         return true;
1925                 }
1926
1927                 //
1928                 // EventInfos and PropertyInfos, return true
1929                 //
1930                 return true;
1931         }
1932
1933         static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
1934
1935         //
1936         // Looks up a member called `name' in the `queried_type'.  This lookup
1937         // is done by code that is contained in the definition for `invocation_type'.
1938         //
1939         // The binding flags are `bf' and the kind of members being looked up are `mt'
1940         //
1941         // Returns an array of a single element for everything but Methods/Constructors
1942         // that might return multiple matches.
1943         //
1944         public static MemberInfo [] MemberLookup (Type invocation_type, Type queried_type, 
1945                                                   MemberTypes mt, BindingFlags original_bf, string name)
1946         {
1947                 Timer.StartTimer (TimerType.MemberLookup);
1948
1949                 MemberInfo[] retval = RealMemberLookup (invocation_type, queried_type,
1950                                                         mt, original_bf, name);
1951
1952                 Timer.StopTimer (TimerType.MemberLookup);
1953
1954                 return retval;
1955         }
1956
1957         static MemberInfo [] RealMemberLookup (Type invocation_type, Type queried_type, 
1958                                                MemberTypes mt, BindingFlags original_bf, string name)
1959         {
1960                 BindingFlags bf = original_bf;
1961                 
1962                 ArrayList method_list = null;
1963                 Type current_type = queried_type;
1964                 bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
1965                 bool private_ok;
1966                 bool always_ok_flag = false;
1967                 bool skip_iface_check = true, used_cache = false;
1968
1969                 closure_name = name;
1970                 closure_invocation_type = invocation_type;
1971                 closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
1972                 closure_start_type = queried_type;
1973
1974                 //
1975                 // If we are a nested class, we always have access to our container
1976                 // type names
1977                 //
1978                 if (invocation_type != null){
1979                         string invocation_name = invocation_type.FullName;
1980                         if (invocation_name.IndexOf ('+') != -1){
1981                                 string container = queried_type.FullName + "+";
1982                                 int container_length = container.Length;
1983                                 
1984                                 if (invocation_name.Length > container_length){
1985                                         string shared = invocation_name.Substring (0, container_length);
1986                                 
1987                                         if (shared == container)
1988                                                 always_ok_flag = true;
1989                                 }
1990                         }
1991                 }
1992                 
1993                 do {
1994                         MemberList list;
1995
1996                         //
1997                         // `NonPublic' is lame, because it includes both protected and
1998                         // private methods, so we need to control this behavior by
1999                         // explicitly tracking if a private method is ok or not.
2000                         //
2001                         // The possible cases are:
2002                         //    public, private and protected (internal does not come into the
2003                         //    equation)
2004                         //
2005                         if (invocation_type != null){
2006                                 if (invocation_type == current_type){
2007                                         private_ok = true;
2008                                 } else
2009                                         private_ok = always_ok_flag;
2010                                 
2011                                 if (private_ok || invocation_type.IsSubclassOf (current_type))
2012                                         bf = original_bf | BindingFlags.NonPublic;
2013                         } else {
2014                                 private_ok = false;
2015                                 bf = original_bf & ~BindingFlags.NonPublic;
2016                         }
2017
2018                         closure_private_ok = private_ok;
2019                         closure_queried_type = current_type;
2020
2021                         Timer.StopTimer (TimerType.MemberLookup);
2022
2023                         list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
2024
2025                         Timer.StartTimer (TimerType.MemberLookup);
2026
2027                         //
2028                         // When queried for an interface type, the cache will automatically check all
2029                         // inherited members, so we don't need to do this here.  However, this only
2030                         // works if we already used the cache in the first iteration of this loop.
2031                         //
2032                         // If we used the cache in any further iteration, we can still terminate the
2033                         // loop since the cache always looks in all parent classes.
2034                         //
2035
2036                         if (used_cache)
2037                                 searching = false;
2038                         else
2039                                 skip_iface_check = false;
2040
2041                         if (current_type == TypeManager.object_type)
2042                                 searching = false;
2043                         else {
2044                                 current_type = current_type.BaseType;
2045                                 
2046                                 //
2047                                 // This happens with interfaces, they have a null
2048                                 // basetype.  Look members up in the Object class.
2049                                 //
2050                                 if (current_type == null)
2051                                         current_type = TypeManager.object_type;
2052                         }
2053                         
2054                         if (list.Count == 0)
2055                                 continue;
2056                         
2057                         //
2058                         // Events and types are returned by both `static' and `instance'
2059                         // searches, which means that our above FindMembers will
2060                         // return two copies of the same.
2061                         //
2062                         if (list.Count == 1 && !(list [0] is MethodBase)){
2063                                 return (MemberInfo []) list;
2064                         }
2065
2066                         //
2067                         // Multiple properties: we query those just to find out the indexer
2068                         // name
2069                         //
2070                         if (list [0] is PropertyInfo)
2071                                 return (MemberInfo []) list;
2072
2073                         //
2074                         // We found methods, turn the search into "method scan"
2075                         // mode.
2076                         //
2077                         
2078                         method_list = CopyNewMethods (method_list, list);
2079                         mt &= (MemberTypes.Method | MemberTypes.Constructor);
2080                 } while (searching);
2081
2082                 if (method_list != null && method_list.Count > 0)
2083                         return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
2084
2085                 //
2086                 // This happens if we already used the cache in the first iteration, in this case
2087                 // the cache already looked in all interfaces.
2088                 //
2089                 if (skip_iface_check)
2090                         return null;
2091
2092                 //
2093                 // Interfaces do not list members they inherit, so we have to
2094                 // scan those.
2095                 // 
2096                 if (!queried_type.IsInterface)
2097                         return null;
2098
2099                 if (queried_type.IsArray)
2100                         queried_type = TypeManager.array_type;
2101                 
2102                 Type [] ifaces = GetInterfaces (queried_type);
2103                 if (ifaces == null)
2104                         return null;
2105                 
2106                 foreach (Type itype in ifaces){
2107                         MemberInfo [] x;
2108
2109                         x = MemberLookup (null, itype, mt, bf, name);
2110                         if (x != null)
2111                                 return x;
2112                 }
2113                                         
2114                 return null;
2115         }
2116 #endregion
2117         
2118 }
2119
2120 /// <summary>
2121 ///   There is exactly one instance of this class per type.
2122 /// </summary>
2123 public sealed class TypeHandle : IMemberContainer {
2124         public readonly TypeHandle BaseType;
2125
2126         readonly int id = ++next_id;
2127         static int next_id = 0;
2128
2129         /// <summary>
2130         ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
2131         ///   a TypeHandle yet, a new instance of it is created.  This static method
2132         ///   ensures that we'll only have one TypeHandle instance per type.
2133         /// </summary>
2134         public static TypeHandle GetTypeHandle (Type t)
2135         {
2136                 TypeHandle handle = (TypeHandle) type_hash [t];
2137                 if (handle != null)
2138                         return handle;
2139
2140                 handle = new TypeHandle (t);
2141                 type_hash.Add (t, handle);
2142                 return handle;
2143         }
2144
2145         /// <summary>
2146         ///   Returns the TypeHandle for TypeManager.object_type.
2147         /// </summary>
2148         public static IMemberContainer ObjectType {
2149                 get {
2150                         if (object_type != null)
2151                                 return object_type;
2152
2153                         object_type = GetTypeHandle (TypeManager.object_type);
2154
2155                         return object_type;
2156                 }
2157         }
2158
2159         /// <summary>
2160         ///   Returns the TypeHandle for TypeManager.array_type.
2161         /// </summary>
2162         public static IMemberContainer ArrayType {
2163                 get {
2164                         if (array_type != null)
2165                                 return array_type;
2166
2167                         array_type = GetTypeHandle (TypeManager.array_type);
2168
2169                         return array_type;
2170                 }
2171         }
2172
2173         private static PtrHashtable type_hash = new PtrHashtable ();
2174
2175         private static TypeHandle object_type = null;
2176         private static TypeHandle array_type = null;
2177
2178         private Type type;
2179         private bool is_interface;
2180         private MemberCache member_cache;
2181
2182         private TypeHandle (Type type)
2183         {
2184                 this.type = type;
2185                 if (type.BaseType != null)
2186                         BaseType = GetTypeHandle (type.BaseType);
2187                 else if ((type != TypeManager.object_type) && (type != typeof (object)))
2188                         is_interface = true;
2189                 this.member_cache = new MemberCache (this);
2190         }
2191
2192         // IMemberContainer methods
2193
2194         public string Name {
2195                 get {
2196                         return type.FullName;
2197                 }
2198         }
2199
2200         public Type Type {
2201                 get {
2202                         return type;
2203                 }
2204         }
2205
2206         public IMemberContainer Parent {
2207                 get {
2208                         return BaseType;
2209                 }
2210         }
2211
2212         public bool IsInterface {
2213                 get {
2214                         return is_interface;
2215                 }
2216         }
2217
2218         public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
2219         {
2220                 return new MemberList (type.FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null));
2221         }
2222
2223         // IMemberFinder methods
2224
2225         public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
2226                                        MemberFilter filter, object criteria)
2227         {
2228                 return member_cache.FindMembers (mt, bf, name, filter, criteria);
2229         }
2230
2231         public MemberCache MemberCache {
2232                 get {
2233                         return member_cache;
2234                 }
2235         }
2236
2237         public override string ToString ()
2238         {
2239                 if (BaseType != null)
2240                         return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
2241                 else
2242                         return "TypeHandle (" + id + "," + Name + ")";
2243         }
2244 }
2245
2246 }