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
{
22 public enum LanguageVersion
30 Default
= LanguageVersion
.V_4
,
33 public enum MetadataVersion
40 public class RootContext
{
43 // COMPILER OPTIONS CLASS
45 public static Target Target
;
47 public static Platform Platform
;
49 public static string TargetExt
;
50 public static bool VerifyClsCompliance
= true;
51 public static bool Optimize
= true;
52 public static LanguageVersion Version
;
54 public static MetadataVersion MetadataCompatibilityVersion
;
57 // We keep strongname related info here because
58 // it's also used as complier options from CSC 8.x
60 public static string StrongNameKeyFile
;
61 public static string StrongNameKeyContainer
;
62 public static bool StrongNameDelaySign
;
65 // If set, enable XML documentation generation
67 public static Documentation Documentation
;
69 static public string MainClass
;
72 // The default compiler checked state
74 static public bool Checked
;
77 // If true, it means that the compiler is executing as
78 // in eval mode so unresolved variables are resolved in
79 // static classes maintained by the eval engine.
81 static public bool EvalMode
;
84 // If true, the compiler is operating in statement mode,
85 // this currently turns local variable declaration into
86 // static variables of a class
88 static public bool StatementMode
;
91 // Whether to allow Unsafe code
93 static public bool Unsafe
;
96 // Whether we are being linked against the standard libraries.
97 // This is only used to tell whether `System.Object' should
98 // have a base class or not.
100 public static bool StdLib
;
102 public static bool NeedsEntryPoint
{
103 get { return Target == Target.Exe || Target == Target.WinExe; }
107 // COMPILER OPTIONS CLASS END
111 // Contains the parsed tree
113 static ModuleContainer root
;
116 // This hashtable contains all of the #definitions across the source code
117 // it is used by the ConditionalAttribute handler.
119 static ArrayList AllDefines
;
122 // This keeps track of the order in which classes were defined
123 // so that we can poulate them in that order.
125 // Order is important, because we need to be able to tell, by
126 // examining the list of methods of the base class, which ones are virtual
127 // or abstract as well as the parent names (to implement new,
130 static ArrayList type_container_resolve_order
;
133 // Holds a reference to the Private Implementation Details
136 static ArrayList helper_classes
;
138 static TypeBuilder impl_details_class
;
143 static RootContext ()
148 public static void PartialReset ()
153 public static void Reset (bool full
)
158 type_container_resolve_order
= new ArrayList ();
163 StrongNameKeyFile
= null;
164 StrongNameKeyContainer
= null;
165 StrongNameDelaySign
= false;
170 Platform
= Platform
.AnyCPU
;
172 Version
= LanguageVersion
.Default
;
173 Documentation
= null;
174 impl_details_class
= null;
175 helper_classes
= null;
178 MetadataCompatibilityVersion
= MetadataVersion
.v2
;
180 MetadataCompatibilityVersion
= MetadataVersion
.v1
;
184 // Setup default defines
186 AllDefines
= new ArrayList ();
187 AddConditional ("__MonoCS__");
190 public static void AddConditional (string p
)
192 if (AllDefines
.Contains (p
))
197 public static bool IsConditionalDefined (string value)
199 return AllDefines
.Contains (value);
202 static public ModuleContainer ToplevelTypes
{
204 set { root = value; }
207 public static void RegisterOrder (TypeContainer tc
)
209 type_container_resolve_order
.Add (tc
);
213 // This function is used to resolve the hierarchy tree.
214 // It processes interfaces, structs and classes in that order.
216 // It creates the TypeBuilder's as it processes the user defined
219 static public void ResolveTree ()
224 // Interfaces are processed next, as classes and
225 // structs might inherit from an object or implement
226 // a set of interfaces, we need to be able to tell
227 // them appart by just using the TypeManager.
229 foreach (TypeContainer tc
in root
.Types
)
232 foreach (TypeContainer tc
in root
.Types
)
235 if (root
.Delegates
!= null)
236 foreach (Delegate d
in root
.Delegates
)
241 // Closes all open types
245 // We usually use TypeBuilder types. When we are done
246 // creating the type (which will happen after we have added
247 // methods, fields, etc) we need to "Define" them before we
248 // can save the Assembly
250 static public void CloseTypes ()
253 // We do this in two passes, first we close the structs,
254 // then the classes, because it seems the code needs it this
255 // way. If this is really what is going on, we should probably
256 // make sure that we define the structs in order as well.
258 foreach (TypeContainer tc
in type_container_resolve_order
){
259 if (tc
.Kind
== Kind
.Struct
&& tc
.Parent
== root
){
264 foreach (TypeContainer tc
in type_container_resolve_order
){
265 if (!(tc
.Kind
== Kind
.Struct
&& tc
.Parent
== root
))
269 if (root
.Delegates
!= null)
270 foreach (Delegate d
in root
.Delegates
)
275 // If we have a <PrivateImplementationDetails> class, close it
277 if (helper_classes
!= null){
278 foreach (TypeBuilder type_builder
in helper_classes
) {
279 PredefinedAttributes
.Get
.CompilerGenerated
.EmitAttribute (type_builder
);
280 type_builder
.CreateType ();
284 type_container_resolve_order
= null;
285 helper_classes
= null;
287 TypeManager
.CleanUp ();
291 /// Used to register classes that need to be closed after all the
292 /// user defined classes
294 public static void RegisterCompilerGeneratedType (TypeBuilder helper_class
)
296 if (helper_classes
== null)
297 helper_classes
= new ArrayList ();
299 helper_classes
.Add (helper_class
);
302 static public void PopulateCoreType (TypeContainer root
, string name
)
304 DeclSpace ds
= (DeclSpace
) root
.GetDefinition (name
);
305 // Core type was imported
312 static public void BootCorlib_PopulateCoreTypes ()
314 PopulateCoreType (root
, "System.Object");
315 PopulateCoreType (root
, "System.ValueType");
316 PopulateCoreType (root
, "System.Attribute");
317 PopulateCoreType (root
, "System.Runtime.CompilerServices.IndexerNameAttribute");
321 // Populates the structs and classes with fields and methods
324 // This is invoked after all interfaces, structs and classes
325 // have been defined through `ResolveTree'
326 static public void PopulateTypes ()
329 if (type_container_resolve_order
!= null){
330 foreach (TypeContainer tc
in type_container_resolve_order
)
332 foreach (TypeContainer tc
in type_container_resolve_order
) {
335 } catch (Exception e
) {
336 throw new InternalErrorException (tc
, e
);
341 ArrayList delegates
= root
.Delegates
;
342 if (delegates
!= null){
343 foreach (Delegate d
in delegates
)
348 // Check for cycles in the struct layout
350 if (type_container_resolve_order
!= null){
351 Hashtable seen
= new Hashtable ();
352 foreach (TypeContainer tc
in type_container_resolve_order
)
353 TypeManager
.CheckStructCycles (tc
, seen
);
357 static public void EmitCode ()
359 if (type_container_resolve_order
!= null) {
360 foreach (TypeContainer tc
in type_container_resolve_order
)
363 if (RootContext
.ToplevelTypes
.Compiler
.Report
.Errors
> 0)
366 foreach (TypeContainer tc
in type_container_resolve_order
)
370 if (root
.Delegates
!= null) {
371 foreach (Delegate d
in root
.Delegates
)
375 CodeGen
.Assembly
.Emit (root
);
380 // Public Field, used to track which method is the public entry
383 static public Method EntryPoint
;
386 // These are used to generate unique names on the structs and fields.
388 static int field_count
;
391 // Makes an initialized struct, returns the field builder that
392 // references the data. Thanks go to Sergey Chaban for researching
393 // how to do this. And coming up with a shorter mechanism than I
394 // was able to figure out.
396 // This works but makes an implicit public struct $ArrayType$SIZE and
397 // makes the fields point to it. We could get more control if we did
400 // 1. DefineNestedType on the impl_details_class with our struct.
402 // 2. Define the field on the impl_details_class
404 static public FieldBuilder
MakeStaticData (byte [] data
)
408 if (impl_details_class
== null){
409 impl_details_class
= ToplevelTypes
.Builder
.DefineType (
410 "<PrivateImplementationDetails>",
411 TypeAttributes
.NotPublic
,
412 TypeManager
.object_type
);
414 RegisterCompilerGeneratedType (impl_details_class
);
417 fb
= impl_details_class
.DefineInitializedData (
418 "$$field-" + (field_count
++), data
,
419 FieldAttributes
.Static
| FieldAttributes
.Assembly
);
424 public static void CheckUnsafeOption (Location loc
, Report Report
)
427 Report
.Error (227, loc
,
428 "Unsafe code requires the `unsafe' command line option to be specified");