2 // rootcontext.cs: keeps track of our tree representation, and assemblies loaded.
4 // Author: Miguel de Icaza (miguel@ximian.com)
5 // Ravi Pratap (ravi@ximian.com)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
12 using System.Collections;
13 using System.Reflection;
14 using System.Reflection.Emit;
15 using System.Diagnostics;
17 namespace Mono.CSharp {
19 public class RootContext {
22 // Contains the parsed tree
27 // This hashtable contains all of the #definitions across the source code
28 // it is used by the ConditionalAttribute handler.
30 public static Hashtable AllDefines = new Hashtable ();
33 // Whether we are being linked against the standard libraries.
34 // This is only used to tell whether `System.Object' should
35 // have a parent or not.
37 public static bool StdLib = true;
40 // This keeps track of the order in which classes were defined
41 // so that we can poulate them in that order.
43 // Order is important, because we need to be able to tell by
44 // examining the parent's list of methods which ones are virtual
45 // or abstract as well as the parent names (to implement new,
48 static ArrayList type_container_resolve_order;
49 static ArrayList interface_resolve_order;
50 static ArrayList attribute_types;
53 // Holds a reference to the Private Implementation Details
56 static ArrayList helper_classes;
58 static TypeBuilder impl_details_class;
60 public static int WarningLevel = 2;
62 public static Target Target = Target.Exe;
63 public static string TargetExt = ".exe";
65 public static bool VerifyClsCompliance = true;
68 // If set, enable C# version 2 features
70 public static bool V2 = true;
73 // We keep strongname related info here because
74 // it's also used as complier options from CSC 8.x
76 public static string StrongNameKeyFile;
77 public static string StrongNameKeyContainer;
78 public static bool StrongNameDelaySign = false;
86 interface_resolve_order = new ArrayList ();
87 type_container_resolve_order = new ArrayList ();
90 public static bool NeedsEntryPoint {
92 return RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe;
96 static public Tree Tree {
102 static public string MainClass;
104 public static void RegisterOrder (Interface iface)
106 interface_resolve_order.Add (iface);
109 public static void RegisterOrder (TypeContainer tc)
111 type_container_resolve_order.Add (tc);
114 public static void RegisterAttribute (TypeContainer tc)
116 if (attribute_types == null)
117 attribute_types = new ArrayList ();
119 attribute_types.Add (tc);
123 // The default compiler checked state
125 static public bool Checked = false;
128 // Whether to allow Unsafe code
130 static public bool Unsafe = false;
132 static string MakeFQN (string nsn, string name)
136 return String.Concat (nsn, ".", name);
140 // This function is used to resolve the hierarchy tree.
141 // It processes interfaces, structs and classes in that order.
143 // It creates the TypeBuilder's as it processes the user defined
146 static public void ResolveTree ()
149 // Process the attribute types separately and before anything else
151 if (attribute_types != null)
152 foreach (TypeContainer tc in attribute_types)
156 // Interfaces are processed next, as classes and
157 // structs might inherit from an object or implement
158 // a set of interfaces, we need to be able to tell
159 // them appart by just using the TypeManager.
161 TypeContainer root = Tree.Types;
163 ArrayList ifaces = root.Interfaces;
165 foreach (Interface i in ifaces)
169 foreach (TypeContainer tc in root.Types)
172 if (root.Delegates != null)
173 foreach (Delegate d in root.Delegates)
176 if (root.Enums != null)
177 foreach (Enum e in root.Enums)
181 static void Error_TypeConflict (string name, Location loc)
184 520, loc, "`" + name + "' conflicts with a predefined type");
187 static void Error_TypeConflict (string name)
190 520, "`" + name + "' conflicts with a predefined type");
194 // Resolves a single class during the corlib bootstrap process
196 static TypeBuilder BootstrapCorlib_ResolveClass (TypeContainer root, string name)
198 object o = root.GetDefinition (name);
200 Report.Error (518, "The predefined type `" + name + "' is not defined");
206 DeclSpace d = (DeclSpace) o;
208 Error_TypeConflict (name, d.Location);
210 Error_TypeConflict (name);
215 return ((DeclSpace) o).DefineType ();
219 // Resolves a struct during the corlib bootstrap process
221 static void BootstrapCorlib_ResolveStruct (TypeContainer root, string name)
223 object o = root.GetDefinition (name);
225 Report.Error (518, "The predefined type `" + name + "' is not defined");
231 DeclSpace d = (DeclSpace) o;
233 Error_TypeConflict (name, d.Location);
235 Error_TypeConflict (name);
240 ((DeclSpace) o).DefineType ();
244 // Resolves a struct during the corlib bootstrap process
246 static void BootstrapCorlib_ResolveInterface (TypeContainer root, string name)
248 object o = root.GetDefinition (name);
250 Report.Error (518, "The predefined type `" + name + "' is not defined");
254 if (!(o is Interface)){
256 DeclSpace d = (DeclSpace) o;
258 Error_TypeConflict (name, d.Location);
260 Error_TypeConflict (name);
265 ((DeclSpace) o).DefineType ();
269 // Resolves a delegate during the corlib bootstrap process
271 static void BootstrapCorlib_ResolveDelegate (TypeContainer root, string name)
273 object o = root.GetDefinition (name);
275 Report.Error (518, "The predefined type `" + name + "' is not defined");
276 Environment.Exit (1);
279 if (!(o is Delegate)){
280 Error_TypeConflict (name);
284 ((DeclSpace) o).DefineType ();
289 /// Resolves the core types in the compiler when compiling with --nostdlib
291 static public void ResolveCore ()
293 TypeContainer root = Tree.Types;
295 TypeManager.object_type = BootstrapCorlib_ResolveClass (root, "System.Object");
296 TypeManager.value_type = BootstrapCorlib_ResolveClass (root, "System.ValueType");
297 TypeManager.attribute_type = BootstrapCorlib_ResolveClass (root, "System.Attribute");
299 string [] interfaces_first_stage = {
300 "System.IComparable", "System.ICloneable",
301 "System.IConvertible",
303 "System.Collections.IEnumerable",
304 "System.Collections.ICollection",
305 "System.Collections.IEnumerator",
306 "System.Collections.IList",
307 "System.IAsyncResult",
308 "System.IDisposable",
310 "System.Runtime.Serialization.ISerializable",
312 "System.Reflection.IReflect",
313 "System.Reflection.ICustomAttributeProvider",
318 "System.Collections.Generic.IEnumerator!1",
319 "System.Collections.Generic.IEnumerable!1"
322 foreach (string iname in interfaces_first_stage)
323 BootstrapCorlib_ResolveInterface (root, iname);
326 // These are the base value types
328 string [] structs_first_stage = {
329 "System.Byte", "System.SByte",
330 "System.Int16", "System.UInt16",
331 "System.Int32", "System.UInt32",
332 "System.Int64", "System.UInt64",
335 foreach (string cname in structs_first_stage)
336 BootstrapCorlib_ResolveStruct (root, cname);
339 // Now, we can load the enumerations, after this point,
342 TypeManager.InitEnumUnderlyingTypes ();
344 string [] structs_second_stage = {
345 "System.Single", "System.Double",
346 "System.Char", "System.Boolean",
347 "System.Decimal", "System.Void",
348 "System.RuntimeFieldHandle",
349 "System.RuntimeArgumentHandle",
350 "System.RuntimeTypeHandle",
352 "System.TypedReference",
356 foreach (string cname in structs_second_stage)
357 BootstrapCorlib_ResolveStruct (root, cname);
360 // These are classes that depends on the core interfaces
362 string [] classes_second_stage = {
363 "System.Reflection.MemberInfo",
369 // These are not really important in the order, but they
370 // are used by the compiler later on (typemanager/CoreLookupType-d)
372 "System.Runtime.CompilerServices.RuntimeHelpers",
373 "System.Reflection.DefaultMemberAttribute",
374 "System.Threading.Monitor",
376 "System.AttributeUsageAttribute",
377 "System.Runtime.InteropServices.DllImportAttribute",
378 "System.Runtime.CompilerServices.MethodImplAttribute",
379 "System.Runtime.InteropServices.MarshalAsAttribute",
380 "System.Runtime.CompilerServices.NewConstraintAttribute",
381 "System.Diagnostics.ConditionalAttribute",
382 "System.ObsoleteAttribute",
383 "System.ParamArrayAttribute",
384 "System.CLSCompliantAttribute",
385 "System.Security.UnverifiableCodeAttribute",
386 "System.Runtime.CompilerServices.IndexerNameAttribute",
387 "System.Runtime.InteropServices.InAttribute",
388 "System.Runtime.InteropServices.StructLayoutAttribute",
389 "System.Runtime.InteropServices.FieldOffsetAttribute",
390 "System.InvalidOperationException",
391 "System.NotSupportedException",
392 "System.MarshalByRefObject"
395 // We must store them here before calling BootstrapCorlib_ResolveDelegate.
396 TypeManager.string_type = BootstrapCorlib_ResolveClass (root, "System.String");
397 TypeManager.enum_type = BootstrapCorlib_ResolveClass (root, "System.Enum");
398 TypeManager.array_type = BootstrapCorlib_ResolveClass (root, "System.Array");
399 TypeManager.multicast_delegate_type = BootstrapCorlib_ResolveClass (root, "System.MulticastDelegate");
400 TypeManager.delegate_type = BootstrapCorlib_ResolveClass (root, "System.Delegate");
402 foreach (string cname in classes_second_stage)
403 BootstrapCorlib_ResolveClass (root, cname);
405 BootstrapCorlib_ResolveDelegate (root, "System.AsyncCallback");
409 // Closes all open types
413 // We usually use TypeBuilder types. When we are done
414 // creating the type (which will happen after we have added
415 // methods, fields, etc) we need to "Define" them before we
416 // can save the Assembly
418 static public void CloseTypes ()
420 TypeContainer root = Tree.Types;
422 if (root.Enums != null)
423 foreach (Enum en in root.Enums)
426 if (attribute_types != null)
427 foreach (TypeContainer tc in attribute_types)
430 foreach (Interface iface in interface_resolve_order)
434 // We do this in two passes, first we close the structs,
435 // then the classes, because it seems the code needs it this
436 // way. If this is really what is going on, we should probably
437 // make sure that we define the structs in order as well.
439 foreach (TypeContainer tc in type_container_resolve_order){
440 if (tc is Struct && tc.Parent == tree.Types){
445 foreach (TypeContainer tc in type_container_resolve_order){
446 if (!(tc is Struct && tc.Parent == tree.Types))
450 if (root.Delegates != null)
451 foreach (Delegate d in root.Delegates)
456 // If we have a <PrivateImplementationDetails> class, close it
458 if (helper_classes != null){
459 foreach (TypeBuilder type_builder in helper_classes)
460 type_builder.CreateType ();
463 attribute_types = null;
464 interface_resolve_order = null;
465 type_container_resolve_order = null;
466 helper_classes = null;
468 TypeManager.CleanUp ();
472 /// Used to register classes that need to be closed after all the
473 /// user defined classes
475 public static void RegisterHelperClass (TypeBuilder helper_class)
477 if (helper_classes == null)
478 helper_classes = new ArrayList ();
479 helper_classes.Add (helper_class);
483 // This idea is from Felix Arrese-Igor
485 // Returns : the implicit parent of a composite namespace string
486 // eg. Implicit parent of A.B is A
488 static public string ImplicitParent (string ns)
490 int i = ns.LastIndexOf ('.');
494 return ns.Substring (0, i);
497 static TypeExpr NamespaceLookup (DeclSpace ds, string name,
498 int num_type_args, bool silent, Location loc)
501 // Try in the current namespace and all its implicit parents
503 for (NamespaceEntry ns = ds.NamespaceEntry; ns != null; ns = ns.ImplicitParent) {
504 IAlias result = ns.Lookup (ds, name, num_type_args, silent, loc);
518 static public TypeExpr LookupType (DeclSpace ds, string name, bool silent,
521 return LookupType (ds, name, silent, 0, loc);
525 // Public function used to locate types, this can only
526 // be used after the ResolveTree function has been invoked.
528 // Returns: Type or null if they type can not be found.
530 // Come to think of it, this should be a DeclSpace
532 static public TypeExpr LookupType (DeclSpace ds, string name, bool silent,
533 int num_type_params, Location loc)
537 if (ds.Cache.Contains (name)){
538 t = (TypeExpr) ds.Cache [name];
543 // For the case the type we are looking for is nested within this one
544 // or is in any base class
546 DeclSpace containing_ds = ds;
547 while (containing_ds != null){
548 Type current_type = containing_ds.TypeBuilder;
550 while (current_type != null) {
554 Type type = TypeManager.LookupType (current_type.FullName + "." + name);
556 t = new TypeExpression (type, loc);
561 current_type = current_type.BaseType;
564 containing_ds = containing_ds.Parent;
567 t = NamespaceLookup (ds, name, num_type_params, silent, loc);
575 Report.Error (246, loc, "Cannot find type `"+name+"'");
581 // This is the silent version of LookupType, you can use this
582 // to `probe' for a type
584 static public TypeExpr LookupType (TypeContainer tc, string name, Location loc)
586 return LookupType (tc, name, true, loc);
589 static public bool IsNamespace (string name)
593 if (tree.Namespaces != null){
594 ns = (Namespace) tree.Namespaces [name];
603 static void Report1530 (Location loc)
605 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
608 static public void PopulateCoreType (TypeContainer root, string name)
610 DeclSpace ds = (DeclSpace) root.GetDefinition (name);
612 ds.DefineMembers (root);
616 static public void BootCorlib_PopulateCoreTypes ()
618 TypeContainer root = tree.Types;
620 PopulateCoreType (root, "System.Object");
621 PopulateCoreType (root, "System.ValueType");
622 PopulateCoreType (root, "System.Attribute");
626 // Populates the structs and classes with fields and methods
629 // This is invoked after all interfaces, structs and classes
630 // have been defined through `ResolveTree'
631 static public void PopulateTypes ()
633 TypeContainer root = Tree.Types;
635 if (attribute_types != null)
636 foreach (TypeContainer tc in attribute_types)
637 tc.DefineMembers (root);
639 if (interface_resolve_order != null){
640 foreach (Interface iface in interface_resolve_order)
641 if ((iface.ModFlags & Modifiers.NEW) == 0)
642 iface.DefineMembers (root);
644 Report1530 (iface.Location);
648 if (type_container_resolve_order != null){
649 if (RootContext.StdLib){
650 foreach (TypeContainer tc in type_container_resolve_order)
651 tc.DefineMembers (root);
653 foreach (TypeContainer tc in type_container_resolve_order) {
654 // When compiling corlib, these types have already been
655 // populated from BootCorlib_PopulateCoreTypes ().
656 if (((tc.Name == "System.Object") ||
657 (tc.Name == "System.Attribute") ||
658 (tc.Name == "System.ValueType")))
661 tc.DefineMembers (root);
666 ArrayList delegates = root.Delegates;
667 if (delegates != null){
668 foreach (Delegate d in delegates)
669 if ((d.ModFlags & Modifiers.NEW) == 0)
670 d.DefineMembers (root);
672 Report1530 (d.Location);
675 ArrayList enums = root.Enums;
677 foreach (Enum en in enums)
678 if ((en.ModFlags & Modifiers.NEW) == 0)
679 en.DefineMembers (root);
681 Report1530 (en.Location);
685 // Check for cycles in the struct layout
687 if (type_container_resolve_order != null){
688 Hashtable seen = new Hashtable ();
689 foreach (TypeContainer tc in type_container_resolve_order)
690 TypeManager.CheckStructCycles (tc, seen);
695 // A generic hook delegate
697 public delegate void Hook ();
700 // A hook invoked when the code has been generated.
702 public static event Hook EmitCodeHook;
705 // DefineTypes is used to fill in the members of each type.
707 static public void DefineTypes ()
709 TypeContainer root = Tree.Types;
711 if (attribute_types != null)
712 foreach (TypeContainer tc in attribute_types)
715 if (interface_resolve_order != null){
716 foreach (Interface iface in interface_resolve_order)
717 if ((iface.ModFlags & Modifiers.NEW) == 0)
722 if (type_container_resolve_order != null){
723 foreach (TypeContainer tc in type_container_resolve_order) {
724 // When compiling corlib, these types have already been
725 // populated from BootCorlib_PopulateCoreTypes ().
726 if (!RootContext.StdLib &&
727 ((tc.Name == "System.Object") ||
728 (tc.Name == "System.Attribute") ||
729 (tc.Name == "System.ValueType")))
732 if ((tc.ModFlags & Modifiers.NEW) == 0)
737 ArrayList delegates = root.Delegates;
738 if (delegates != null){
739 foreach (Delegate d in delegates)
740 if ((d.ModFlags & Modifiers.NEW) == 0)
744 ArrayList enums = root.Enums;
746 foreach (Enum en in enums)
747 if ((en.ModFlags & Modifiers.NEW) == 0)
752 static public void EmitCode ()
754 if (attribute_types != null)
755 foreach (TypeContainer tc in attribute_types)
758 CodeGen.Assembly.Emit (Tree.Types);
759 CodeGen.Module.Emit (Tree.Types);
761 if (Tree.Types.Enums != null) {
762 foreach (Enum e in Tree.Types.Enums)
766 if (interface_resolve_order != null){
767 foreach (Interface iface in interface_resolve_order)
768 iface.Emit (Tree.Types);
771 if (type_container_resolve_order != null) {
772 foreach (TypeContainer tc in type_container_resolve_order)
775 foreach (TypeContainer tc in type_container_resolve_order)
779 if (Tree.Types.Delegates != null) {
780 foreach (Delegate d in Tree.Types.Delegates)
784 // Run any hooks after all the types have been defined.
785 // This is used to create nested auxiliary classes for example
788 if (EmitCodeHook != null)
793 // Public Field, used to track which method is the public entry
796 static public MethodInfo EntryPoint;
799 // Track the location of the entry point.
801 static public Location EntryPointLocation;
804 // These are used to generate unique names on the structs and fields.
806 static int field_count;
809 // Makes an initialized struct, returns the field builder that
810 // references the data. Thanks go to Sergey Chaban for researching
811 // how to do this. And coming up with a shorter mechanism than I
812 // was able to figure out.
814 // This works but makes an implicit public struct $ArrayType$SIZE and
815 // makes the fields point to it. We could get more control if we did
818 // 1. DefineNestedType on the impl_details_class with our struct.
820 // 2. Define the field on the impl_details_class
822 static public FieldBuilder MakeStaticData (byte [] data)
826 if (impl_details_class == null){
827 impl_details_class = CodeGen.Module.Builder.DefineType (
828 "<PrivateImplementationDetails>",
829 TypeAttributes.NotPublic,
830 TypeManager.object_type);
832 RegisterHelperClass (impl_details_class);
835 fb = impl_details_class.DefineInitializedData (
836 "$$field-" + (field_count++), data,
837 FieldAttributes.Static | FieldAttributes.Assembly);