// rootcontext.cs: keeps track of our tree representation, and assemblies loaded.
//
// Author: Miguel de Icaza (miguel@ximian.com)
-// Ravi Pratap (ravi@ximian.com)
+// Ravi Pratap (ravi@ximian.com)
+// Marek Safar (marek.safar@gmail.com)
//
-// Licensed under the terms of the GNU GPL
//
-// (C) 2001 Ximian, Inc (http://www.ximian.com)
-// (C) 2004 Novell, Inc
+// Dual licensed under the terms of the MIT X11 or GNU GPL
+//
+// Copyright 2001 Ximian, Inc (http://www.ximian.com)
+// Copyright 2004-2008 Novell, Inc
using System;
-using System.Collections;
+using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Diagnostics;
public enum LanguageVersion
{
- Default = 0,
- ISO_1 = 1
+ ISO_1 = 1,
+ ISO_2 = 2,
+ V_3 = 3,
+ V_4 = 4,
+ Future = 100,
+
+ Default = LanguageVersion.V_4,
+ }
+
+ public enum MetadataVersion
+ {
+ v1,
+ v2,
+ v4
}
public class RootContext {
//
- // Contains the parsed tree
+ // COMPILER OPTIONS CLASS
//
- static Tree tree;
+ public static Target Target;
+ public static Platform Platform;
+ public static string TargetExt;
+ public static bool VerifyClsCompliance = true;
+ public static bool Optimize = true;
+ public static LanguageVersion Version;
+ public static bool EnhancedWarnings;
+
+ public static MetadataVersion MetadataCompatibilityVersion;
//
- // This hashtable contains all of the #definitions across the source code
- // it is used by the ConditionalAttribute handler.
+ // We keep strongname related info here because
+ // it's also used as complier options from CSC 8.x
//
- public static Hashtable AllDefines = new Hashtable ();
-
+ public static string StrongNameKeyFile;
+ public static string StrongNameKeyContainer;
+ public static bool StrongNameDelaySign;
+
//
- // Whether we are being linked against the standard libraries.
- // This is only used to tell whether `System.Object' should
- // have a base class or not.
+ // If set, enable XML documentation generation
//
- public static bool StdLib;
+ public static Documentation Documentation;
+
+ static public string MainClass;
+ //
+ // The default compiler checked state
//
- // This keeps track of the order in which classes were defined
- // so that we can poulate them in that order.
+ static public bool Checked;
+
//
- // Order is important, because we need to be able to tell, by
- // examining the list of methods of the base class, which ones are virtual
- // or abstract as well as the parent names (to implement new,
- // override).
+ // If true, it means that the compiler is executing as
+ // in eval mode so unresolved variables are resolved in
+ // static classes maintained by the eval engine.
//
- static ArrayList type_container_resolve_order;
+ static public bool EvalMode;
//
- // Holds a reference to the Private Implementation Details
- // class.
+ // If true, the compiler is operating in statement mode,
+ // this currently turns local variable declaration into
+ // static variables of a class
//
- static ArrayList helper_classes;
+ static public bool StatementMode;
- static TypeBuilder impl_details_class;
-
- public static int WarningLevel;
-
- public static Target Target;
- public static string TargetExt;
+ //
+ // Whether to allow Unsafe code
+ //
+ static public bool Unsafe;
- public static bool VerifyClsCompliance = true;
+ //
+ // Whether we are being linked against the standard libraries.
+ // This is only used to tell whether `System.Object' should
+ // have a base class or not.
+ //
+ public static bool StdLib;
- /// <summary>
- /// Holds /optimize option
- /// </summary>
- public static bool Optimize = true;
+ public static bool NeedsEntryPoint {
+ get { return Target == Target.Exe || Target == Target.WinExe; }
+ }
- public static LanguageVersion Version;
+ //
+ // COMPILER OPTIONS CLASS END
+ //
//
- // We keep strongname related info here because
- // it's also used as complier options from CSC 8.x
+ // Contains the parsed tree
//
- public static string StrongNameKeyFile;
- public static string StrongNameKeyContainer;
- public static bool StrongNameDelaySign;
+ static ModuleCompiled root;
//
- // If set, enable XML documentation generation
+ // This hashtable contains all of the #definitions across the source code
+ // it is used by the ConditionalAttribute handler.
//
- public static Documentation Documentation;
+ static List<string> AllDefines;
+
+ //
+ // Holds a reference to the Private Implementation Details
+ // class.
+ //
+ static List<TypeBuilder> helper_classes;
+
+ static TypeBuilder impl_details_class;
- static public string MainClass;
+ public static List<Enum> hack_corlib_enums = new List<Enum> ();
//
// Constructor
//
static RootContext ()
{
- Reset ();
+ Reset (true);
}
- public static void Reset ()
+ public static void PartialReset ()
+ {
+ Reset (false);
+ }
+
+ public static void Reset (bool full)
{
- tree = new Tree ();
- type_container_resolve_order = new ArrayList ();
+ impl_details_class = null;
+ helper_classes = null;
+
+ if (!full)
+ return;
+
EntryPoint = null;
- WarningLevel = 3;
Checked = false;
Unsafe = false;
StdLib = true;
StrongNameDelaySign = false;
MainClass = null;
Target = Target.Exe;
- TargetExt = ".exe";
+ TargetExt = ".exe";
+ Platform = Platform.AnyCPU;
Version = LanguageVersion.Default;
Documentation = null;
impl_details_class = null;
- }
-
- public static bool NeedsEntryPoint {
- get {
- return RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe;
- }
+ helper_classes = null;
+
+#if NET_4_0
+ MetadataCompatibilityVersion = MetadataVersion.v4;
+#else
+ MetadataCompatibilityVersion = MetadataVersion.v2;
+#endif
+
+ //
+ // Setup default defines
+ //
+ AllDefines = new List<string> ();
+ AddConditional ("__MonoCS__");
}
- static public Tree Tree {
- get {
- return tree;
- }
+ public static void AddConditional (string p)
+ {
+ if (AllDefines.Contains (p))
+ return;
+ AllDefines.Add (p);
}
- public static void RegisterOrder (TypeContainer tc)
+ public static bool IsConditionalDefined (string value)
{
- type_container_resolve_order.Add (tc);
+ return AllDefines.Contains (value);
+ }
+
+ static public ModuleCompiled ToplevelTypes {
+ get { return root; }
+ set { root = value; }
}
-
- //
- // The default compiler checked state
- //
- static public bool Checked;
- //
- // Whether to allow Unsafe code
- //
- static public bool Unsafe;
-
// <remarks>
// This function is used to resolve the hierarchy tree.
// It processes interfaces, structs and classes in that order.
// </remarks>
static public void ResolveTree ()
{
+ root.Resolve ();
+
//
// 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){
- foreach (TypeContainer i in ifaces)
- i.DefineType ();
- }
+ foreach (TypeContainer tc in root.Types)
+ tc.CreateType ();
foreach (TypeContainer tc in root.Types)
tc.DefineType ();
-
- if (root.Delegates != null)
- foreach (Delegate d in root.Delegates)
- d.DefineType ();
-
- if (root.Enums != null)
- foreach (Enum e in root.Enums)
- 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 or imported");
- 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 or imported");
- 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)
+ static void HackCorlib ()
{
- object o = root.GetDefinition (name);
- if (o == null){
- Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
+ if (StdLib)
return;
- }
- if (!(o is Interface)){
- if (o is DeclSpace){
- DeclSpace d = (DeclSpace) o;
+ //
+ // HACK: When building corlib mcs uses loaded mscorlib which
+ // has different predefined types and this method sets mscorlib types
+ // to be same to avoid type check errors in CreateType.
+ //
+ var type = typeof (Type);
+ var system_4_type_arg = new[] { type, type, type, type };
- Error_TypeConflict (name, d.Location);
- } else
- Error_TypeConflict (name);
+ MethodInfo set_corlib_type_builders =
+ typeof (System.Reflection.Emit.AssemblyBuilder).GetMethod (
+ "SetCorlibTypeBuilders", BindingFlags.NonPublic | BindingFlags.Instance, null,
+ system_4_type_arg, null);
+ if (set_corlib_type_builders == null) {
+ root.Compiler.Report.Warning (-26, 3, "The compilation may fail due to missing `{0}.SetCorlibTypeBuilders(...)' method",
+ typeof (System.Reflection.Emit.AssemblyBuilder).FullName);
return;
}
- ((DeclSpace) o).DefineType ();
+ object[] args = new object[4];
+ args[0] = TypeManager.object_type.GetMetaInfo ();
+ args[1] = TypeManager.value_type.GetMetaInfo ();
+ args[2] = TypeManager.enum_type.GetMetaInfo ();
+ args[3] = TypeManager.void_type.GetMetaInfo ();
+ set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
+
+ // Another Mono corlib HACK
+ // mono_class_layout_fields requires to have enums created
+ // before creating a class which used the enum for any of its fields
+ foreach (var e in hack_corlib_enums)
+ e.CloseType ();
}
- //
- // 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 or imported");
- return;
- }
-
- if (!(o is Delegate)){
- Error_TypeConflict (name);
- return;
- }
-
- ((DeclSpace) o).DefineType ();
- }
-
-
- /// <summary>
- /// Resolves the core types in the compiler when compiling with --nostdlib
- /// </summary>
- static public void ResolveCore ()
- {
- TypeContainer root = Tree.Types;
-
- TypeManager.object_type = BootstrapCorlib_ResolveClass (root, "System.Object");
- TypeManager.system_object_expr.Type = TypeManager.object_type;
- TypeManager.value_type = BootstrapCorlib_ResolveClass (root, "System.ValueType");
- TypeManager.system_valuetype_expr.Type = TypeManager.value_type;
- TypeManager.attribute_type = BootstrapCorlib_ResolveClass (root, "System.Attribute");
- TypeManager.indexer_name_type = BootstrapCorlib_ResolveClass (root, "System.Runtime.CompilerServices.IndexerNameAttribute");
-
- 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.RuntimeArgumentHandle",
- "System.RuntimeTypeHandle",
- "System.IntPtr",
- "System.TypedReference",
- "System.ArgIterator"
- };
-
- 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.Enum",
- "System.String",
- "System.Array",
- "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.CLSCompliantAttribute",
- "System.Security.UnverifiableCodeAttribute",
- "System.Security.Permissions.SecurityAttribute",
- "System.Runtime.CompilerServices.DecimalConstantAttribute",
- "System.Runtime.InteropServices.InAttribute",
- "System.Runtime.InteropServices.OutAttribute",
- "System.Runtime.InteropServices.StructLayoutAttribute",
- "System.Runtime.InteropServices.FieldOffsetAttribute",
- "System.InvalidOperationException",
- "System.NotSupportedException",
- "System.MarshalByRefObject",
- "System.Security.CodeAccessPermission",
- "System.Runtime.CompilerServices.RequiredAttributeAttribute",
- "System.Runtime.InteropServices.GuidAttribute",
- "System.Reflection.AssemblyCultureAttribute"
- };
-
- foreach (string cname in classes_second_stage)
- BootstrapCorlib_ResolveClass (root, cname);
-
- BootstrapCorlib_ResolveDelegate (root, "System.AsyncCallback");
-
- // These will be defined indirectly during the previous ResolveDelegate.
- // However make sure the rest of the checks happen.
- string [] delegate_types = { "System.Delegate", "System.MulticastDelegate" };
- foreach (string cname in delegate_types)
- BootstrapCorlib_ResolveClass (root, cname);
- }
-
// <summary>
// Closes all open types
// </summary>
// </remarks>
static public void CloseTypes ()
{
- TypeContainer root = Tree.Types;
-
- if (root.Enums != null)
- foreach (Enum en in root.Enums)
- en.CloseType ();
+ HackCorlib ();
- //
- // 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.Kind == Kind.Struct && tc.Parent == tree.Types){
- tc.CloseType ();
- }
+ foreach (TypeContainer tc in root.Types){
+ tc.CloseType ();
}
- foreach (TypeContainer tc in type_container_resolve_order){
- if (!(tc.Kind == Kind.Struct && tc.Parent == tree.Types))
- tc.CloseType ();
- }
-
- if (root.Delegates != null)
- foreach (Delegate d in root.Delegates)
- d.CloseType ();
-
+ if (root.CompilerGeneratedClasses != null)
+ foreach (CompilerGeneratedClass c in root.CompilerGeneratedClasses)
+ c.CloseType ();
//
// If we have a <PrivateImplementationDetails> class, close it
//
if (helper_classes != null){
foreach (TypeBuilder type_builder in helper_classes) {
-#if NET_2_0
- type_builder.SetCustomAttribute (TypeManager.compiler_generated_attr);
-#endif
+ PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (type_builder);
type_builder.CreateType ();
}
}
- type_container_resolve_order = null;
helper_classes = null;
- //tree = null;
- TypeManager.CleanUp ();
}
/// <summary>
public static void RegisterCompilerGeneratedType (TypeBuilder helper_class)
{
if (helper_classes == null)
- helper_classes = new ArrayList ();
+ helper_classes = new List<TypeBuilder> ();
helper_classes.Add (helper_class);
}
- static public void PopulateCoreType (TypeContainer root, string name)
- {
- DeclSpace ds = (DeclSpace) root.GetDefinition (name);
-
- ds.DefineMembers ();
- ds.Define ();
- }
-
- static public void BootCorlib_PopulateCoreTypes ()
- {
- TypeContainer root = tree.Types;
-
- PopulateCoreType (root, "System.Object");
- PopulateCoreType (root, "System.ValueType");
- PopulateCoreType (root, "System.Attribute");
- PopulateCoreType (root, "System.Runtime.CompilerServices.IndexerNameAttribute");
- }
-
// <summary>
// Populates the structs and classes with fields and methods
// </summary>
// have been defined through `ResolveTree'
static public void PopulateTypes ()
{
- TypeContainer root = Tree.Types;
-
- if (type_container_resolve_order != null){
- foreach (TypeContainer tc in type_container_resolve_order)
- tc.DefineMembers ();
- }
-
- ArrayList delegates = root.Delegates;
- if (delegates != null){
- foreach (Delegate d in delegates)
- d.DefineMembers ();
- }
-
- ArrayList enums = root.Enums;
- if (enums != null){
- foreach (Enum en in enums)
- en.DefineMembers ();
- }
-
- //
- // Check for cycles in the struct layout
- //
- if (type_container_resolve_order != null){
- Hashtable seen = new Hashtable ();
- foreach (TypeContainer tc in type_container_resolve_order)
- TypeManager.CheckStructCycles (tc, seen);
- }
- }
-
- //
- // A generic hook delegate
- //
- public delegate void Hook ();
-
- //
- // A hook invoked when the code has been generated.
- //
- public static event Hook EmitCodeHook;
-
- //
- // DefineTypes is used to fill in the members of each type.
- //
- static public void DefineTypes ()
- {
- TypeContainer root = Tree.Types;
-
- ArrayList delegates = root.Delegates;
- if (delegates != null){
- foreach (Delegate d in delegates)
- d.Define ();
- }
-
- 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") ||
- (tc.Name == "System.Runtime.CompilerServices.IndexerNameAttribute")))
- continue;
+ foreach (TypeContainer tc in ToplevelTypes.Types)
+ tc.ResolveTypeParameters ();
+ foreach (TypeContainer tc in ToplevelTypes.Types) {
+ try {
tc.Define ();
+ } catch (Exception e) {
+ throw new InternalErrorException (tc, e);
}
}
-
- ArrayList enums = root.Enums;
- if (enums != null){
- foreach (Enum en in enums)
- en.Define ();
- }
}
static public void EmitCode ()
{
- if (Tree.Types.Enums != null) {
- foreach (Enum e in Tree.Types.Enums)
- e.Emit ();
- }
+ foreach (var tc in ToplevelTypes.Types)
+ tc.DefineConstants ();
- if (type_container_resolve_order != null) {
- foreach (TypeContainer tc in type_container_resolve_order)
- tc.EmitType ();
+ foreach (TypeContainer tc in ToplevelTypes.Types)
+ tc.EmitType ();
- if (Report.Errors > 0)
- return;
+ if (ToplevelTypes.Compiler.Report.Errors > 0)
+ return;
- foreach (TypeContainer tc in type_container_resolve_order)
- tc.VerifyMembers ();
- }
-
- if (Tree.Types.Delegates != null) {
- foreach (Delegate d in Tree.Types.Delegates)
- d.Emit ();
- }
- //
- // Run any hooks after all the types have been defined.
- // This is used to create nested auxiliary classes for example
- //
+ foreach (TypeContainer tc in ToplevelTypes.Types)
+ tc.VerifyMembers ();
- if (EmitCodeHook != null)
- EmitCodeHook ();
+ if (root.CompilerGeneratedClasses != null)
+ foreach (CompilerGeneratedClass c in root.CompilerGeneratedClasses)
+ c.EmitType ();
- CodeGen.Assembly.Emit (Tree.Types);
- CodeGen.Module.Emit (Tree.Types);
+ CodeGen.Assembly.Emit (root);
+ root.Emit ();
}
//
// Public Field, used to track which method is the public entry
// point.
//
- static public MethodInfo EntryPoint;
-
- //
- // Track the location of the entry point.
- //
- static public Location EntryPointLocation;
+ static public Method EntryPoint;
//
// These are used to generate unique names on the structs and fields.
FieldBuilder fb;
if (impl_details_class == null){
- impl_details_class = CodeGen.Module.Builder.DefineType (
+ impl_details_class = ToplevelTypes.Builder.DefineType (
"<PrivateImplementationDetails>",
TypeAttributes.NotPublic,
- TypeManager.object_type);
+ TypeManager.object_type.GetMetaInfo ());
RegisterCompilerGeneratedType (impl_details_class);
}
return fb;
}
- public static void CheckUnsafeOption (Location loc)
+ public static void CheckUnsafeOption (Location loc, Report Report)
{
if (!Unsafe) {
Report.Error (227, loc,
}
}
}
-
-