Rework gc descriptor to include size information in more cases.
[mono.git] / mcs / mcs / roottypes.cs
index bea0408a25697387bf478c48682b30b1be474d56..48f2b266b3b7637a15fdbf0c15a8dfebc27f70c6 100644 (file)
@@ -8,6 +8,7 @@
 //
 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
 // Copyright 2003-2008 Novell, Inc.
+// Copyright 2011 Xamarin Inc
 //
 
 using System;
@@ -28,18 +29,16 @@ namespace Mono.CSharp
        //
        // Module (top-level type) container
        //
-       public class ModuleContainer : TypeContainer
+       public sealed class ModuleContainer : TypeContainer
        {
+#if STATIC
                //
                // Compiler generated container for static data
                //
                sealed class StaticDataContainer : CompilerGeneratedClass
                {
-                       Dictionary<int, Struct> size_types;
+                       readonly Dictionary<int, Struct> size_types;
                        new int fields;
-#if !STATIC
-                       static MethodInfo set_data;
-#endif
 
                        public StaticDataContainer (ModuleContainer module)
                                : base (module, new MemberName ("<PrivateImplementationDetails>" + module.builder.ModuleVersionId.ToString ("B"), Location.Null), Modifiers.STATIC)
@@ -65,69 +64,69 @@ namespace Mono.CSharp
                                        // DefineInitializedData because it creates public type,
                                        // and its name is not unique among modules
                                        //
-                                       size_type = new Struct (null, this, new MemberName ("$ArrayType=" + data.Length, Location), Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, null);
+                                       size_type = new Struct (null, this, new MemberName ("$ArrayType=" + data.Length, loc), Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, null);
                                        size_type.CreateType ();
                                        size_type.DefineType ();
 
                                        size_types.Add (data.Length, size_type);
 
-                                       var pa = Module.PredefinedAttributes.StructLayout;
-                                       if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.short_type)) {
-                                               var argsEncoded = new AttributeEncoder (false);
-                                               argsEncoded.Encode ((short) LayoutKind.Explicit);
-
-                                               var field_size = pa.GetField ("Size", TypeManager.int32_type, Location);
-                                               var pack = pa.GetField ("Pack", TypeManager.int32_type, Location);
-                                               if (field_size != null) {
-                                                       argsEncoded.EncodeNamedArguments (
-                                                               new[] { field_size, pack },
-                                                               new[] { new IntConstant ((int) data.Length, Location), new IntConstant (1, Location) }
-                                                       );
-                                               }
-
-                                               pa.EmitAttribute (size_type.TypeBuilder, argsEncoded);
-                                       }
+                                       // It has to work even if StructLayoutAttribute does not exist
+                                       size_type.TypeBuilder.__SetLayout (1, data.Length);
                                }
 
                                var name = "$field-" + fields.ToString ("X");
                                ++fields;
                                const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL;
                                var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
-#if STATIC
                                fbuilder.__SetDataAndRVA (data);
-#else
-                               if (set_data == null)
-                                       set_data = typeof (FieldBuilder).GetMethod ("SetRVAData", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
-
-                               try {
-                                       set_data.Invoke (fbuilder, new object[] { data });
-                               } catch {
-                                       Report.RuntimeMissingSupport (loc, "SetRVAData");
-                               }
-#endif
 
                                return new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
                        }
                }
 
-               public CharSet DefaultCharSet = CharSet.Ansi;
+               StaticDataContainer static_data;
+
+               //
+               // Makes const data field inside internal type container
+               //
+               public FieldSpec MakeStaticData (byte[] data, Location loc)
+               {
+                       if (static_data == null) {
+                               static_data = new StaticDataContainer (this);
+                               static_data.CreateType ();
+                               static_data.DefineType ();
+
+                               AddCompilerGeneratedClass (static_data);
+                       }
+
+                       return static_data.DefineInitializedData (data, loc);
+               }
+#endif
+
+               public CharSet? DefaultCharSet;
                public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
 
-               Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
-               StaticDataContainer static_data;
+               readonly Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
+               readonly Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> array_types;
+               readonly Dictionary<TypeSpec, PointerContainer> pointer_types;
+               readonly Dictionary<TypeSpec, ReferenceContainer> reference_types;
+               readonly Dictionary<TypeSpec, MethodSpec> attrs_cache;
+
+               // Used for unique namespaces/types during parsing
+               Dictionary<MemberName, ITypesContainer> defined_type_containers;
 
                AssemblyDefinition assembly;
                readonly CompilerContext context;
                readonly RootNamespace global_ns;
-               Dictionary<string, RootNamespace> alias_ns;
+               readonly Dictionary<string, RootNamespace> alias_ns;
 
                ModuleBuilder builder;
 
