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