X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Frootcontext.cs;h=b429b974de11d5c2ee4ab09df266c47ff387ce9b;hb=5f0dc4802f69745ced8f32b39bd770f7bd134b8f;hp=cfea44aac0ba1edbf8fe56d2a533525fee558c9a;hpb=0b0e2fa27c7a81480d9af647659563425d0b29aa;p=mono.git diff --git a/mcs/mcs/rootcontext.cs b/mcs/mcs/rootcontext.cs index cfea44aac0b..b429b974de1 100755 --- a/mcs/mcs/rootcontext.cs +++ b/mcs/mcs/rootcontext.cs @@ -2,6 +2,7 @@ // rootcontext.cs: keeps track of our tree representation, and assemblies loaded. // // Author: Miguel de Icaza (miguel@ximian.com) +// Ravi Pratap (ravi@ximian.com) // // Licensed under the terms of the GNU GPL // @@ -20,29 +21,25 @@ namespace Mono.CSharp { // // Contains the parsed tree // - Tree tree; + static Tree tree; // - // Contains loaded assemblies and our generated code as we go. + // This hashtable contains all of the #definitions across the source code + // it is used by the ConditionalAttribute handler. // - public TypeManager TypeManager; - - // - // The System.Reflection.Emit CodeGenerator - // - CodeGen cg; - + public static Hashtable AllDefines = new Hashtable (); + // - // The module builder pointer. + // The list of global attributes (those that target the assembly) // - static ModuleBuilder mb; - + static Hashtable global_attributes = new Hashtable (); + // // Whether we are being linked against the standard libraries. // This is only used to tell whether `System.Object' should // have a parent or not. // - bool stdlib = true; + public static bool StdLib = true; // // This keeps track of the order in which classes were defined @@ -53,52 +50,65 @@ namespace Mono.CSharp { // or abstract as well as the parent names (to implement new, // override). // - ArrayList type_container_resolve_order; - ArrayList interface_resolve_order; - + static ArrayList type_container_resolve_order; + static ArrayList interface_resolve_order; + static ArrayList attribute_types; + // // Holds a reference to the Private Implementation Details // class. // - TypeBuilder impl_details_class; + static TypeBuilder impl_details_class; + public static int WarningLevel = 2; + // // Constructor // - public RootContext () + static RootContext () { - tree = new Tree (this); - TypeManager = new TypeManager (); + tree = new Tree (); + interface_resolve_order = new ArrayList (); + type_container_resolve_order = new ArrayList (); } - public Tree Tree { + static public Tree Tree { get { return tree; } } - public CodeGen CodeGen { - get { - return cg; - } - - set { - // - // Temporary hack, we should probably - // intialize `cg' rather than depending on - // external initialization of it. - // - cg = value; - mb = cg.ModuleBuilder; - } + static public string MainClass; + + public static void RegisterOrder (Interface iface) + { + interface_resolve_order.Add (iface); + } + + public static void RegisterOrder (TypeContainer tc) + { + type_container_resolve_order.Add (tc); } + public static void RegisterAttribute (TypeContainer tc) + { + if (attribute_types == null) + attribute_types = new ArrayList (); + + attribute_types.Add (tc); + } + // // The default compiler checked state // - public bool Checked = false; + static public bool Checked = false; - string MakeFQN (string nsn, string name) + // + // Whether to allow Unsafe code + // + static public bool Unsafe = false; + + static string MakeFQN (string nsn, string name) { string prefix = (nsn == "" ? "" : nsn + "."); @@ -112,44 +122,251 @@ namespace Mono.CSharp { // It creates the TypeBuilder's as it processes the user defined // types. // - public void ResolveTree () + static public void ResolveTree () { // - // Interfaces are processed first, as classes and + // Process the attribute types separately and before anything else + // + if (attribute_types != null) + foreach (TypeContainer tc in attribute_types) + tc.DefineType (); + + // + // Interfaces are processed next, as classes and // structs might inherit from an object or implement // a set of interfaces, we need to be able to tell // them appart by just using the TypeManager. // - TypeContainer root = Tree.Types; ArrayList ifaces = root.Interfaces; if (ifaces != null){ - interface_resolve_order = new ArrayList (); - - foreach (Interface i in ifaces) { - Type t = i.DefineInterface (mb); - if (t != null) - interface_resolve_order.Add (i); - } + foreach (Interface i in ifaces) + i.DefineType (); } - - type_container_resolve_order = new ArrayList (); + - foreach (TypeContainer tc in root.Types) { - Type t = tc.DefineType (mb); - if (t != null) - type_container_resolve_order.Add (tc); - } + foreach (TypeContainer tc in root.Types) + tc.DefineType (); if (root.Delegates != null) foreach (Delegate d in root.Delegates) - d.DefineDelegate (mb); + d.DefineType (); if (root.Enums != null) foreach (Enum e in root.Enums) - e.DefineEnum (mb); + e.DefineType (); + + } + + static void Error_TypeConflict (string name, Location loc) + { + Report.Error ( + 520, loc, "`" + name + "' conflicts with a predefined type"); + } + + static void Error_TypeConflict (string name) + { + Report.Error ( + 520, "`" + name + "' conflicts with a predefined type"); + } + + // + // Resolves a single class during the corlib bootstrap process + // + static TypeBuilder BootstrapCorlib_ResolveClass (TypeContainer root, string name) + { + object o = root.GetDefinition (name); + if (o == null){ + Report.Error (518, "The predefined type `" + name + "' is not defined"); + return null; + } + + if (!(o is Class)){ + if (o is DeclSpace){ + DeclSpace d = (DeclSpace) o; + + Error_TypeConflict (name, d.Location); + } else + Error_TypeConflict (name); + + return null; + } + + return ((DeclSpace) o).DefineType (); + } + + // + // Resolves a struct during the corlib bootstrap process + // + static void BootstrapCorlib_ResolveStruct (TypeContainer root, string name) + { + object o = root.GetDefinition (name); + if (o == null){ + Report.Error (518, "The predefined type `" + name + "' is not defined"); + return; + } + + if (!(o is Struct)){ + if (o is DeclSpace){ + DeclSpace d = (DeclSpace) o; + + Error_TypeConflict (name, d.Location); + } else + Error_TypeConflict (name); + + return; + } + + ((DeclSpace) o).DefineType (); + } + + // + // Resolves a struct during the corlib bootstrap process + // + static void BootstrapCorlib_ResolveInterface (TypeContainer root, string name) + { + object o = root.GetDefinition (name); + if (o == null){ + Report.Error (518, "The predefined type `" + name + "' is not defined"); + return; + } + + if (!(o is Interface)){ + if (o is DeclSpace){ + DeclSpace d = (DeclSpace) o; + + Error_TypeConflict (name, d.Location); + } else + Error_TypeConflict (name); + + return; + } + + ((DeclSpace) o).DefineType (); + } + + // + // Resolves a delegate during the corlib bootstrap process + // + static void BootstrapCorlib_ResolveDelegate (TypeContainer root, string name) + { + object o = root.GetDefinition (name); + if (o == null){ + Report.Error (518, "The predefined type `" + name + "' is not defined"); + Environment.Exit (0); + } + + if (!(o is Delegate)){ + Error_TypeConflict (name); + return; + } + + ((DeclSpace) o).DefineType (); + } + + + /// + /// Resolves the core types in the compiler when compiling with --nostdlib + /// + static public void ResolveCore () + { + TypeContainer root = Tree.Types; + + TypeManager.object_type = BootstrapCorlib_ResolveClass (root, "System.Object"); + TypeManager.value_type = BootstrapCorlib_ResolveClass (root, "System.ValueType"); + TypeManager.attribute_type = BootstrapCorlib_ResolveClass (root, "System.Attribute"); + + string [] interfaces_first_stage = { + "System.IComparable", "System.ICloneable", + "System.IConvertible", + + "System.Collections.IEnumerable", + "System.Collections.ICollection", + "System.Collections.IEnumerator", + "System.Collections.IList", + "System.IAsyncResult", + "System.IDisposable", + + "System.Runtime.Serialization.ISerializable", + + "System.Reflection.IReflect", + "System.Reflection.ICustomAttributeProvider" + }; + + foreach (string iname in interfaces_first_stage) + BootstrapCorlib_ResolveInterface (root, iname); + + // + // These are the base value types + // + string [] structs_first_stage = { + "System.Byte", "System.SByte", + "System.Int16", "System.UInt16", + "System.Int32", "System.UInt32", + "System.Int64", "System.UInt64", + }; + + foreach (string cname in structs_first_stage) + BootstrapCorlib_ResolveStruct (root, cname); + + // + // Now, we can load the enumerations, after this point, + // we can use enums. + // + TypeManager.InitEnumUnderlyingTypes (); + + string [] structs_second_stage = { + "System.Single", "System.Double", + "System.Char", "System.Boolean", + "System.Decimal", "System.Void", + "System.RuntimeFieldHandle", + "System.RuntimeTypeHandle", + "System.IntPtr" + }; + foreach (string cname in structs_second_stage) + BootstrapCorlib_ResolveStruct (root, cname); + + // + // These are classes that depends on the core interfaces + // + string [] classes_second_stage = { + "System.Reflection.MemberInfo", + "System.Type", + "System.Exception", + + // + // These are not really important in the order, but they + // are used by the compiler later on (typemanager/CoreLookupType-d) + // + "System.Runtime.CompilerServices.RuntimeHelpers", + "System.Reflection.DefaultMemberAttribute", + "System.Threading.Monitor", + + "System.AttributeUsageAttribute", + "System.Runtime.InteropServices.DllImportAttribute", + "System.Runtime.CompilerServices.MethodImplAttribute", + "System.Runtime.InteropServices.MarshalAsAttribute", + "System.Diagnostics.ConditionalAttribute", + "System.ObsoleteAttribute", + "System.ParamArrayAttribute", + "System.Security.UnverifiableCodeAttribute", + "System.Runtime.CompilerServices.IndexerNameAttribute", + "System.Runtime.InteropServices.InAttribute" + }; + + // We must store them here before calling BootstrapCorlib_ResolveDelegate. + TypeManager.string_type = BootstrapCorlib_ResolveClass (root, "System.String"); + TypeManager.enum_type = BootstrapCorlib_ResolveClass (root, "System.Enum"); + TypeManager.array_type = BootstrapCorlib_ResolveClass (root, "System.Array"); + TypeManager.multicast_delegate_type = BootstrapCorlib_ResolveClass (root, "System.MulticastDelegate"); + TypeManager.delegate_type = BootstrapCorlib_ResolveClass (root, "System.Delegate"); + + foreach (string cname in classes_second_stage) + BootstrapCorlib_ResolveClass (root, cname); + + BootstrapCorlib_ResolveDelegate (root, "System.AsyncCallback"); } // @@ -162,27 +379,44 @@ namespace Mono.CSharp { // methods, fields, etc) we need to "Define" them before we // can save the Assembly // - public void CloseTypes () + static public void CloseTypes () { TypeContainer root = Tree.Types; ArrayList ifaces = root.Interfaces; - if (ifaces != null) - foreach (Interface i in ifaces) - i.CloseType (); + if (root.Enums != null) + foreach (Enum en in root.Enums) + en.CloseType (); + + if (attribute_types != null) + foreach (TypeContainer tc in attribute_types) + tc.CloseType (); - foreach (TypeContainer tc in root.Types) - tc.CloseType (); + foreach (Interface iface in interface_resolve_order) + iface.CloseType (); + // + // We do this in two passes, first we close the structs, + // then the classes, because it seems the code needs it this + // way. If this is really what is going on, we should probably + // make sure that we define the structs in order as well. + // + foreach (TypeContainer tc in type_container_resolve_order){ + if (tc is Struct && tc.Parent == tree.Types){ + tc.CloseType (); + } + } + + foreach (TypeContainer tc in type_container_resolve_order){ + if (!(tc is Struct && tc.Parent == tree.Types)) + tc.CloseType (); + } + if (root.Delegates != null) foreach (Delegate d in root.Delegates) - d.CloseDelegate (); + d.CloseType (); - if (root.Enums != null) - foreach (Enum en in root.Enums) - en.CloseEnum (); - // // If we have a class, close it @@ -191,48 +425,158 @@ namespace Mono.CSharp { impl_details_class.CreateType (); } } - + // - // Public function used to locate types, this can only - // be used after the ResolveTree function has been invoked. + // This idea is from Felix Arrese-Igor // - // Returns: Type or null if they type can not be found. + // Returns : the implicit parent of a composite namespace string + // eg. Implicit parent of A.B is A // - public Type LookupType (TypeContainer tc, string name, bool silent) + static public string ImplicitParent (string ns) { - Type t; - - t = TypeManager.LookupType (MakeFQN (tc.Namespace.Name, name)); - if (t != null) - return t; + int i = ns.LastIndexOf ("."); + if (i < 0) + return null; + + return ns.Substring (0, i); + } + static Type NamespaceLookup (Namespace curr_ns, string name, Location loc) + { + Type t; + + // + // Try in the current namespace and all its implicit parents + // + for (string ns = curr_ns.Name; ns != null; ns = ImplicitParent (ns)) { + t = TypeManager.LookupType (MakeFQN (ns, name)); + if (t != null) + return t; + } + + // // It's possible that name already is fully qualified. So we do // a simple direct lookup without adding any namespace names - + // t = TypeManager.LookupType (name); if (t != null) return t; + + // + // Try the aliases in the current namespace + // + string alias = curr_ns.LookupAlias (name); + + if (alias != null) { + t = TypeManager.LookupType (alias); + if (t != null) + return t; + + t = TypeManager.LookupType (MakeFQN (alias, name)); + if (t != null) + return t; + } - for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){ + for (Namespace ns = curr_ns; ns != null; ns = ns.Parent) { + // + // Look in the namespace ns + // + t = TypeManager.LookupType (MakeFQN (ns.Name, name)); + if (t != null) + return t; + + // + // Then try with the using clauses + // ArrayList using_list = ns.UsingTable; if (using_list == null) continue; - foreach (string n in using_list){ - t = TypeManager.LookupType (MakeFQN (n, name)); + Type match = null; + foreach (Namespace.UsingEntry ue in using_list) { + match = TypeManager.LookupType (MakeFQN (ue.Name, name)); + if (match != null){ + if (t != null){ + DeclSpace.Error_AmbiguousTypeReference (loc, name, t, match); + return null; + } + + t = match; + ue.Used = true; + } + } + if (t != null) + return t; + + // + // Try with aliases + // + string a = ns.LookupAlias (name); + if (a != null) { + t = TypeManager.LookupType (a); + if (t != null) + return t; + + t = TypeManager.LookupType (MakeFQN (a, name)); if (t != null) return t; } } - // For the case the type we are looking for is nested within this one. - t = TypeManager.LookupType (tc.Name + "." + name); - if (t != null) - return t; - + return null; + } + + // + // Public function used to locate types, this can only + // be used after the ResolveTree function has been invoked. + // + // Returns: Type or null if they type can not be found. + // + // Come to think of it, this should be a DeclSpace + // + static public Type LookupType (DeclSpace ds, string name, bool silent, Location loc) + { + Type t; + + if (ds.Cache.Contains (name)){ + t = (Type) ds.Cache [name]; + if (t != null) + return t; + } else { + // + // For the case the type we are looking for is nested within this one + // or is in any base class + // + DeclSpace containing_ds = ds; + while (containing_ds != null){ + Type current_type = containing_ds.TypeBuilder; + + while (current_type != null) { + // + // nested class + // + t = TypeManager.LookupType (current_type.FullName + "." + name); + if (t != null){ + ds.Cache [name] = t; + return t; + } + + current_type = current_type.BaseType; + } + + containing_ds = containing_ds.Parent; + } + + t = NamespaceLookup (ds.Namespace, name, loc); + if (t != null){ + ds.Cache [name] = t; + return t; + } + } + if (!silent) - Report.Error (246, "Cannot find type `"+name+"'"); + Report.Error (246, loc, "Cannot find type `"+name+"'"); return null; } @@ -241,12 +585,12 @@ namespace Mono.CSharp { // This is the silent version of LookupType, you can use this // to `probe' for a type // - public Type LookupType (TypeContainer tc, string name) + static public Type LookupType (TypeContainer tc, string name, Location loc) { - return LookupType (tc, name, true); + return LookupType (tc, name, true, loc); } - public bool IsNamespace (string name) + static public bool IsNamespace (string name) { Namespace ns; @@ -260,72 +604,200 @@ namespace Mono.CSharp { return false; } + static void Report1530 (Location loc) + { + Report.Error (1530, loc, "Keyword new not allowed for namespace elements"); + } + + static public void PopulateCoreType (TypeContainer root, string name) + { + DeclSpace ds = (DeclSpace) root.GetDefinition (name); + + ds.DefineMembers (root); + ds.Define (root); + } + + static public void BootCorlib_PopulateCoreTypes () + { + TypeContainer root = tree.Types; + + PopulateCoreType (root, "System.Object"); + PopulateCoreType (root, "System.ValueType"); + PopulateCoreType (root, "System.Attribute"); + } + // // Populates the structs and classes with fields and methods // // // This is invoked after all interfaces, structs and classes // have been defined through `ResolveTree' - public void PopulateTypes () + static public void PopulateTypes () { - if (interface_resolve_order != null) + TypeContainer root = Tree.Types; + + if (attribute_types != null) + foreach (TypeContainer tc in attribute_types) + tc.DefineMembers (root); + + if (interface_resolve_order != null){ foreach (Interface iface in interface_resolve_order) - iface.Populate (); + if ((iface.ModFlags & Modifiers.NEW) == 0) + iface.DefineMembers (root); + else + Report1530 (iface.Location); + } - if (type_container_resolve_order != null) - foreach (TypeContainer tc in type_container_resolve_order) - tc.Populate (); - TypeContainer root = Tree.Types; + if (type_container_resolve_order != null){ + if (RootContext.StdLib){ + foreach (TypeContainer tc in type_container_resolve_order) { + if ((tc.ModFlags & Modifiers.NEW) == 0) + tc.DefineMembers (root); + else + Report1530 (tc.Location); + } + } else { + foreach (TypeContainer tc in type_container_resolve_order) { + // When compiling corlib, these types have already been + // populated from BootCorlib_PopulateCoreTypes (). + if (((tc.Name == "System.Object") || + (tc.Name == "System.Attribute") || + (tc.Name == "System.ValueType"))) + continue; + + if ((tc.ModFlags & Modifiers.NEW) == 0) + tc.DefineMembers (root); + else + Report1530 (tc.Location); + } + } + } ArrayList delegates = root.Delegates; - if (delegates != null) + if (delegates != null){ foreach (Delegate d in delegates) - d.Populate (root); + if ((d.ModFlags & Modifiers.NEW) == 0) + d.DefineMembers (root); + else + Report1530 (d.Location); + } ArrayList enums = root.Enums; - if (enums != null) + if (enums != null){ foreach (Enum en in enums) - en.Populate (root); - + if ((en.ModFlags & Modifiers.NEW) == 0) + en.DefineMembers (root); + else + Report1530 (en.Location); + } } - public void EmitCode () + static public void DefineTypes () { - if (type_container_resolve_order != null) - foreach (TypeContainer tc in type_container_resolve_order) - tc.Emit (); - } - - // - // Compiling against Standard Libraries property. - // - public bool StdLib { - get { - return stdlib; + TypeContainer root = Tree.Types; + + if (attribute_types != null) + foreach (TypeContainer tc in attribute_types) + tc.Define (root); + + if (interface_resolve_order != null){ + foreach (Interface iface in interface_resolve_order) + if ((iface.ModFlags & Modifiers.NEW) == 0) + iface.Define (root); } - set { - stdlib = value; + + if (type_container_resolve_order != null){ + foreach (TypeContainer tc in type_container_resolve_order) { + // When compiling corlib, these types have already been + // populated from BootCorlib_PopulateCoreTypes (). + if (!RootContext.StdLib && + ((tc.Name == "System.Object") || + (tc.Name == "System.Attribute") || + (tc.Name == "System.ValueType"))) + continue; + + if ((tc.ModFlags & Modifiers.NEW) == 0) + tc.Define (root); + } } - } - public static ModuleBuilder ModuleBuilder { - get { - return mb; + ArrayList delegates = root.Delegates; + if (delegates != null){ + foreach (Delegate d in delegates) + if ((d.ModFlags & Modifiers.NEW) == 0) + d.Define (root); + } + + ArrayList enums = root.Enums; + if (enums != null){ + foreach (Enum en in enums) + if ((en.ModFlags & Modifiers.NEW) == 0) + en.Define (root); } } + static public void EmitCode () + { + // + // Because of the strange way in which we do things, global + // attributes must be processed first. + // + if (global_attributes.Count > 0){ + AssemblyBuilder ab = CodeGen.AssemblyBuilder; + TypeContainer dummy = new TypeContainer (null, "", new Location (-1)); + EmitContext temp_ec = new EmitContext ( + dummy, Mono.CSharp.Location.Null, null, null, 0, false); + + foreach (DictionaryEntry de in global_attributes){ + Namespace ns = (Namespace) de.Key; + Attributes attrs = (Attributes) de.Value; + + dummy.Namespace = ns; + Attribute.ApplyAttributes (temp_ec, ab, ab, attrs); + } + } + + if (attribute_types != null) + foreach (TypeContainer tc in attribute_types) + tc.Emit (); + + if (type_container_resolve_order != null) { + foreach (TypeContainer tc in type_container_resolve_order) + tc.EmitConstants (); + + foreach (TypeContainer tc in type_container_resolve_order) + tc.Emit (); + } + + if (Unsafe) { + if (TypeManager.unverifiable_code_ctor == null) { + Console.WriteLine ("Internal error ! Cannot set unverifiable code attribute."); + return; + } + + CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.unverifiable_code_ctor, + new object [0]); + CodeGen.ModuleBuilder.SetCustomAttribute (cb); + } + } + // // Public Field, used to track which method is the public entry // point. // - public MethodInfo EntryPoint; + static public MethodInfo EntryPoint; + + // + // Track the location of the entry point. + // + static public Location EntryPointLocation; // // These are used to generate unique names on the structs and fields. // - int field_count; + static int field_count; // // Makes an initialized struct, returns the field builder that @@ -341,14 +813,14 @@ namespace Mono.CSharp { // // 2. Define the field on the impl_details_class // - public FieldBuilder MakeStaticData (byte [] data) + static public FieldBuilder MakeStaticData (byte [] data) { FieldBuilder fb; int size = data.Length; if (impl_details_class == null) - impl_details_class = mb.DefineType ( - "", TypeAttributes.NotPublic); + impl_details_class = CodeGen.ModuleBuilder.DefineType ( + "", TypeAttributes.NotPublic, TypeManager.object_type); fb = impl_details_class.DefineInitializedData ( "$$field-" + (field_count++), data, @@ -356,6 +828,21 @@ namespace Mono.CSharp { return fb; } + + // + // Adds a global attribute that was declared in `container', + // the attribute is in `attr', and it was defined at `loc' + // + static public void AddGlobalAttributeSection (TypeContainer container, AttributeSection attr) + { + Namespace ns = container.Namespace; + Attributes a = (Attributes) global_attributes [ns]; + + if (a == null) + global_attributes [ns] = new Attributes (attr); + else + a.AddAttributeSection (attr); + } } }