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