2002-03-06 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / typemanager.cs
index ce735f43f75f70f9d3c43b89ec25fa5ce3d47dd8..6527047fdb87834e5a60acb60304580dbea10f7c 100755 (executable)
@@ -30,6 +30,7 @@ public class TypeManager {
        static public Type float_type;
        static public Type double_type;
        static public Type char_type;
+       static public Type char_ptr_type;
        static public Type short_type;
        static public Type decimal_type;
        static public Type bool_type;
@@ -55,7 +56,12 @@ public class TypeManager {
        static public Type runtime_field_handle_type;
        static public Type attribute_usage_type;
        static public Type dllimport_type;
+       static public Type unverifiable_code_type;
+       static public Type methodimpl_attr_type;
        static public Type param_array_type;
+       static public Type void_ptr_type;
+
+       static public Type [] NoTypes;
        
        //
        // Internal, not really used outside
@@ -78,6 +84,7 @@ public class TypeManager {
        static public MethodInfo int_getlength_int;
        static public MethodInfo delegate_combine_delegate_delegate;
        static public MethodInfo delegate_remove_delegate_delegate;
+       static public MethodInfo int_get_offset_to_string_data;
        
        //
        // The attribute constructors.
@@ -89,13 +96,13 @@ public class TypeManager {
        //   (either because it is the default or the user used the
        //   -r command line option)
        // </remarks>
-       ArrayList assemblies;
+       Assembly [] assemblies;
 
        // <remarks>
        //  Keeps a list of module builders. We used this to do lookups
        //  on the modulebuilder using GetType -- needed for arrays
        // </remarks>
-       ArrayList modules;
+       ModuleBuilder [] modules;
 
        // <remarks>
        //   This is the type_cache from the assemblies to avoid
@@ -154,8 +161,8 @@ public class TypeManager {
 
        public TypeManager ()
        {
-               assemblies = new ArrayList ();
-               modules = new ArrayList ();
+               assemblies = null;
+               modules = null;
                user_types = new ArrayList ();
                types = new Hashtable ();
                typecontainers = new Hashtable ();
@@ -171,6 +178,7 @@ public class TypeManager {
                method_internal_params = new PtrHashtable ();
                builder_to_container = new PtrHashtable ();
                type_interface_cache = new PtrHashtable ();
+               NoTypes = new Type [0];
        }
 
        public void AddUserType (string name, TypeBuilder t)
@@ -243,7 +251,13 @@ public class TypeManager {
        /// </summary>
        public void AddAssembly (Assembly a)
        {
-               assemblies.Add (a);
+               int top = assemblies != null ? assemblies.Length : 0;
+               Assembly [] n = new Assembly [top + 1];
+
+               if (assemblies != null)
+                       assemblies.CopyTo (n, 0);
+               n [top] = a;
+               assemblies = n;
        }
 
        /// <summary>
@@ -251,7 +265,13 @@ public class TypeManager {
        /// </summary>
        public void AddModule (ModuleBuilder mb)
        {
-               modules.Add (mb);
+               int top = modules != null ? modules.Length : 0;
+               ModuleBuilder [] n = new ModuleBuilder [top + 1];
+
+               if (modules != null)
+                       modules.CopyTo (n, 0);
+               n [top] = mb;
+               modules = n;
        }
 
        /// <summary>
@@ -326,6 +346,8 @@ public class TypeManager {
                        return "string";
                else if (t == object_type)
                        return "object";
+               else if (t == void_type)
+                       return "void";
                else
                        return t.FullName;
        }
@@ -389,6 +411,7 @@ public class TypeManager {
                byte_type     = CoreLookupType ("System.Byte");
                sbyte_type    = CoreLookupType ("System.SByte");
                char_type     = CoreLookupType ("System.Char");
+               char_ptr_type = CoreLookupType ("System.Char*");
                short_type    = CoreLookupType ("System.Int16");
                ushort_type   = CoreLookupType ("System.UInt16");
                decimal_type  = CoreLookupType ("System.Decimal");
@@ -416,7 +439,12 @@ public class TypeManager {
 
                attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
                dllimport_type       = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
+               methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
                param_array_type     = CoreLookupType ("System.ParamArrayAttribute");
+
+               unverifiable_code_type = CoreLookupType ("System.Security.UnverifiableCodeAttribute");
+
+               void_ptr_type        = CoreLookupType ("System.Void*");
                
                //
                // Now load the default methods that we use.
@@ -454,6 +482,8 @@ public class TypeManager {
                        ienumerator_type, "MoveNext", void_arg);
                void_dispose_void = GetMethod (
                        idisposable_type, "Dispose", void_arg);
+               int_get_offset_to_string_data = GetMethod (
+                       runtime_helpers_type, "get_OffsetToStringData", void_arg);
 
                //
                // object arguments
@@ -483,6 +513,8 @@ public class TypeManager {
                        param_array_type, void_arg);
                
        }
+
+       const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
        
        public MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
                                          MemberFilter filter, object criteria)
@@ -495,9 +527,37 @@ public class TypeManager {
                if (t.IsSubclassOf (TypeManager.array_type))
                        return TypeManager.array_type.FindMembers (mt, bf, filter, criteria);
                
-               if (!(t is TypeBuilder))
+               if (!(t is TypeBuilder)){
+                       //
+                       // Since FindMembers will not lookup both static and instance
+                       // members, we emulate this behaviour here.
+                       //
+                       if ((bf & instance_and_static) == instance_and_static){
+                               MemberInfo [] i_members = t.FindMembers (
+                                       mt, bf & ~BindingFlags.Static, filter, criteria);
+                               MemberInfo [] s_members = t.FindMembers (
+                                       mt, bf & ~BindingFlags.Instance, filter, criteria);
+
+                               int i_len = i_members.Length;
+                               int s_len = s_members.Length;
+                               if (i_len > 0 || s_len > 0){
+                                       MemberInfo [] both = new MemberInfo [i_len + s_len];
+
+                                       i_members.CopyTo (both, 0);
+                                       s_members.CopyTo (both, i_len);
+
+                                       return both;
+                               } else
+                                       return i_members;
+                       }
                        return t.FindMembers (mt, bf, filter, criteria);
+               }
 
+               //
+               // FIXME: We should not have builder_to_blah everywhere,
+               // we should just have a builder_to_findmemberizable
+               // and have them implement a new ICanFindMembers interface
+               //
                Enum e = (Enum) builder_to_enum [t];
 
                if (e != null)
@@ -594,18 +654,20 @@ public class TypeManager {
                return (Const) builder_to_constant [fb];
        }
        
-       //
-       // Gigantic work around for stupidity in System.Reflection.Emit follows
-       //
-       // Since System.Reflection.Emit can not return MethodBase.GetParameters
-       // for anything which is dynamic, and we need this in a number of places,
-       // we register this information here, and use it afterwards.
-       //
+       /// <summary>
+       ///   Gigantic work around for missing features in System.Reflection.Emit follows.
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
+       ///   for anything which is dynamic, and we need this in a number of places,
+       ///   we register this information here, and use it afterwards.
+       /// </remarks>
        static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
        {
-               if (method_arguments.Contains (mb))
-                       return false;
-               
+               if (args == null)
+                       args = NoTypes;
+                               
                method_arguments.Add (mb, args);
                method_internal_params.Add (mb, ip);
                
@@ -614,8 +676,6 @@ public class TypeManager {
        
        static public InternalParameters LookupParametersByBuilder (MethodBase mb)
        {
-               object o = method_arguments [mb];
-
                if (! (mb is ConstructorBuilder || mb is MethodBuilder))
                        return null;
                
@@ -653,13 +713,9 @@ public class TypeManager {
        //  This is a workaround the fact that GetValue is not
        //  supported for dynamic types
        // </remarks>
-       static Hashtable fields;
-
-       static public bool RegisterField (FieldBuilder fb, object value)
+       static Hashtable fields = new Hashtable ();
+       static public bool RegisterFieldValue (FieldBuilder fb, object value)
        {
-               if (fields == null)
-                       fields = new Hashtable ();
-
                if (fields.Contains (fb))
                        return false;
 
@@ -673,6 +729,21 @@ public class TypeManager {
                return fields [fb];
        }
 
+       static Hashtable fieldbuilders_to_fields = new Hashtable ();
+       static public bool RegisterField (FieldBuilder fb, Field f)
+       {
+               if (fieldbuilders_to_fields.Contains (fb))
+                       return false;
+
+               fieldbuilders_to_fields.Add (fb, f);
+               return true;
+       }
+
+       static public Field GetField (FieldInfo fb)
+       {
+               return (Field) fieldbuilders_to_fields [fb];
+       }
+       
        static Hashtable events;
 
        static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
@@ -797,8 +868,67 @@ public class TypeManager {
                
                return false;
        }
-       
+
+       //
+       // This is needed, because enumerations from assemblies
+       // do not report their underlyingtype, but they report
+       // themselves
+       //
+       public static Type EnumToUnderlying (Type t)
+       {
+               t = t.UnderlyingSystemType;
+               if (!TypeManager.IsEnumType (t))
+                       return t;
+               
+               TypeCode tc = Type.GetTypeCode (t);
+
+               switch (tc){
+               case TypeCode.Boolean:
+                       return TypeManager.bool_type;
+               case TypeCode.Byte:
+                       return TypeManager.byte_type;
+               case TypeCode.SByte:
+                       return TypeManager.sbyte_type;
+               case TypeCode.Char:
+                       return TypeManager.char_type;
+               case TypeCode.Int16:
+                       return TypeManager.short_type;
+               case TypeCode.UInt16:
+                       return TypeManager.ushort_type;
+               case TypeCode.Int32:
+                       return TypeManager.int32_type;
+               case TypeCode.UInt32:
+                       return TypeManager.uint32_type;
+               case TypeCode.Int64:
+                       return TypeManager.int64_type;
+               case TypeCode.UInt64:
+                       return TypeManager.uint64_type;
+               }
+               throw new Exception ("Unhandled typecode in enum" + tc);
+       }
 
+       /// <summary>
+       ///   Utility function that can be used to probe whether a type
+       ///   is managed or not.  
+       /// </summary>
+       public static bool VerifyUnManaged (Type t, Location loc)
+       {
+               if (t.IsValueType){
+                       //
+                       // FIXME: this is more complex, we actually need to
+                       // make sure that the type does not contain any
+                       // classes itself
+                       //
+                       return true;
+               }
+
+               Report.Error (
+                       208, loc,
+                       "Cannot take the address or size of a variable of a managed type ('" +
+                       CSharpName (t) + "')");
+               return false;   
+       }
+       
        /// <summary>
        ///   Returns the name of the indexer in a given type.
        /// </summary>
@@ -811,24 +941,52 @@ public class TypeManager {
        public static string IndexerPropertyName (Type t)
        {
                
-               //
-               // FIXME: Replace with something that works around S.R.E failure
-               //
-//#if FIXME
-//               System.Attribute attr;
-//
-//               attr = System.Attribute.GetCustomAttribute (t, TypeManager.default_member_type);
-//               
-//               if (attr != null)
-//                       {
-//                               DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
-//                               
-//                               return dma.MemberName;
-//                       }
-//#endif
+               if (t is TypeBuilder) {
+                       TypeContainer tc = (TypeContainer) builder_to_container [t];
+
+                       Attributes attrs = tc.OptAttributes;
+                       
+                       if (attrs == null || attrs.AttributeSections == null)
+                               return "Item";
+
+                       foreach (AttributeSection asec in attrs.AttributeSections) {
+
+                               if (asec.Attributes == null)
+                                       continue;
+
+                               foreach (Attribute a in asec.Attributes) {
+                                       if (a.Name.IndexOf ("DefaultMember") != -1) {
+                                               ArrayList pos_args = (ArrayList) a.Arguments [0];
+                                               Expression e = ((Argument) pos_args [0]).expr;
+
+                                               if (e is StringConstant)
+                                                       return ((StringConstant) e).Value;
+                                       }
+                               }
+                       }
+
+                       return "Item";
+               }
+               
+               System.Attribute attr = System.Attribute.GetCustomAttribute (t, TypeManager.default_member_type);
+               
+               if (attr != null)
+               {
+                       DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
+                       
+                       return dma.MemberName;
+               }
+
                return "Item";
        }
 
+       public static void MakePinned (LocalBuilder builder)
+       {
+               //
+               // FIXME: Flag the "LocalBuilder" type as being
+               // pinned.  Figure out API.
+               //
+       }
 }
 
 }