-               bool has_default_charset;
                bool has_extenstion_method;
 
                PredefinedAttributes predefined_attributes;
                PredefinedTypes predefined_types;
+               PredefinedMembers predefined_members;
 
                static readonly string[] attribute_targets = new string[] { "assembly", "module" };
 
@@ -142,10 +141,31 @@ namespace Mono.CSharp
                        anonymous_types = new Dictionary<int, List<AnonymousTypeClass>> ();
                        global_ns = new GlobalRootNamespace ();
                        alias_ns = new Dictionary<string, RootNamespace> ();
+                       array_types = new Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ();
+                       pointer_types = new Dictionary<TypeSpec, PointerContainer> ();
+                       reference_types = new Dictionary<TypeSpec, ReferenceContainer> ();
+                       attrs_cache = new Dictionary<TypeSpec, MethodSpec> ();
+
+                       defined_type_containers = new Dictionary<MemberName, ITypesContainer> ();
                }
 
                #region Properties
 
+               internal Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ArrayTypesCache {
+                       get {
+                               return array_types;
+                       }
+               }
+
+               //
+               // Cache for parameter-less attributes
+               //
+               internal Dictionary<TypeSpec, MethodSpec> AttributeConstructorCache {
+                       get {
+                               return attrs_cache;
+                       }
+               }
+
                public override AttributeTargets AttributeTargets {
                        get {
                                return AttributeTargets.Assembly;
@@ -170,9 +190,17 @@ namespace Mono.CSharp
                        }
                }
 
+               internal DocumentationBuilder DocumentationBuilder {
+                       get; set;
+               }
+
+               public Evaluator Evaluator {
+                       get; set;
+               }
+
                public bool HasDefaultCharSet {
                        get {
-                               return has_default_charset;
+                               return DefaultCharSet.HasValue;
                        }
                }
 
@@ -185,6 +213,10 @@ namespace Mono.CSharp
                        }
                }
 
+               public bool HasTypesFullyDefined {
+                       get; set;
+               }
+
                //
                // Returns module global:: namespace
                //
@@ -200,18 +232,36 @@ namespace Mono.CSharp
                        }
                }
 
+               internal Dictionary<TypeSpec, PointerContainer> PointerTypesCache {
+                       get {
+                               return pointer_types;
+                       }
+               }
+
                internal PredefinedAttributes PredefinedAttributes {
                        get {
                                return predefined_attributes;
                        }
                }
 
+               internal PredefinedMembers PredefinedMembers {
+                       get {
+                               return predefined_members;
+                       }
+               }
+
                internal PredefinedTypes PredefinedTypes {
                        get {
                                return predefined_types;
                        }
                }
 
