2009-06-10 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         enum LanguageVersion
23         {
24                 ISO_1           = 1,
25                 ISO_2           = 2,
26                 V_3                     = 3,
27                 V_4                     = 4,
28                 Future          = 100,
29
30 #if NET_4_0 || BOOTSTRAP_NET_4_0
31                 Default         = LanguageVersion.V_4,
32 #else
33                 Default         = LanguageVersion.V_3
34 #endif
35         }
36
37         enum MetadataVersion
38         {
39                 v1,
40                 v2,
41                 v4
42         }
43
44         class RootContext {
45
46                 //
47                 // COMPILER OPTIONS CLASS
48                 //
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;
54
55                 public static MetadataVersion MetadataCompatibilityVersion;
56
57                 //
58                 // We keep strongname related info here because
59                 // it's also used as complier options from CSC 8.x
60                 //
61                 public static string StrongNameKeyFile;
62                 public static string StrongNameKeyContainer;
63                 public static bool StrongNameDelaySign;
64
65                 //
66                 // If set, enable XML documentation generation
67                 //
68                 public static Documentation Documentation;
69
70                 static public string MainClass;
71
72                 // 
73                 // The default compiler checked state
74                 //
75                 static public bool Checked;
76
77                 //
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.
81                 //
82                 static public bool EvalMode;
83
84                 //
85                 // If true, the compiler is operating in statement mode,
86                 // this currently turns local variable declaration into
87                 // static variables of a class
88                 //
89                 static public bool StatementMode;
90                 
91                 //
92                 // Whether to allow Unsafe code
93                 //
94                 static public bool Unsafe;
95
96                 //
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.
100                 //
101                 public static bool StdLib;
102
103                 public static bool NeedsEntryPoint {
104                         get { return Target == Target.Exe || Target == Target.WinExe; }
105                 }
106
107                 //
108                 // COMPILER OPTIONS CLASS END
109                 //
110
111                 //
112                 // Contains the parsed tree
113                 //
114                 static ModuleContainer root;
115
116                 //
117                 // This hashtable contains all of the #definitions across the source code
118                 // it is used by the ConditionalAttribute handler.
119                 //
120                 static ArrayList AllDefines;
121                 
122                 //
123                 // This keeps track of the order in which classes were defined
124                 // so that we can poulate them in that order.
125                 //
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, 
129                 // override).
130                 //
131                 static ArrayList type_container_resolve_order;
132
133                 //
134                 // Holds a reference to the Private Implementation Details
135                 // class.
136                 //
137                 static ArrayList helper_classes;
138                 
139                 static TypeBuilder impl_details_class;
140
141                 //
142                 // Constructor
143                 //
144                 static RootContext ()
145                 {
146                         Reset (true);
147                 }
148
149                 public static void PartialReset ()
150                 {
151                         Reset (false);
152                 }
153                 
154                 public static void Reset (bool full)
155                 {
156                         if (full)
157                                 root = null;
158                         
159                         type_container_resolve_order = new ArrayList ();
160                         EntryPoint = null;
161                         Report.WarningLevel = 4;
162                         Checked = false;
163                         Unsafe = false;
164                         StdLib = true;
165                         StrongNameKeyFile = null;
166                         StrongNameKeyContainer = null;
167                         StrongNameDelaySign = false;
168                         MainClass = null;
169                         Target = Target.Exe;
170                         TargetExt = ".exe";
171                         Version = LanguageVersion.Default;
172                         Documentation = null;
173                         impl_details_class = null;
174                         helper_classes = null;
175
176 #if GMCS_SOURCE
177                         MetadataCompatibilityVersion = MetadataVersion.v2;
178 #else
179                         MetadataCompatibilityVersion = MetadataVersion.v1;
180 #endif
181
182                         //
183                         // Setup default defines
184                         //
185                         AllDefines = new ArrayList ();
186                         AddConditional ("__MonoCS__");
187                 }
188
189                 public static void AddConditional (string p)
190                 {
191                         if (AllDefines.Contains (p))
192                                 return;
193                         AllDefines.Add (p);
194                 }
195
196                 public static bool IsConditionalDefined (string value)
197                 {
198                         return AllDefines.Contains (value);
199                 }
200
201                 static public ModuleContainer ToplevelTypes {
202                         get { return root; }
203                         set { root = value; }
204                 }
205
206                 public static void RegisterOrder (TypeContainer tc)
207                 {
208                         type_container_resolve_order.Add (tc);
209                 }
210                 
211                 // <remarks>
212                 //   This function is used to resolve the hierarchy tree.
213                 //   It processes interfaces, structs and classes in that order.
214                 //
215                 //   It creates the TypeBuilder's as it processes the user defined
216                 //   types.  
217                 // </remarks>
218                 static public void ResolveTree ()
219                 {
220                         root.Resolve ();
221
222                         //
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.
227                         //
228                         foreach (TypeContainer tc in root.Types)
229                                 tc.CreateType ();
230
231                         foreach (TypeContainer tc in root.Types)
232                                 tc.DefineType ();
233
234                         if (root.Delegates != null)
235                                 foreach (Delegate d in root.Delegates) 
236                                         d.DefineType ();
237                 }
238
239                 // <summary>
240                 //   Closes all open types
241                 // </summary>
242                 //
243                 // <remarks>
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
248                 // </remarks>
249                 static public void CloseTypes ()
250                 {
251                         //
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.
256                         //
257                         foreach (TypeContainer tc in type_container_resolve_order){
258                                 if (tc.Kind == Kind.Struct && tc.Parent == root){
259                                         tc.CloseType ();
260                                 }
261                         }
262
263                         foreach (TypeContainer tc in type_container_resolve_order){
264                                 if (!(tc.Kind == Kind.Struct && tc.Parent == root))
265                                         tc.CloseType ();                                        
266                         }
267                         
268                         if (root.Delegates != null)
269                                 foreach (Delegate d in root.Delegates)
270                                         d.CloseType ();
271
272
273                         //
274                         // If we have a <PrivateImplementationDetails> class, close it
275                         //
276                         if (helper_classes != null){
277                                 foreach (TypeBuilder type_builder in helper_classes) {
278                                         PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (type_builder);
279                                         type_builder.CreateType ();
280                                 }
281                         }
282                         
283                         type_container_resolve_order = null;
284                         helper_classes = null;
285                         //root = null;
286                         TypeManager.CleanUp ();
287                 }
288
289                 /// <summary>
290                 ///   Used to register classes that need to be closed after all the
291                 ///   user defined classes
292                 /// </summary>
293                 public static void RegisterCompilerGeneratedType (TypeBuilder helper_class)
294                 {
295                         if (helper_classes == null)
296                                 helper_classes = new ArrayList ();
297
298                         helper_classes.Add (helper_class);
299                 }
300                 
301                 static public void PopulateCoreType (TypeContainer root, string name)
302                 {
303                         DeclSpace ds = (DeclSpace) root.GetDefinition (name);
304                         // Core type was imported
305                         if (ds == null)
306                                 return;
307
308                         ds.Define ();
309                 }
310                 
311                 static public void BootCorlib_PopulateCoreTypes ()
312                 {
313                         PopulateCoreType (root, "System.Object");
314                         PopulateCoreType (root, "System.ValueType");
315                         PopulateCoreType (root, "System.Attribute");
316                         PopulateCoreType (root, "System.Runtime.CompilerServices.IndexerNameAttribute");
317                 }
318                 
319                 // <summary>
320                 //   Populates the structs and classes with fields and methods
321                 // </summary>
322                 //
323                 // This is invoked after all interfaces, structs and classes
324                 // have been defined through `ResolveTree' 
325                 static public void PopulateTypes ()
326                 {
327
328                         if (type_container_resolve_order != null){
329                                 foreach (TypeContainer tc in type_container_resolve_order)
330                                         tc.ResolveType ();
331                                 foreach (TypeContainer tc in type_container_resolve_order) {
332                                         try {
333                                                 tc.Define ();
334                                         } catch (Exception e) {
335                                                 throw new InternalErrorException (tc, e);
336                                         }
337                                 }
338                         }
339
340                         ArrayList delegates = root.Delegates;
341                         if (delegates != null){
342                                 foreach (Delegate d in delegates)
343                                         d.Define ();
344                         }
345
346                         //
347                         // Check for cycles in the struct layout
348                         //
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);
353                         }
354                 }
355
356                 static public void EmitCode ()
357                 {
358                         if (type_container_resolve_order != null) {
359                                 foreach (TypeContainer tc in type_container_resolve_order)
360                                         tc.EmitType ();
361
362                                 if (Report.Errors > 0)
363                                         return;
364
365                                 foreach (TypeContainer tc in type_container_resolve_order)
366                                         tc.VerifyMembers ();
367                         }
368                         
369                         if (root.Delegates != null) {
370                                 foreach (Delegate d in root.Delegates)
371                                         d.Emit ();
372                         }                       
373
374                         CodeGen.Assembly.Emit (root);
375                         root.Emit ();
376                 }
377                 
378                 //
379                 // Public Field, used to track which method is the public entry
380                 // point.
381                 //
382                 static public Method EntryPoint;
383
384                 //
385                 // These are used to generate unique names on the structs and fields.
386                 //
387                 static int field_count;
388                 
389                 //
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.
394                 //
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
397                 // use instead:
398                 //
399                 // 1. DefineNestedType on the impl_details_class with our struct.
400                 //
401                 // 2. Define the field on the impl_details_class
402                 //
403                 static public FieldBuilder MakeStaticData (byte [] data)
404                 {
405                         FieldBuilder fb;
406                         
407                         if (impl_details_class == null){
408                                 impl_details_class = ToplevelTypes.Builder.DefineType (
409                                         "<PrivateImplementationDetails>",
410                                         TypeAttributes.NotPublic,
411                                         TypeManager.object_type);
412                                 
413                                 RegisterCompilerGeneratedType (impl_details_class);
414                         }
415
416                         fb = impl_details_class.DefineInitializedData (
417                                 "$$field-" + (field_count++), data,
418                                 FieldAttributes.Static | FieldAttributes.Assembly);
419                         
420                         return fb;
421                 }
422
423                 public static void CheckUnsafeOption (Location loc)
424                 {
425                         if (!Unsafe) {
426                                 Report.Error (227, loc, 
427                                         "Unsafe code requires the `unsafe' command line option to be specified");
428                         }
429                 }
430         }
431 }
432               
433