2008-11-24 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / rootcontext.cs
1 //
2 // rootcontext.cs: keeps track of our tree representation, and assemblies loaded.
3 //
4 // Author: Miguel de Icaza (miguel@ximian.com)
5 //            Ravi Pratap  (ravi@ximian.com)
6 //            Marek Safar  (marek.safar@gmail.com)
7 //
8 //
9 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 //
11 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
12 // Copyright 2004-2008 Novell, Inc
13
14 using System;
15 using System.Collections;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Diagnostics;
19
20 namespace Mono.CSharp {
21
22         public enum LanguageVersion
23         {
24                 ISO_1           = 1,
25                 Default_MCS     = 2,
26                 ISO_2           = 3,
27                 LINQ            = 4,
28
29 #if GMCS_SOURCE
30                 Default         = LINQ
31 #else
32                 Default         = Default_MCS
33 #endif
34         }
35
36         public class RootContext {
37
38                 //
39                 // COMPILER OPTIONS CLASS
40                 //
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;
46
47                 //
48                 // We keep strongname related info here because
49                 // it's also used as complier options from CSC 8.x
50                 //
51                 public static string StrongNameKeyFile;
52                 public static string StrongNameKeyContainer;
53                 public static bool StrongNameDelaySign;
54
55                 //
56                 // If set, enable XML documentation generation
57                 //
58                 public static Documentation Documentation;
59
60                 static public string MainClass;
61
62                 // 
63                 // The default compiler checked state
64                 //
65                 static public bool Checked;
66
67                 //
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.
71                 //
72                 static public bool EvalMode;
73
74                 //
75                 // If true, the compiler is operating in statement mode,
76                 // this currently turns local variable declaration into
77                 // static variables of a class
78                 //
79                 static public bool StatementMode;
80                 
81                 //
82                 // Whether to allow Unsafe code
83                 //
84                 static public bool Unsafe;
85
86                 //
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.
90                 //
91                 public static bool StdLib;
92
93                 public static bool NeedsEntryPoint {
94                         get { return Target == Target.Exe || Target == Target.WinExe; }
95                 }
96
97                 //
98                 // COMPILER OPTIONS CLASS END
99                 //
100
101                 //
102                 // Contains the parsed tree
103                 //
104                 static RootTypes root;
105
106                 //
107                 // This hashtable contains all of the #definitions across the source code
108                 // it is used by the ConditionalAttribute handler.
109                 //
110                 static ArrayList AllDefines = new ArrayList ();
111                 
112                 //
113                 // This keeps track of the order in which classes were defined
114                 // so that we can poulate them in that order.
115                 //
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, 
119                 // override).
120                 //
121                 static ArrayList type_container_resolve_order;
122
123                 //
124                 // Holds a reference to the Private Implementation Details
125                 // class.
126                 //
127                 static ArrayList helper_classes;
128                 
129                 static TypeBuilder impl_details_class;
130
131                 //
132                 // Constructor
133                 //
134                 static RootContext ()
135                 {
136                         Reset (true);
137                 }
138
139                 public static void PartialReset ()
140                 {
141                         Reset (false);
142                 }
143                 
144                 public static void Reset (bool full)
145                 {
146                         if (full)
147                                 root = new RootTypes ();
148                         
149                         type_container_resolve_order = new ArrayList ();
150                         EntryPoint = null;
151                         Report.WarningLevel = 4;
152                         Checked = false;
153                         Unsafe = false;
154                         StdLib = true;
155                         StrongNameKeyFile = null;
156                         StrongNameKeyContainer = null;
157                         StrongNameDelaySign = false;
158                         MainClass = null;
159                         Target = Target.Exe;
160                         TargetExt = ".exe";
161                         Version = LanguageVersion.Default;
162                         Documentation = null;
163                         impl_details_class = null;
164                         helper_classes = null;
165
166                         //
167                         // Setup default defines
168                         //
169                         RootContext.AllDefines = new ArrayList ();
170                         RootContext.AddConditional ("__MonoCS__");
171                 }
172
173                 public static void AddConditional (string p)
174                 {
175                         if (AllDefines.Contains (p))
176                                 return;
177                         AllDefines.Add (p);
178                 }
179
180                 public static bool IsConditionalDefined (string value)
181                 {
182                         return AllDefines.Contains (value);
183                 }
184
185                 static public RootTypes ToplevelTypes {
186                         get { return root; }
187                 }
188
189                 public static void RegisterOrder (TypeContainer tc)
190                 {
191                         type_container_resolve_order.Add (tc);
192                 }
193                 
194                 // <remarks>
195                 //   This function is used to resolve the hierarchy tree.
196                 //   It processes interfaces, structs and classes in that order.
197                 //
198                 //   It creates the TypeBuilder's as it processes the user defined
199                 //   types.  
200                 // </remarks>
201                 static public void ResolveTree ()
202                 {
203                         //
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.
208                         //
209                         foreach (TypeContainer tc in root.Types)
210                                 tc.CreateType ();
211
212                         foreach (TypeContainer tc in root.Types)
213                                 tc.DefineType ();
214
215                         if (root.Delegates != null)
216                                 foreach (Delegate d in root.Delegates) 
217                                         d.DefineType ();
218                 }
219
220                 // <summary>
221                 //   Closes all open types
222                 // </summary>
223                 //
224                 // <remarks>
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
229                 // </remarks>
230                 static public void CloseTypes ()
231                 {
232                         //
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.
237                         //
238                         foreach (TypeContainer tc in type_container_resolve_order){
239                                 if (tc.Kind == Kind.Struct && tc.Parent == root){
240                                         tc.CloseType ();
241                                 }
242                         }
243
244                         foreach (TypeContainer tc in type_container_resolve_order){
245                                 if (!(tc.Kind == Kind.Struct && tc.Parent == root))
246                                         tc.CloseType ();                                        
247                         }
248                         
249                         if (root.Delegates != null)
250                                 foreach (Delegate d in root.Delegates)
251                                         d.CloseType ();
252
253
254                         //
255                         // If we have a <PrivateImplementationDetails> class, close it
256                         //
257                         if (helper_classes != null){
258                                 foreach (TypeBuilder type_builder in helper_classes) {
259 #if GMCS_SOURCE
260                                         type_builder.SetCustomAttribute (TypeManager.GetCompilerGeneratedAttribute (Location.Null));
261 #endif
262                                         type_builder.CreateType ();
263                                 }
264                         }
265                         
266                         type_container_resolve_order = null;
267                         helper_classes = null;
268                         //root = null;
269                         TypeManager.CleanUp ();
270                 }
271
272                 /// <summary>
273                 ///   Used to register classes that need to be closed after all the
274                 ///   user defined classes
275                 /// </summary>
276                 public static void RegisterCompilerGeneratedType (TypeBuilder helper_class)
277                 {
278                         if (helper_classes == null)
279                                 helper_classes = new ArrayList ();
280
281                         helper_classes.Add (helper_class);
282                 }
283                 
284                 static public void PopulateCoreType (TypeContainer root, string name)
285                 {
286                         DeclSpace ds = (DeclSpace) root.GetDefinition (name);
287                         // Core type was imported
288                         if (ds == null)
289                                 return;
290
291                         ds.Define ();
292                 }
293                 
294                 static public void BootCorlib_PopulateCoreTypes ()
295                 {
296                         PopulateCoreType (root, "System.Object");
297                         PopulateCoreType (root, "System.ValueType");
298                         PopulateCoreType (root, "System.Attribute");
299                         PopulateCoreType (root, "System.Runtime.CompilerServices.IndexerNameAttribute");
300                 }
301                 
302                 // <summary>
303                 //   Populates the structs and classes with fields and methods
304                 // </summary>
305                 //
306                 // This is invoked after all interfaces, structs and classes
307                 // have been defined through `ResolveTree' 
308                 static public void PopulateTypes ()
309                 {
310
311                         if (type_container_resolve_order != null){
312                                 foreach (TypeContainer tc in type_container_resolve_order)
313                                         tc.ResolveType ();
314                                 foreach (TypeContainer tc in type_container_resolve_order)
315                                         tc.Define ();
316                         }
317
318                         ArrayList delegates = root.Delegates;
319                         if (delegates != null){
320                                 foreach (Delegate d in delegates)
321                                         d.Define ();
322                         }
323
324                         //
325                         // Check for cycles in the struct layout
326                         //
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);
331                         }
332                 }
333
334                 static public void EmitCode ()
335                 {
336                         if (type_container_resolve_order != null) {
337                                 foreach (TypeContainer tc in type_container_resolve_order)
338                                         tc.EmitType ();
339
340                                 if (Report.Errors > 0)
341                                         return;
342
343                                 foreach (TypeContainer tc in type_container_resolve_order)
344                                         tc.VerifyMembers ();
345                         }
346                         
347                         if (root.Delegates != null) {
348                                 foreach (Delegate d in root.Delegates)
349                                         d.Emit ();
350                         }                       
351
352                         CodeGen.Assembly.Emit (root);
353                         CodeGen.Module.Emit (root);
354                 }
355                 
356                 //
357                 // Public Field, used to track which method is the public entry
358                 // point.
359                 //
360                 static public MethodInfo EntryPoint;
361
362                 //
363                 // Track the location of the entry point.
364                 //
365                 static public Location EntryPointLocation;
366
367                 //
368                 // These are used to generate unique names on the structs and fields.
369                 //
370                 static int field_count;
371                 
372                 //
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.
377                 //
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
380                 // use instead:
381                 //
382                 // 1. DefineNestedType on the impl_details_class with our struct.
383                 //
384                 // 2. Define the field on the impl_details_class
385                 //
386                 static public FieldBuilder MakeStaticData (byte [] data)
387                 {
388                         FieldBuilder fb;
389                         
390                         if (impl_details_class == null){
391                                 impl_details_class = CodeGen.Module.Builder.DefineType (
392                                         "<PrivateImplementationDetails>",
393                                         TypeAttributes.NotPublic,
394                                         TypeManager.object_type);
395                                 
396                                 RegisterCompilerGeneratedType (impl_details_class);
397                         }
398
399                         fb = impl_details_class.DefineInitializedData (
400                                 "$$field-" + (field_count++), data,
401                                 FieldAttributes.Static | FieldAttributes.Assembly);
402                         
403                         return fb;
404                 }
405
406                 public static void CheckUnsafeOption (Location loc)
407                 {
408                         if (!Unsafe) {
409                                 Report.Error (227, loc, 
410                                         "Unsafe code requires the `unsafe' command line option to be specified");
411                         }
412                 }
413         }
414 }
415               
416