2002-03-06 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / typemanager.cs
index 355fd3208c0f21e0473a38c404229b71d05226e0..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,8 +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
@@ -79,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.
@@ -90,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
@@ -155,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 ();
@@ -172,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)
@@ -244,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>
@@ -252,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>
@@ -327,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;
        }
@@ -390,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");
@@ -419,6 +441,10 @@ public class TypeManager {
                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.
@@ -456,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
@@ -626,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);
                
@@ -646,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;
                
@@ -685,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;
 
@@ -705,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)
@@ -829,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>
@@ -843,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.
+               //
+       }
 }
 
 }