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