Flush (work in progress)
[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.Generic;
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                 ISO_2           = 2,
26                 V_3             = 3,
27                 V_4             = 4,
28                 Future          = 100,
29
30                 Default         = LanguageVersion.V_4,
31         }
32
33         public enum MetadataVersion
34         {
35                 v1,
36                 v2,
37                 v4
38         }
39
40         public class RootContext {
41
42                 //
43                 // COMPILER OPTIONS CLASS
44                 //
45                 public static Target Target;
46                 public static Platform Platform;
47                 public static string TargetExt;
48                 public static bool VerifyClsCompliance = true;
49                 public static bool Optimize = true;
50                 public static LanguageVersion Version;
51                 public static bool EnhancedWarnings;
52
53                 public static MetadataVersion MetadataCompatibilityVersion;
54
55                 //
56                 // We keep strongname related info here because
57                 // it's also used as complier options from CSC 8.x
58                 //
59                 public static string StrongNameKeyFile;
60                 public static string StrongNameKeyContainer;
61                 public static bool StrongNameDelaySign;
62
63                 //
64                 // If set, enable XML documentation generation
65                 //
66                 public static Documentation Documentation;
67
68                 static public string MainClass;
69
70                 // 
71                 // The default compiler checked state
72                 //
73                 static public bool Checked;
74
75                 //
76                 // If true, it means that the compiler is executing as
77                 // in eval mode so unresolved variables are resolved in
78                 // static classes maintained by the eval engine.
79                 //
80                 static public bool EvalMode;
81
82                 //
83                 // If true, the compiler is operating in statement mode,
84                 // this currently turns local variable declaration into
85                 // static variables of a class
86                 //
87                 static public bool StatementMode;
88                 
89                 //
90                 // Whether to allow Unsafe code
91                 //
92                 static public bool Unsafe;
93
94                 //
95                 // Whether we are being linked against the standard libraries.
96                 // This is only used to tell whether `System.Object' should
97                 // have a base class or not.
98                 //
99                 public static bool StdLib;
100
101                 public static bool NeedsEntryPoint {
102                         get { return Target == Target.Exe || Target == Target.WinExe; }
103                 }
104
105                 //
106                 // COMPILER OPTIONS CLASS END
107                 //
108
109                 //
110                 // Contains the parsed tree
111                 //
112                 static ModuleCompiled root;
113
114                 //
115                 // This hashtable contains all of the #definitions across the source code
116                 // it is used by the ConditionalAttribute handler.
117                 //
118                 static List<string> AllDefines;
119                 
120                 //
121                 // Holds a reference to the Private Implementation Details
122                 // class.
123                 //
124                 static List<TypeBuilder> helper_classes;
125                 
126                 static TypeBuilder impl_details_class;
127
128                 public static List<Enum> hack_corlib_enums = new List<Enum> ();
129
130                 //
131                 // Constructor
132                 //
133                 static RootContext ()
134                 {
135                         Reset (true);
136                 }
137
138                 public static void PartialReset ()
139                 {
140                         Reset (false);
141                 }
142                 
143                 public static void Reset (bool full)
144                 {
145                         impl_details_class = null;
146                         helper_classes = null;
147
148                         if (!full)
149                                 return;
150                         
151                         EntryPoint = null;
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                         Platform = Platform.AnyCPU;
162                         Version = LanguageVersion.Default;
163                         Documentation = null;
164                         impl_details_class = null;
165                         helper_classes = null;
166
167 #if NET_4_0
168                         MetadataCompatibilityVersion = MetadataVersion.v4;
169 #else
170                         MetadataCompatibilityVersion = MetadataVersion.v2;
171 #endif
172
173                         //
174                         // Setup default defines
175                         //
176                         AllDefines = new List<string> ();
177                         AddConditional ("__MonoCS__");
178                 }
179
180                 public static void AddConditional (string p)
181                 {
182                         if (AllDefines.Contains (p))
183                                 return;
184                         AllDefines.Add (p);
185                 }
186
187                 public static bool IsConditionalDefined (string value)
188                 {
189                         return AllDefines.Contains (value);
190                 }
191
192                 static public ModuleCompiled ToplevelTypes {
193                         get { return root; }
194                         set { root = value; }
195                 }
196
197                 // <remarks>
198                 //   This function is used to resolve the hierarchy tree.
199                 //   It processes interfaces, structs and classes in that order.
200                 //
201                 //   It creates the TypeBuilder's as it processes the user defined
202                 //   types.  
203                 // </remarks>
204                 static public void ResolveTree ()
205                 {
206                         root.Resolve ();
207
208                         //
209                         // Interfaces are processed next, as classes and
210                         // structs might inherit from an object or implement
211                         // a set of interfaces, we need to be able to tell
212                         // them appart by just using the TypeManager.
213                         //
214                         foreach (TypeContainer tc in root.Types)
215                                 tc.CreateType ();
216
217                         foreach (TypeContainer tc in root.Types)
218                                 tc.DefineType ();
219                 }
220
221                 static void HackCorlib ()
222                 {
223                         if (StdLib)
224                                 return;
225
226                         //
227                         // HACK: When building corlib mcs uses loaded mscorlib which
228                         // has different predefined types and this method sets mscorlib types
229                         // to be same to avoid type check errors in CreateType.
230                         //
231                         var type = typeof (Type);
232                         var system_4_type_arg = new[] { type, type, type, type };
233
234                         MethodInfo set_corlib_type_builders =
235                                 typeof (System.Reflection.Emit.AssemblyBuilder).GetMethod (
236                                 "SetCorlibTypeBuilders", BindingFlags.NonPublic | BindingFlags.Instance, null,
237                                 system_4_type_arg, null);
238
239                         if (set_corlib_type_builders == null) {
240                                 root.Compiler.Report.Warning (-26, 3, "The compilation may fail due to missing `{0}.SetCorlibTypeBuilders(...)' method",
241                                         typeof (System.Reflection.Emit.AssemblyBuilder).FullName);
242                                 return;
243                         }
244
245                         object[] args = new object[4];
246                         args[0] = TypeManager.object_type.GetMetaInfo ();
247                         args[1] = TypeManager.value_type.GetMetaInfo ();
248                         args[2] = TypeManager.enum_type.GetMetaInfo ();
249                         args[3] = TypeManager.void_type.GetMetaInfo ();
250                         set_corlib_type_builders.Invoke (CodeGen.Assembly.Builder, args);
251
252                         // Another Mono corlib HACK
253                         // mono_class_layout_fields requires to have enums created
254                         // before creating a class which used the enum for any of its fields
255                         foreach (var e in hack_corlib_enums)
256                                 e.CloseType ();
257                 }
258
259                 // <summary>
260                 //   Closes all open types
261                 // </summary>
262                 //
263                 // <remarks>
264                 //   We usually use TypeBuilder types.  When we are done
265                 //   creating the type (which will happen after we have added
266                 //   methods, fields, etc) we need to "Define" them before we
267                 //   can save the Assembly
268                 // </remarks>
269                 static public void CloseTypes ()
270                 {
271                         HackCorlib ();
272
273                         foreach (TypeContainer tc in root.Types){
274                                 tc.CloseType ();
275                         }
276
277                         if (root.CompilerGeneratedClasses != null)
278                                 foreach (CompilerGeneratedClass c in root.CompilerGeneratedClasses)
279                                         c.CloseType ();
280
281                         //
282                         // If we have a <PrivateImplementationDetails> class, close it
283                         //
284                         if (helper_classes != null){
285                                 foreach (TypeBuilder type_builder in helper_classes) {
286                                         PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (type_builder);
287                                         type_builder.CreateType ();
288                                 }
289                         }
290                         
291                         helper_classes = null;
292                 }
293
294                 /// <summary>
295                 ///   Used to register classes that need to be closed after all the
296                 ///   user defined classes
297                 /// </summary>
298                 public static void RegisterCompilerGeneratedType (TypeBuilder helper_class)
299                 {
300                         if (helper_classes == null)
301                                 helper_classes = new List<TypeBuilder> ();
302
303                         helper_classes.Add (helper_class);
304                 }
305                 
306                 // <summary>
307                 //   Populates the structs and classes with fields and methods
308                 // </summary>
309                 //
310                 // This is invoked after all interfaces, structs and classes
311                 // have been defined through `ResolveTree' 
312                 static public void PopulateTypes ()
313                 {
314                         foreach (TypeContainer tc in ToplevelTypes.Types)
315                                 tc.ResolveTypeParameters ();
316
317                         foreach (TypeContainer tc in ToplevelTypes.Types) {
318                                 try {
319                                         tc.Define ();
320                                 } catch (Exception e) {
321                                         throw new InternalErrorException (tc, e);
322                                 }
323                         }
324                 }
325
326                 static public void EmitCode ()
327                 {
328                         foreach (var tc in ToplevelTypes.Types)
329                                 tc.DefineConstants ();
330
331                         foreach (TypeContainer tc in ToplevelTypes.Types)
332                                 tc.EmitType ();
333
334                         if (ToplevelTypes.Compiler.Report.Errors > 0)
335                                 return;
336
337                         foreach (TypeContainer tc in ToplevelTypes.Types)
338                                 tc.VerifyMembers ();
339
340                         if (root.CompilerGeneratedClasses != null)
341                                 foreach (CompilerGeneratedClass c in root.CompilerGeneratedClasses)
342                                         c.EmitType ();
343
344                         CodeGen.Assembly.Emit (root);
345                         root.Emit ();
346                 }
347                 
348                 //
349                 // Public Field, used to track which method is the public entry
350                 // point.
351                 //
352                 static public Method EntryPoint;
353
354                 //
355                 // These are used to generate unique names on the structs and fields.
356                 //
357                 static int field_count;
358                 
359                 //
360                 // Makes an initialized struct, returns the field builder that
361                 // references the data.  Thanks go to Sergey Chaban for researching
362                 // how to do this.  And coming up with a shorter mechanism than I
363                 // was able to figure out.
364                 //
365                 // This works but makes an implicit public struct $ArrayType$SIZE and
366                 // makes the fields point to it.  We could get more control if we did
367                 // use instead:
368                 //
369                 // 1. DefineNestedType on the impl_details_class with our struct.
370                 //
371                 // 2. Define the field on the impl_details_class
372                 //
373                 static public FieldBuilder MakeStaticData (byte [] data)
374                 {
375                         FieldBuilder fb;
376                         
377                         if (impl_details_class == null){
378                                 impl_details_class = ToplevelTypes.Builder.DefineType (
379                                         "<PrivateImplementationDetails>",
380                                         TypeAttributes.NotPublic,
381                                         TypeManager.object_type.GetMetaInfo ());
382                                 
383                                 RegisterCompilerGeneratedType (impl_details_class);
384                         }
385
386                         fb = impl_details_class.DefineInitializedData (
387                                 "$$field-" + (field_count++), data,
388                                 FieldAttributes.Static | FieldAttributes.Assembly);
389                         
390                         return fb;
391                 }
392
393                 public static void CheckUnsafeOption (Location loc, Report Report)
394                 {
395                         if (!Unsafe) {
396                                 Report.Error (227, loc, 
397                                         "Unsafe code requires the `unsafe' command line option to be specified");
398                         }
399                 }
400         }
401 }