+               internal Dictionary<TypeSpec, ReferenceContainer> ReferenceTypesCache {
+                       get {
+                               return reference_types;
+                       }
+               }
+
                public override string[] ValidAttributeTargets {
                        get {
                                return attribute_targets;
@@ -220,6 +270,11 @@ namespace Mono.CSharp
 
                #endregion
 
+               public override void Accept (StructuralVisitor visitor)
+               {
+                       visitor.Visit (this);
+               }
+
                public void AddAnonymousType (AnonymousTypeClass type)
                {
                        List<AnonymousTypeClass> existing;
@@ -232,21 +287,16 @@ namespace Mono.CSharp
                        existing.Add (type);
                }
 
-               public void AddAttributes (List<Attribute> attrs)
-               {
-                       AddAttributes (attrs, this);
-               }
-
-               public void AddAttributes (List<Attribute> attrs, IMemberContext context)
+               public void AddAttribute (Attribute attr, IMemberContext context)
                {
-                       foreach (Attribute a in attrs)
-                               a.AttachTo (this, context);
+                       attr.AttachTo (this, context);
 
                        if (attributes == null) {
-                               attributes = new Attributes (attrs);
+                               attributes = new Attributes (attr);
                                return;
                        }
-                       attributes.AddAttributes (attrs);
+
+                       attributes.AddAttribute (attr);
                }
 
                public override TypeContainer AddPartial (TypeContainer nextPart)
@@ -261,7 +311,25 @@ namespace Mono.CSharp
                                return;
                        }
 
-                       if (a.Type == pa.CLSCompliant) {
+                       if (a.Type == pa.DefaultCharset) {
+                               switch (a.GetCharSetValue ()) {
+                               case CharSet.Ansi:
+                               case CharSet.None:
+                                       break;
+                               case CharSet.Auto:
+                                       DefaultCharSet = CharSet.Auto;
+                                       DefaultCharSetType = TypeAttributes.AutoClass;
+                                       break;
+                               case CharSet.Unicode:
+                                       DefaultCharSet = CharSet.Unicode;
+                                       DefaultCharSetType = TypeAttributes.UnicodeClass;
+                                       break;
+                               default:
+                                       Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid",
+                                               a.GetSignatureForError ());
+                                       break;
+                               }
+                       } else if (a.Type == pa.CLSCompliant) {
                                Attribute cls = DeclaringAssembly.CLSCompliantAttribute;
                                if (cls == null) {
                                        Report.Warning (3012, 1, a.Location,
@@ -299,7 +367,7 @@ namespace Mono.CSharp
                public RootNamespace CreateRootNamespace (string alias)
                {
                        if (alias == global_ns.Alias) {
-                               NamespaceEntry.Error_GlobalNamespaceRedefined (Location.Null, Report);
+                               RootNamespace.Error_GlobalNamespaceRedefined (Report, Location.Null);
                                return global_ns;
                        }
 
@@ -312,24 +380,33 @@ namespace Mono.CSharp
                        return rn;
                }
 
-               public new void Define ()
+               public void Create (AssemblyDefinition assembly, ModuleBuilder moduleBuilder)
                {
-                       builder = assembly.CreateModuleBuilder ();
-
-                       // FIXME: Temporary hack for repl to reset
-                       static_data = null;
+                       this.assembly = assembly;
+                       builder = moduleBuilder;
+               }
 
-                       // TODO: It should be done much later when the types are resolved
-                       // but that require DefineType clean-up
-                       ResolveGlobalAttributes ();
+               public new void CreateType ()
+               {
+                       // Release cache used by parser only
+                       if (Evaluator == null)
+                               defined_type_containers = null;
+                       else
+                               defined_type_containers.Clear ();
 
                        foreach (TypeContainer tc in types)
                                tc.CreateType ();
+               }
 
-                       InitializePredefinedTypes ();
-
-                       foreach (TypeContainer tc in types)
-                               tc.DefineType ();
+               public new void Define ()
+               {
+                       foreach (TypeContainer tc in types) {
+                               try {
+                                       tc.DefineType ();
+                               } catch (Exception e) {
+                                       throw new InternalErrorException (tc, e);
+                               }
+                       }
 
                        foreach (TypeContainer tc in types)
                                tc.ResolveTypeParameters ();
@@ -341,6 +418,8 @@ namespace Mono.CSharp
                                        throw new InternalErrorException (tc, e);
                                }
                        }
+
+                       HasTypesFullyDefined = true;
                }
 
                public override void Emit ()
@@ -348,7 +427,7 @@ namespace Mono.CSharp
                        if (OptAttributes != null)
                                OptAttributes.Emit ();
 
-                       if (RootContext.Unsafe) {
+                       if (Compiler.Settings.Unsafe) {
                                var pa = PredefinedAttributes.UnverifiableCode;
                                if (pa.IsDefined)
                                        pa.EmitAttribute (builder);
@@ -371,6 +450,12 @@ namespace Mono.CSharp
                                        c.EmitType ();
                }
 
+               internal override void GenerateDocComment (DocumentationBuilder builder)
+               {
+                       foreach (var tc in types)
+                               tc.GenerateDocComment (builder);
+               }
+
                public AnonymousTypeClass GetAnonymousType (IList<AnonymousTypeParameter> parameters)
                {
                        List<AnonymousTypeClass> candidates;
@@ -407,6 +492,7 @@ namespace Mono.CSharp
                {
                        predefined_attributes = new PredefinedAttributes (this);
                        predefined_types = new PredefinedTypes (this);
+                       predefined_members = new PredefinedMembers (this);
                }
 
                public override bool IsClsComplianceRequired ()
@@ -414,84 +500,65 @@ namespace Mono.CSharp
                        return DeclaringAssembly.IsCLSCompliant;
                }
 
-               //
-               // Makes const data field inside internal type container
-               //
-               public FieldSpec MakeStaticData (byte[] data, Location loc)
+               protected override bool AddMemberType (TypeContainer tc)
                {
-                       if (static_data == null) {
-                               static_data = new StaticDataContainer (this);
-                               static_data.CreateType ();
-                               static_data.DefineType ();
+                       if (AddTypesContainer (tc)) {
+                               if ((tc.ModFlags & Modifiers.PARTIAL) != 0)
+                                       defined_names.Add (tc.Name, tc);
 
-                               AddCompilerGeneratedClass (static_data);
+                               tc.NamespaceEntry.NS.AddType (this, tc.Definition);
+                               return true;
                        }
 
-                       return static_data.DefineInitializedData (data, loc);
+                       return false;
                }
 
-               protected override bool AddMemberType (TypeContainer ds)
+               public bool AddTypesContainer (ITypesContainer container)
                {
-                       if (!AddToContainer (ds, ds.Name))
-                               return false;
-                       ds.NamespaceEntry.NS.AddType (ds.Definition);
-                       return true;
-               }
-
-               protected override void RemoveMemberType (DeclSpace ds)
-               {
-                       ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
-                       base.RemoveMemberType (ds);
-               }
+                       var mn = container.MemberName;
+                       ITypesContainer found;
+                       if (!defined_type_containers.TryGetValue (mn, out found)) {
+                               defined_type_containers.Add (mn, container);
+                               return true;
+                       }
 
-               /// <summary>
-               /// It is called very early therefore can resolve only predefined attributes
-               /// </summary>
-               void ResolveGlobalAttributes ()
-               {
-                       if (OptAttributes == null)
-                               return;
+                       if (container is NamespaceContainer && found is NamespaceContainer)
+                               return true;
 
-                       if (!OptAttributes.CheckTargets ())
-                               return;
+                       var container_tc = container as TypeContainer;
+                       var found_tc = found as TypeContainer;
+                       if (container_tc != null && found_tc != null && container_tc.Kind == found_tc.Kind) {
+                               if ((found_tc.ModFlags & container_tc.ModFlags & Modifiers.PARTIAL) != 0) {
+                                       return false;
+                               }
 
-                       // FIXME: Define is wrong as the type may not exist yet
-                       var DefaultCharSet_attr = new PredefinedAttribute (this, "System.Runtime.InteropServices", "DefaultCharSetAttribute");
-                       DefaultCharSet_attr.Define ();
-                       Attribute a = ResolveModuleAttribute (DefaultCharSet_attr);
-                       if (a != null) {
-                               has_default_charset = true;
-                               DefaultCharSet = a.GetCharSetValue ();
-                               switch (DefaultCharSet) {
-                               case CharSet.Ansi:
-                               case CharSet.None:
-                                       break;
-                               case CharSet.Auto:
-                                       DefaultCharSetType = TypeAttributes.AutoClass;
-                                       break;
-                               case CharSet.Unicode:
-                                       DefaultCharSetType = TypeAttributes.UnicodeClass;
-                                       break;
-                               default:
-                                       Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid", 
-                                               DefaultCharSet_attr.GetSignatureForError ());
-                                       break;
+                               if (((found_tc.ModFlags | container_tc.ModFlags) & Modifiers.PARTIAL) != 0) {
+                                       Report.SymbolRelatedToPreviousError (found_tc);
+                                       Error_MissingPartialModifier (container_tc);
+                                       return false;
                                }
                        }
+
+                       string ns = mn.Left != null ? mn.Left.GetSignatureForError () : Module.GlobalRootNamespace.GetSignatureForError ();
+                       mn = new MemberName (mn.Name, mn.TypeArguments, mn.Location);
+
+                       Report.SymbolRelatedToPreviousError (found.Location, "");
+                       Report.Error (101, container.Location,
+                               "The namespace `{0}' already contains a definition for `{1}'",
+                               ns, mn.GetSignatureForError ());
+                       return false;
                }
 
-               public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type)
+               protected override void RemoveMemberType (TypeContainer ds)
                {
-                       Attribute a = OptAttributes.Search ("assembly", a_type);
-                       if (a != null) {
-                               a.Resolve ();
-                       }
-                       return a;
+                       defined_type_containers.Remove (ds.MemberName);
+                       ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
+                       base.RemoveMemberType (ds);
                }
 
-               Attribute ResolveModuleAttribute (PredefinedAttribute a_type)
+               public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type)
                {
-                       Attribute a = OptAttributes.Search ("module", a_type);
+                       Attribute a = OptAttributes.Search ("assembly", a_type);
                        if (a != null) {
                                a.Resolve ();
                        }
@@ -505,11 +572,11 @@ namespace Mono.CSharp
                }
        }
 
-       class RootDeclSpace : TypeContainer {
-               public RootDeclSpace (NamespaceEntry ns)
+       sealed class RootDeclSpace : TypeContainer {
+               public RootDeclSpace (ModuleContainer module, NamespaceContainer ns)
                        : base (ns, null, MemberName.Null, null, 0)
                {
-                       PartialContainer = RootContext.ToplevelTypes;
+                       PartialContainer = module;
                }
 
                public override AttributeTargets AttributeTargets {
@@ -537,11 +604,21 @@ namespace Mono.CSharp
                        }
                }
 
+               public override void Accept (StructuralVisitor visitor)
+               {
+                       throw new InternalErrorException ("should not be called");
+               }
+
                public override bool IsClsComplianceRequired ()
                {
                        return PartialContainer.IsClsComplianceRequired ();
                }
 
+               public override ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
+               {
+                       return null;
+               }
+
                public override FullNamedExpression LookupNamespaceAlias (string name)
                {
                        return NamespaceEntry.LookupNamespaceAlias (name);