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;
51 public static Platform Platform;
53 public static string TargetExt;
54 public static bool VerifyClsCompliance = true;
55 public static bool Optimize = true;
56 public static LanguageVersion Version;
58 public static MetadataVersion MetadataCompatibilityVersion;
61 // We keep strongname related info here because
62 // it's also used as complier options from CSC 8.x
64 public static string StrongNameKeyFile;
65 public static string StrongNameKeyContainer;
66 public static bool StrongNameDelaySign;
69 // If set, enable XML documentation generation
71 public static Documentation Documentation;
73 static public string MainClass;
76 // The default compiler checked state
78 static public bool Checked;
81 // If true, it means that the compiler is executing as
82 // in eval mode so unresolved variables are resolved in
83 // static classes maintained by the eval engine.
85 static public bool EvalMode;
88 // If true, the compiler is operating in statement mode,
89 // this currently turns local variable declaration into
90 // static variables of a class
92 static public bool StatementMode;
95 // Whether to allow Unsafe code
97 static public bool Unsafe;
100 // Whether we are being linked against the standard libraries.
101 // This is only used to tell whether `System.Object' should
102 // have a base class or not.
104 public static bool StdLib;
106 public static bool NeedsEntryPoint {
107 get { return Target == Target.Exe || Target == Target.WinExe; }
111 // COMPILER OPTIONS CLASS END
115 // Contains the parsed tree
117 static ModuleContainer root;
120 // This hashtable contains all of the #definitions across the source code
121 // it is used by the ConditionalAttribute handler.
123 static ArrayList AllDefines;
126 // This keeps track of the order in which classes were defined
127 // so that we can poulate them in that order.
129 // Order is important, because we need to be able to tell, by
130 // examining the list of methods of the base class, which ones are virtual
131 // or abstract as well as the parent names (to implement new,
134 static ArrayList type_container_resolve_order;
137 // Holds a reference to the Private Implementation Details
140 static ArrayList helper_classes;
142 static TypeBuilder impl_details_class;
147 static RootContext ()
152 public static void PartialReset ()
157 public static void Reset (bool full)
162 type_container_resolve_order = new ArrayList ();
164 Report.WarningLevel = 4;
168 StrongNameKeyFile = null;
169 StrongNameKeyContainer = null;
170 StrongNameDelaySign = false;
175 Platform = Platform.AnyCPU;
177 Version = LanguageVersion.Default;
178 Documentation = null;
179 impl_details_class = null;
180 helper_classes = null;
183 MetadataCompatibilityVersion = MetadataVersion.v2;
185 MetadataCompatibilityVersion = MetadataVersion.v1;
189 // Setup default defines
191 AllDefines = new ArrayList ();
192 AddConditional ("__MonoCS__");
195 public static void AddConditional (string p)
197 if (AllDefines.Contains (p))
202 public static bool IsConditionalDefined (string value)
204 return AllDefines.Contains (value);
207 static public ModuleContainer ToplevelTypes {
209 set { root = value; }
212 public static void RegisterOrder (TypeContainer tc)
214 type_container_resolve_order.Add (tc);
218 // This function is used to resolve the hierarchy tree.
219 // It processes interfaces, structs and classes in that order.
221 // It creates the TypeBuilder's as it processes the user defined
224 static public void ResolveTree ()
229 // Interfaces are processed next, as classes and
230 // structs might inherit from an object or implement
231 // a set of interfaces, we need to be able to tell
232 // them appart by just using the TypeManager.
234 foreach (TypeContainer tc in root.Types)
237 foreach (TypeContainer tc in root.Types)
240 if (root.Delegates != null)
241 foreach (Delegate d in root.Delegates)
246 // Closes all open types
250 // We usually use TypeBuilder types. When we are done
251 // creating the type (which will happen after we have added
252 // methods, fields, etc) we need to "Define" them before we
253 // can save the Assembly
255 static public void CloseTypes ()
258 // We do this in two passes, first we close the structs,
259 // then the classes, because it seems the code needs it this
260 // way. If this is really what is going on, we should probably
261 // make sure that we define the structs in order as well.
263 foreach (TypeContainer tc in type_container_resolve_order){
264 if (tc.Kind == Kind.Struct && tc.Parent == root){
269 foreach (TypeContainer tc in type_container_resolve_order){
270 if (!(tc.Kind == Kind.Struct && tc.Parent == root))
274 if (root.Delegates != null)
275 foreach (Delegate d in root.Delegates)
280 // If we have a <PrivateImplementationDetails> class, close it
282 if (helper_classes != null){
283 foreach (TypeBuilder type_builder in helper_classes) {
284 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (type_builder);
285 type_builder.CreateType ();
289 type_container_resolve_order = null;
290 helper_classes = null;
292 TypeManager.CleanUp ();
296 /// Used to register classes that need to be closed after all the
297 /// user defined classes
299 public static void RegisterCompilerGeneratedType (TypeBuilder helper_class)
301 if (helper_classes == null)
302 helper_classes = new ArrayList ();
304 helper_classes.Add (helper_class);
307 static public void PopulateCoreType (TypeContainer root, string name)
309 DeclSpace ds = (DeclSpace) root.GetDefinition (name);
310 // Core type was imported
317 static public void BootCorlib_PopulateCoreTypes ()
319 PopulateCoreType (root, "System.Object");
320 PopulateCoreType (root, "System.ValueType");
321 PopulateCoreType (root, "System.Attribute");
322 PopulateCoreType (root, "System.Runtime.CompilerServices.IndexerNameAttribute");
326 // Populates the structs and classes with fields and methods
329 // This is invoked after all interfaces, structs and classes
330 // have been defined through `ResolveTree'
331 static public void PopulateTypes ()
334 if (type_container_resolve_order != null){
335 foreach (TypeContainer tc in type_container_resolve_order)
337 foreach (TypeContainer tc in type_container_resolve_order) {
340 } catch (Exception e) {
341 throw new InternalErrorException (tc, e);
346 ArrayList delegates = root.Delegates;
347 if (delegates != null){
348 foreach (Delegate d in delegates)
353 // Check for cycles in the struct layout
355 if (type_container_resolve_order != null){
356 Hashtable seen = new Hashtable ();
357 foreach (TypeContainer tc in type_container_resolve_order)
358 TypeManager.CheckStructCycles (tc, seen);
362 static public void EmitCode ()
364 if (type_container_resolve_order != null) {
365 foreach (TypeContainer tc in type_container_resolve_order)
368 if (Report.Errors > 0)
371 foreach (TypeContainer tc in type_container_resolve_order)
375 if (root.Delegates != null) {
376 foreach (Delegate d in root.Delegates)
380 CodeGen.Assembly.Emit (root);
385 // Public Field, used to track which method is the public entry
388 static public Method EntryPoint;
391 // These are used to generate unique names on the structs and fields.
393 static int field_count;
396 // Makes an initialized struct, returns the field builder that
397 // references the data. Thanks go to Sergey Chaban for researching
398 // how to do this. And coming up with a shorter mechanism than I
399 // was able to figure out.
401 // This works but makes an implicit public struct $ArrayType$SIZE and
402 // makes the fields point to it. We could get more control if we did
405 // 1. DefineNestedType on the impl_details_class with our struct.
407 // 2. Define the field on the impl_details_class
409 static public FieldBuilder MakeStaticData (byte [] data)
413 if (impl_details_class == null){
414 impl_details_class = ToplevelTypes.Builder.DefineType (
415 "<PrivateImplementationDetails>",
416 TypeAttributes.NotPublic,
417 TypeManager.object_type);
419 RegisterCompilerGeneratedType (impl_details_class);
422 fb = impl_details_class.DefineInitializedData (
423 "$$field-" + (field_count++), data,
424 FieldAttributes.Static | FieldAttributes.Assembly);
429 public static void CheckUnsafeOption (Location loc)
432 Report.Error (227, loc,
433 "Unsafe code requires the `unsafe' command line option to be specified");