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)
6 // Marek Safar (marek.safar@gmail.com)
9 // Dual licensed under the terms of the MIT X11 or GNU GPL
11 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
12 // Copyright 2004-2008 Novell, Inc
15 using System.Collections;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Diagnostics;
20 namespace Mono.CSharp {
30 #if NET_4_0 || BOOTSTRAP_NET_4_0
31 Default = LanguageVersion.V_4,
33 Default = LanguageVersion.V_3
47 // COMPILER OPTIONS CLASS
49 public static Target Target;
50 public static string TargetExt;
51 public static bool VerifyClsCompliance = true;
52 public static bool Optimize = true;
53 public static LanguageVersion Version;
55 public static MetadataVersion MetadataCompatibilityVersion;
58 // We keep strongname related info here because
59 // it's also used as complier options from CSC 8.x
61 public static string StrongNameKeyFile;
62 public static string StrongNameKeyContainer;
63 public static bool StrongNameDelaySign;
66 // If set, enable XML documentation generation
68 public static Documentation Documentation;
70 static public string MainClass;
73 // The default compiler checked state
75 static public bool Checked;
78 // If true, it means that the compiler is executing as
79 // in eval mode so unresolved variables are resolved in
80 // static classes maintained by the eval engine.
82 static public bool EvalMode;
85 // If true, the compiler is operating in statement mode,
86 // this currently turns local variable declaration into
87 // static variables of a class
89 static public bool StatementMode;
92 // Whether to allow Unsafe code
94 static public bool Unsafe;
97 // Whether we are being linked against the standard libraries.
98 // This is only used to tell whether `System.Object' should
99 // have a base class or not.
101 public static bool StdLib;
103 public static bool NeedsEntryPoint {
104 get { return Target == Target.Exe || Target == Target.WinExe; }
108 // COMPILER OPTIONS CLASS END
112 // Contains the parsed tree
114 static ModuleContainer root;
117 // This hashtable contains all of the #definitions across the source code
118 // it is used by the ConditionalAttribute handler.
120 static ArrayList AllDefines;
123 // This keeps track of the order in which classes were defined
124 // so that we can poulate them in that order.
126 // Order is important, because we need to be able to tell, by
127 // examining the list of methods of the base class, which ones are virtual
128 // or abstract as well as the parent names (to implement new,
131 static ArrayList type_container_resolve_order;
134 // Holds a reference to the Private Implementation Details
137 static ArrayList helper_classes;
139 static TypeBuilder impl_details_class;
144 static RootContext ()
149 public static void PartialReset ()
154 public static void Reset (bool full)
159 type_container_resolve_order = new ArrayList ();
161 Report.WarningLevel = 4;
165 StrongNameKeyFile = null;
166 StrongNameKeyContainer = null;
167 StrongNameDelaySign = false;
171 Version = LanguageVersion.Default;
172 Documentation = null;
173 impl_details_class = null;
174 helper_classes = null;
177 MetadataCompatibilityVersion = MetadataVersion.v2;
179 MetadataCompatibilityVersion = MetadataVersion.v1;
183 // Setup default defines
185 AllDefines = new ArrayList ();
186 AddConditional ("__MonoCS__");
189 public static void AddConditional (string p)
191 if (AllDefines.Contains (p))
196 public static bool IsConditionalDefined (string value)
198 return AllDefines.Contains (value);
201 static public ModuleContainer ToplevelTypes {
203 set { root = value; }
206 public static void RegisterOrder (TypeContainer tc)
208 type_container_resolve_order.Add (tc);
212 // This function is used to resolve the hierarchy tree.
213 // It processes interfaces, structs and classes in that order.
215 // It creates the TypeBuilder's as it processes the user defined
218 static public void ResolveTree ()
223 // Interfaces are processed next, as classes and
224 // structs might inherit from an object or implement
225 // a set of interfaces, we need to be able to tell
226 // them appart by just using the TypeManager.
228 foreach (TypeContainer tc in root.Types)
231 foreach (TypeContainer tc in root.Types)
234 if (root.Delegates != null)
235 foreach (Delegate d in root.Delegates)
240 // Closes all open types
244 // We usually use TypeBuilder types. When we are done
245 // creating the type (which will happen after we have added
246 // methods, fields, etc) we need to "Define" them before we
247 // can save the Assembly
249 static public void CloseTypes ()
252 // We do this in two passes, first we close the structs,
253 // then the classes, because it seems the code needs it this
254 // way. If this is really what is going on, we should probably
255 // make sure that we define the structs in order as well.
257 foreach (TypeContainer tc in type_container_resolve_order){
258 if (tc.Kind == Kind.Struct && tc.Parent == root){
263 foreach (TypeContainer tc in type_container_resolve_order){
264 if (!(tc.Kind == Kind.Struct && tc.Parent == root))
268 if (root.Delegates != null)
269 foreach (Delegate d in root.Delegates)
274 // If we have a <PrivateImplementationDetails> class, close it
276 if (helper_classes != null){
277 foreach (TypeBuilder type_builder in helper_classes) {
278 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (type_builder);
279 type_builder.CreateType ();
283 type_container_resolve_order = null;
284 helper_classes = null;
286 TypeManager.CleanUp ();
290 /// Used to register classes that need to be closed after all the
291 /// user defined classes
293 public static void RegisterCompilerGeneratedType (TypeBuilder helper_class)
295 if (helper_classes == null)
296 helper_classes = new ArrayList ();
298 helper_classes.Add (helper_class);
301 static public void PopulateCoreType (TypeContainer root, string name)
303 DeclSpace ds = (DeclSpace) root.GetDefinition (name);
304 // Core type was imported
311 static public void BootCorlib_PopulateCoreTypes ()
313 PopulateCoreType (root, "System.Object");
314 PopulateCoreType (root, "System.ValueType");
315 PopulateCoreType (root, "System.Attribute");
316 PopulateCoreType (root, "System.Runtime.CompilerServices.IndexerNameAttribute");
320 // Populates the structs and classes with fields and methods
323 // This is invoked after all interfaces, structs and classes
324 // have been defined through `ResolveTree'
325 static public void PopulateTypes ()
328 if (type_container_resolve_order != null){
329 foreach (TypeContainer tc in type_container_resolve_order)
331 foreach (TypeContainer tc in type_container_resolve_order) {
334 } catch (Exception e) {
335 throw new InternalErrorException (tc, e);
340 ArrayList delegates = root.Delegates;
341 if (delegates != null){
342 foreach (Delegate d in delegates)
347 // Check for cycles in the struct layout
349 if (type_container_resolve_order != null){
350 Hashtable seen = new Hashtable ();
351 foreach (TypeContainer tc in type_container_resolve_order)
352 TypeManager.CheckStructCycles (tc, seen);
356 static public void EmitCode ()
358 if (type_container_resolve_order != null) {
359 foreach (TypeContainer tc in type_container_resolve_order)
362 if (Report.Errors > 0)
365 foreach (TypeContainer tc in type_container_resolve_order)
369 if (root.Delegates != null) {
370 foreach (Delegate d in root.Delegates)
374 CodeGen.Assembly.Emit (root);
379 // Public Field, used to track which method is the public entry
382 static public Method EntryPoint;
385 // These are used to generate unique names on the structs and fields.
387 static int field_count;
390 // Makes an initialized struct, returns the field builder that
391 // references the data. Thanks go to Sergey Chaban for researching
392 // how to do this. And coming up with a shorter mechanism than I
393 // was able to figure out.
395 // This works but makes an implicit public struct $ArrayType$SIZE and
396 // makes the fields point to it. We could get more control if we did
399 // 1. DefineNestedType on the impl_details_class with our struct.
401 // 2. Define the field on the impl_details_class
403 static public FieldBuilder MakeStaticData (byte [] data)
407 if (impl_details_class == null){
408 impl_details_class = ToplevelTypes.Builder.DefineType (
409 "<PrivateImplementationDetails>",
410 TypeAttributes.NotPublic,
411 TypeManager.object_type);
413 RegisterCompilerGeneratedType (impl_details_class);
416 fb = impl_details_class.DefineInitializedData (
417 "$$field-" + (field_count++), data,
418 FieldAttributes.Static | FieldAttributes.Assembly);
423 public static void CheckUnsafeOption (Location loc)
426 Report.Error (227, loc,
427 "Unsafe code requires the `unsafe' command line option to be specified");