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
36 public class RootContext
{
39 // COMPILER OPTIONS CLASS
41 public static Target Target
;
42 public static string TargetExt
;
43 public static bool VerifyClsCompliance
= true;
44 public static bool Optimize
= true;
45 public static LanguageVersion Version
;
48 // We keep strongname related info here because
49 // it's also used as complier options from CSC 8.x
51 public static string StrongNameKeyFile
;
52 public static string StrongNameKeyContainer
;
53 public static bool StrongNameDelaySign
;
56 // If set, enable XML documentation generation
58 public static Documentation Documentation
;
60 static public string MainClass
;
63 // The default compiler checked state
65 static public bool Checked
;
68 // If true, it means that the compiler is executing as
69 // in eval mode so unresolved variables are resolved in
70 // static classes maintained by the eval engine.
72 static public bool EvalMode
;
75 // If true, the compiler is operating in statement mode,
76 // this currently turns local variable declaration into
77 // static variables of a class
79 static public bool StatementMode
;
82 // Whether to allow Unsafe code
84 static public bool Unsafe
;
87 // Whether we are being linked against the standard libraries.
88 // This is only used to tell whether `System.Object' should
89 // have a base class or not.
91 public static bool StdLib
;
93 public static bool NeedsEntryPoint
{
94 get { return Target == Target.Exe || Target == Target.WinExe; }
98 // COMPILER OPTIONS CLASS END
102 // Contains the parsed tree
104 static RootTypes root
;
107 // This hashtable contains all of the #definitions across the source code
108 // it is used by the ConditionalAttribute handler.
110 static ArrayList AllDefines
= new ArrayList ();
113 // This keeps track of the order in which classes were defined
114 // so that we can poulate them in that order.
116 // Order is important, because we need to be able to tell, by
117 // examining the list of methods of the base class, which ones are virtual
118 // or abstract as well as the parent names (to implement new,
121 static ArrayList type_container_resolve_order
;
124 // Holds a reference to the Private Implementation Details
127 static ArrayList helper_classes
;
129 static TypeBuilder impl_details_class
;
134 static RootContext ()
139 public static void PartialReset ()
144 public static void Reset (bool full
)
147 root
= new RootTypes ();
149 type_container_resolve_order
= new ArrayList ();
151 Report
.WarningLevel
= 4;
155 StrongNameKeyFile
= null;
156 StrongNameKeyContainer
= null;
157 StrongNameDelaySign
= false;
161 Version
= LanguageVersion
.Default
;
162 Documentation
= null;
163 impl_details_class
= null;
164 helper_classes
= null;
167 // Setup default defines
169 RootContext
.AllDefines
= new ArrayList ();
170 RootContext
.AddConditional ("__MonoCS__");
173 public static void AddConditional (string p
)
175 if (AllDefines
.Contains (p
))
180 public static bool IsConditionalDefined (string value)
182 return AllDefines
.Contains (value);
185 static public RootTypes ToplevelTypes
{
189 public static void RegisterOrder (TypeContainer tc
)
191 type_container_resolve_order
.Add (tc
);
195 // This function is used to resolve the hierarchy tree.
196 // It processes interfaces, structs and classes in that order.
198 // It creates the TypeBuilder's as it processes the user defined
201 static public void ResolveTree ()
204 // Interfaces are processed next, as classes and
205 // structs might inherit from an object or implement
206 // a set of interfaces, we need to be able to tell
207 // them appart by just using the TypeManager.
209 foreach (TypeContainer tc
in root
.Types
)
212 foreach (TypeContainer tc
in root
.Types
)
215 if (root
.Delegates
!= null)
216 foreach (Delegate d
in root
.Delegates
)
221 // Closes all open types
225 // We usually use TypeBuilder types. When we are done
226 // creating the type (which will happen after we have added
227 // methods, fields, etc) we need to "Define" them before we
228 // can save the Assembly
230 static public void CloseTypes ()
233 // We do this in two passes, first we close the structs,
234 // then the classes, because it seems the code needs it this
235 // way. If this is really what is going on, we should probably
236 // make sure that we define the structs in order as well.
238 foreach (TypeContainer tc
in type_container_resolve_order
){
239 if (tc
.Kind
== Kind
.Struct
&& tc
.Parent
== root
){
244 foreach (TypeContainer tc
in type_container_resolve_order
){
245 if (!(tc
.Kind
== Kind
.Struct
&& tc
.Parent
== root
))
249 if (root
.Delegates
!= null)
250 foreach (Delegate d
in root
.Delegates
)
255 // If we have a <PrivateImplementationDetails> class, close it
257 if (helper_classes
!= null){
258 foreach (TypeBuilder type_builder
in helper_classes
) {
260 type_builder
.SetCustomAttribute (TypeManager
.GetCompilerGeneratedAttribute (Location
.Null
));
262 type_builder
.CreateType ();
266 type_container_resolve_order
= null;
267 helper_classes
= null;
269 TypeManager
.CleanUp ();
273 /// Used to register classes that need to be closed after all the
274 /// user defined classes
276 public static void RegisterCompilerGeneratedType (TypeBuilder helper_class
)
278 if (helper_classes
== null)
279 helper_classes
= new ArrayList ();
281 helper_classes
.Add (helper_class
);
284 static public void PopulateCoreType (TypeContainer root
, string name
)
286 DeclSpace ds
= (DeclSpace
) root
.GetDefinition (name
);
287 // Core type was imported
294 static public void BootCorlib_PopulateCoreTypes ()
296 PopulateCoreType (root
, "System.Object");
297 PopulateCoreType (root
, "System.ValueType");
298 PopulateCoreType (root
, "System.Attribute");
299 PopulateCoreType (root
, "System.Runtime.CompilerServices.IndexerNameAttribute");
303 // Populates the structs and classes with fields and methods
306 // This is invoked after all interfaces, structs and classes
307 // have been defined through `ResolveTree'
308 static public void PopulateTypes ()
311 if (type_container_resolve_order
!= null){
312 foreach (TypeContainer tc
in type_container_resolve_order
)
314 foreach (TypeContainer tc
in type_container_resolve_order
)
318 ArrayList delegates
= root
.Delegates
;
319 if (delegates
!= null){
320 foreach (Delegate d
in delegates
)
325 // Check for cycles in the struct layout
327 if (type_container_resolve_order
!= null){
328 Hashtable seen
= new Hashtable ();
329 foreach (TypeContainer tc
in type_container_resolve_order
)
330 TypeManager
.CheckStructCycles (tc
, seen
);
334 static public void EmitCode ()
336 if (type_container_resolve_order
!= null) {
337 foreach (TypeContainer tc
in type_container_resolve_order
)
340 if (Report
.Errors
> 0)
343 foreach (TypeContainer tc
in type_container_resolve_order
)
347 if (root
.Delegates
!= null) {
348 foreach (Delegate d
in root
.Delegates
)
352 CodeGen
.Assembly
.Emit (root
);
353 CodeGen
.Module
.Emit (root
);
357 // Public Field, used to track which method is the public entry
360 static public MethodInfo EntryPoint
;
363 // Track the location of the entry point.
365 static public Location EntryPointLocation
;
368 // These are used to generate unique names on the structs and fields.
370 static int field_count
;
373 // Makes an initialized struct, returns the field builder that
374 // references the data. Thanks go to Sergey Chaban for researching
375 // how to do this. And coming up with a shorter mechanism than I
376 // was able to figure out.
378 // This works but makes an implicit public struct $ArrayType$SIZE and
379 // makes the fields point to it. We could get more control if we did
382 // 1. DefineNestedType on the impl_details_class with our struct.
384 // 2. Define the field on the impl_details_class
386 static public FieldBuilder
MakeStaticData (byte [] data
)
390 if (impl_details_class
== null){
391 impl_details_class
= CodeGen
.Module
.Builder
.DefineType (
392 "<PrivateImplementationDetails>",
393 TypeAttributes
.NotPublic
,
394 TypeManager
.object_type
);
396 RegisterCompilerGeneratedType (impl_details_class
);
399 fb
= impl_details_class
.DefineInitializedData (
400 "$$field-" + (field_count
++), data
,
401 FieldAttributes
.Static
| FieldAttributes
.Assembly
);
406 public static void CheckUnsafeOption (Location loc
)
409 Report
.Error (227, loc
,
410 "Unsafe code requires the `unsafe' command line option to be specified");