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