2008-02-16 Ivan N. Zlatev <contact@i-nz.net>
[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 // Licensed under the terms of the GNU GPL
10 //
11 // (C) 2001 Ximian, Inc (http://www.ximian.com)
12 // (C) 2004 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                 // Contains the parsed tree
40                 //
41                 static RootTypes root;
42
43                 //
44                 // This hashtable contains all of the #definitions across the source code
45                 // it is used by the ConditionalAttribute handler.
46                 //
47                 public static Hashtable AllDefines = new Hashtable ();
48                 
49                 //
50                 // Whether we are being linked against the standard libraries.
51                 // This is only used to tell whether `System.Object' should
52                 // have a base class or not.
53                 //
54                 public static bool StdLib;
55
56                 //
57                 // This keeps track of the order in which classes were defined
58                 // so that we can poulate them in that order.
59                 //
60                 // Order is important, because we need to be able to tell, by
61                 // examining the list of methods of the base class, which ones are virtual
62                 // or abstract as well as the parent names (to implement new, 
63                 // override).
64                 //
65                 static ArrayList type_container_resolve_order;
66
67                 //
68                 // Holds a reference to the Private Implementation Details
69                 // class.
70                 //
71                 static ArrayList helper_classes;
72                 
73                 static TypeBuilder impl_details_class;
74
75                 public static Target Target;
76                 public static string TargetExt;
77
78                 public static bool VerifyClsCompliance = true;
79
80                 /// <summary>
81                 /// Holds /optimize option
82                 /// </summary>
83                 public static bool Optimize = true;
84
85                 public static LanguageVersion Version;
86
87                 //
88                 // We keep strongname related info here because
89                 // it's also used as complier options from CSC 8.x
90                 //
91                 public static string StrongNameKeyFile;
92                 public static string StrongNameKeyContainer;
93                 public static bool StrongNameDelaySign;
94
95                 //
96                 // If set, enable XML documentation generation
97                 //
98                 public static Documentation Documentation;
99
100                 static public string MainClass;
101
102                 //
103                 // Constructor
104                 //
105                 static RootContext ()
106                 {
107                         Reset ();
108                 }
109
110                 public static void Reset ()
111                 {
112                         root = new RootTypes ();
113                         type_container_resolve_order = new ArrayList ();
114                         EntryPoint = null;
115                         Report.WarningLevel = 3;
116                         Checked = false;
117                         Unsafe = false;
118                         StdLib = true;
119                         StrongNameKeyFile = null;
120                         StrongNameKeyContainer = null;
121                         StrongNameDelaySign = false;
122                         MainClass = null;
123                         Target = Target.Exe;
124                         TargetExt = ".exe";
125                         Version = LanguageVersion.Default;
126                         Documentation = null;
127                         impl_details_class = null;
128                         helper_classes = null;
129                 }
130
131                 public static bool NeedsEntryPoint {
132                         get { return RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe; }
133                 }
134
135                 static public RootTypes ToplevelTypes {
136                         get { return root; }
137                 }
138
139                 public static void RegisterOrder (TypeContainer tc)
140                 {
141                         type_container_resolve_order.Add (tc);
142                 }
143                 
144                 // 
145                 // The default compiler checked state
146                 //
147                 static public bool Checked;
148
149                 //
150                 // Whether to allow Unsafe code
151                 //
152                 static public bool Unsafe;
153                 
154                 // <remarks>
155                 //   This function is used to resolve the hierarchy tree.
156                 //   It processes interfaces, structs and classes in that order.
157                 //
158                 //   It creates the TypeBuilder's as it processes the user defined
159                 //   types.  
160                 // </remarks>
161                 static public void ResolveTree ()
162                 {
163                         //
164                         // Interfaces are processed next, as classes and
165                         // structs might inherit from an object or implement
166                         // a set of interfaces, we need to be able to tell
167                         // them appart by just using the TypeManager.
168                         //
169                         foreach (TypeContainer tc in root.Types)
170                                 tc.CreateType ();
171
172                         foreach (TypeContainer tc in root.Types)
173                                 tc.DefineType ();
174
175                         if (root.Delegates != null)
176                                 foreach (Delegate d in root.Delegates) 
177                                         d.DefineType ();
178                 }
179
180                 delegate bool VerifyBootstrapType (Type t);
181
182                 static Type BootstrapCorlib_ResolveType (TypeContainer root, string name, VerifyBootstrapType typeVerifier)
183                 {
184                         TypeLookupExpression tle = new TypeLookupExpression (name);
185                         Report.DisableReporting ();
186                         TypeExpr te = tle.ResolveAsTypeTerminal (root, false);
187                         Report.EnableReporting ();
188                         if (te == null) {
189                                 Report.Error (518, "The predefined type `{0}' is not defined or imported", name);
190                                 return null;
191                         }
192
193                         Type t = te.Type;
194                         if (!typeVerifier (t)) {
195                                 MemberCore mc = root.GetDefinition (name);
196                                 Location loc = Location.Null;
197                                 if (mc != null) {
198                                         name = mc.GetSignatureForError ();
199                                         loc = mc.Location;
200                                 }
201
202                                 Report.Error (520, loc, "The predefined type `{0}' is not declared correctly", name);
203                                 return null;
204                         }
205
206                         AttributeTester.RegisterNonObsoleteType (t);
207                         return t;
208                 }
209                 //
210                 // Resolves a single class during the corlib bootstrap process
211                 //
212                 static Type BootstrapCorlib_ResolveClass (TypeContainer root, string name)
213                 {
214                         return BootstrapCorlib_ResolveType (root, name, IsClass);
215                 }
216
217                 static bool IsClass (Type t)
218                 {
219                         DeclSpace ds = TypeManager.LookupDeclSpace (t);
220                         if (ds != null)
221                                 return ds is Class;
222                         return t.IsClass;
223                 }
224
225                 //
226                 // Resolves a struct during the corlib bootstrap process
227                 //
228                 static Type BootstrapCorlib_ResolveStruct (TypeContainer root, string name)
229                 {
230                         return BootstrapCorlib_ResolveType (root, name, IsStruct);
231                 }
232
233                 static bool IsStruct (Type t)
234                 {
235                         DeclSpace ds = TypeManager.LookupDeclSpace (t);
236                         if (ds != null)
237                                 return ds is Struct;
238                         
239                         return TypeManager.IsSubclassOf (t, TypeManager.value_type);                    
240                 }
241
242                 //
243                 // Resolves an interface during the corlib bootstrap process
244                 //
245                 static void BootstrapCorlib_ResolveInterface (TypeContainer root, string name)
246                 {
247                         BootstrapCorlib_ResolveType (root, name, IsInterface);
248                 }
249
250                 static bool IsInterface (Type t)
251                 {
252                         return t.IsInterface;
253                 }
254
255                 //
256                 // Resolves a delegate during the corlib bootstrap process
257                 //
258                 static void BootstrapCorlib_ResolveDelegate (TypeContainer root, string name)
259                 {
260                         BootstrapCorlib_ResolveType (root, name, IsDelegate);
261                 }
262
263                 static bool IsDelegate (Type t)
264                 {
265                         return TypeManager.IsDelegateType (t);
266                 }
267
268                 /// <summary>
269                 ///    Resolves the core types in the compiler when compiling with --nostdlib
270                 /// </summary>
271                 static public void ResolveCore ()
272                 {
273                         TypeManager.object_type = BootstrapCorlib_ResolveClass (root, "System.Object");
274                         TypeManager.system_object_expr.Type = TypeManager.object_type;
275                         TypeManager.value_type = BootstrapCorlib_ResolveClass (root, "System.ValueType");
276                         TypeManager.system_valuetype_expr.Type = TypeManager.value_type;
277
278                         //
279                         // The core attributes
280                         //
281                         BootstrapCorlib_ResolveInterface (root, "System.Runtime.InteropServices._Attribute");
282                         TypeManager.attribute_type = BootstrapCorlib_ResolveClass (root, "System.Attribute");
283                         TypeManager.obsolete_attribute_type = BootstrapCorlib_ResolveClass (root, "System.ObsoleteAttribute");
284                         if (TypeManager.obsolete_attribute_type != null) {
285                                 Class c = TypeManager.LookupClass (TypeManager.obsolete_attribute_type);
286                                 c.DefineMembers ();
287                         }
288                         
289                         TypeManager.indexer_name_type = BootstrapCorlib_ResolveClass (root, "System.Runtime.CompilerServices.IndexerNameAttribute");
290                         
291                         string [] interfaces_first_stage = {
292                                 "System.IComparable", "System.ICloneable",
293                                 "System.IConvertible",
294                                 
295                                 "System.Collections.IEnumerable",
296                                 "System.Collections.ICollection",
297                                 "System.Collections.IEnumerator",
298                                 "System.Collections.IList", 
299                                 "System.IAsyncResult",
300                                 "System.IDisposable",
301                                 
302                                 "System.Runtime.Serialization.ISerializable",
303
304                                 "System.Reflection.IReflect",
305                                 "System.Reflection.ICustomAttributeProvider",
306 #if GMCS_SOURCE
307                                 "System.Runtime.InteropServices._Exception",
308
309                                 //
310                                 // Generic types
311                                 //
312                                 "System.Collections.Generic.IEnumerator`1",
313                                 "System.Collections.Generic.IEnumerable`1"
314 #endif
315                         };
316
317                         foreach (string iname in interfaces_first_stage)
318                                 BootstrapCorlib_ResolveInterface (root, iname);
319
320                         //
321                         // These are the base value types
322                         //
323                         string [] structs_first_stage = {
324                                 "System.Byte",    "System.SByte",
325                                 "System.Int16",   "System.UInt16",
326                                 "System.Int32",   "System.UInt32",
327                                 "System.Int64",   "System.UInt64",
328                         };
329                         
330                         foreach (string cname in structs_first_stage)
331                                 BootstrapCorlib_ResolveStruct (root, cname);
332
333                         //
334                         // Now, we can load the enumerations, after this point,
335                         // we can use enums.
336                         //
337                         TypeManager.InitEnumUnderlyingTypes ();
338
339                         string [] structs_second_stage = {
340                                 "System.Single",  "System.Double",
341                                 "System.Char",
342                                 "System.Decimal", "System.Void",
343                                 "System.RuntimeFieldHandle",
344                                 "System.RuntimeArgumentHandle",
345                                 "System.RuntimeTypeHandle",
346                                 "System.IntPtr",
347                                 "System.TypedReference",
348                                 "System.ArgIterator"
349                         };
350                         
351                         TypeManager.bool_type = BootstrapCorlib_ResolveStruct (root, "System.Boolean");
352                         
353                         foreach (string cname in structs_second_stage)
354                                 BootstrapCorlib_ResolveStruct (root, cname);
355                         
356                         //
357                         // These are classes that depends on the core interfaces
358                         //
359                         string [] classes_second_stage = {
360                                 "System.Enum",
361                                 "System.String",
362                                 "System.Array",
363                                 "System.Reflection.MemberInfo",
364                                 "System.Type",
365                                 "System.Exception",
366 #if GMCS_SOURCE
367                                 "System.Activator",
368 #endif
369
370                                 //
371                                 // These are not really important in the order, but they
372                                 // are used by the compiler later on (typemanager/CoreLookupType-d)
373                                 //
374                                 "System.Runtime.CompilerServices.RuntimeHelpers",
375                                 "System.Reflection.DefaultMemberAttribute",
376                                 "System.Threading.Monitor",
377                                 "System.Threading.Interlocked",
378                                 
379                                 "System.AttributeUsageAttribute",
380                                 "System.Runtime.InteropServices.DllImportAttribute",
381                                 "System.Runtime.CompilerServices.MethodImplAttribute",
382                                 "System.Runtime.InteropServices.MarshalAsAttribute",
383 #if GMCS_SOURCE
384                                 "System.Runtime.CompilerServices.CompilerGeneratedAttribute",
385                                 "System.Runtime.CompilerServices.FixedBufferAttribute",
386 #endif
387                                 "System.Diagnostics.ConditionalAttribute",
388                                 "System.ParamArrayAttribute",
389                                 "System.CLSCompliantAttribute",
390                                 "System.Security.UnverifiableCodeAttribute",
391                                 "System.Security.Permissions.SecurityAttribute",
392                                 "System.Runtime.CompilerServices.DecimalConstantAttribute",
393                                 "System.Runtime.InteropServices.InAttribute",
394                                 "System.Runtime.InteropServices.OutAttribute",
395                                 "System.Runtime.InteropServices.StructLayoutAttribute",
396                                 "System.Runtime.InteropServices.FieldOffsetAttribute",
397 #if GMCS_SOURCE
398                                 "System.Runtime.InteropServices.DefaultCharSetAttribute",
399 #endif
400                                 "System.InvalidOperationException",
401                                 "System.NotSupportedException",
402                                 "System.MarshalByRefObject",
403                                 "System.Security.CodeAccessPermission",
404                                 "System.Runtime.CompilerServices.RequiredAttributeAttribute",
405                                 "System.Runtime.InteropServices.GuidAttribute",
406                                 "System.Reflection.AssemblyCultureAttribute"
407                         };
408
409                         foreach (string cname in classes_second_stage)
410                                 BootstrapCorlib_ResolveClass (root, cname);
411 #if GMCS_SOURCE
412                         BootstrapCorlib_ResolveStruct (root, "System.Nullable`1");
413 #endif
414                         TypeManager.delegate_type = BootstrapCorlib_ResolveClass (root, "System.Delegate");
415                         BootstrapCorlib_ResolveClass (root, "System.MulticastDelegate");
416
417                         BootstrapCorlib_ResolveDelegate (root, "System.AsyncCallback");
418                 }
419                         
420                 // <summary>
421                 //   Closes all open types
422                 // </summary>
423                 //
424                 // <remarks>
425                 //   We usually use TypeBuilder types.  When we are done
426                 //   creating the type (which will happen after we have added
427                 //   methods, fields, etc) we need to "Define" them before we
428                 //   can save the Assembly
429                 // </remarks>
430                 static public void CloseTypes ()
431                 {
432                         //
433                         // We do this in two passes, first we close the structs,
434                         // then the classes, because it seems the code needs it this
435                         // way.  If this is really what is going on, we should probably
436                         // make sure that we define the structs in order as well.
437                         //
438                         foreach (TypeContainer tc in type_container_resolve_order){
439                                 if (tc.Kind == Kind.Struct && tc.Parent == root){
440                                         tc.CloseType ();
441                                 }
442                         }
443
444                         foreach (TypeContainer tc in type_container_resolve_order){
445                                 if (!(tc.Kind == Kind.Struct && tc.Parent == root))
446                                         tc.CloseType ();                                        
447                         }
448                         
449                         if (root.Delegates != null)
450                                 foreach (Delegate d in root.Delegates)
451                                         d.CloseType ();
452
453
454                         //
455                         // If we have a <PrivateImplementationDetails> class, close it
456                         //
457                         if (helper_classes != null){
458                                 foreach (TypeBuilder type_builder in helper_classes) {
459 #if GMCS_SOURCE
460                                         type_builder.SetCustomAttribute (TypeManager.compiler_generated_attr);
461 #endif
462                                         type_builder.CreateType ();
463                                 }
464                         }
465                         
466                         type_container_resolve_order = null;
467                         helper_classes = null;
468                         //root = null;
469                         TypeManager.CleanUp ();
470                 }
471
472                 /// <summary>
473                 ///   Used to register classes that need to be closed after all the
474                 ///   user defined classes
475                 /// </summary>
476                 public static void RegisterCompilerGeneratedType (TypeBuilder helper_class)
477                 {
478                         if (helper_classes == null)
479                                 helper_classes = new ArrayList ();
480
481                         helper_classes.Add (helper_class);
482                 }
483                 
484                 static public void PopulateCoreType (TypeContainer root, string name)
485                 {
486                         DeclSpace ds = (DeclSpace) root.GetDefinition (name);
487                         // Core type was imported
488                         if (ds == null)
489                                 return;
490
491                         ds.DefineMembers ();
492                         ds.Define ();
493                 }
494                 
495                 static public void BootCorlib_PopulateCoreTypes ()
496                 {
497                         PopulateCoreType (root, "System.Object");
498                         PopulateCoreType (root, "System.ValueType");
499                         PopulateCoreType (root, "System.Attribute");
500                         PopulateCoreType (root, "System.Runtime.CompilerServices.IndexerNameAttribute");
501                 }
502                 
503                 // <summary>
504                 //   Populates the structs and classes with fields and methods
505                 // </summary>
506                 //
507                 // This is invoked after all interfaces, structs and classes
508                 // have been defined through `ResolveTree' 
509                 static public void PopulateTypes ()
510                 {
511
512                         if (type_container_resolve_order != null){
513                                 foreach (TypeContainer tc in type_container_resolve_order)
514                                         tc.ResolveType ();
515                                 foreach (TypeContainer tc in type_container_resolve_order)
516                                         tc.DefineMembers ();
517                         }
518
519                         ArrayList delegates = root.Delegates;
520                         if (delegates != null){
521                                 foreach (Delegate d in delegates)
522                                         d.DefineMembers ();
523                         }
524
525                         //
526                         // Check for cycles in the struct layout
527                         //
528                         if (type_container_resolve_order != null){
529                                 Hashtable seen = new Hashtable ();
530                                 foreach (TypeContainer tc in type_container_resolve_order)
531                                         TypeManager.CheckStructCycles (tc, seen);
532                         }
533                 }
534
535                 //
536                 // A generic hook delegate
537                 //
538                 public delegate void Hook ();
539
540                 //
541                 // A hook invoked when the code has been generated.
542                 //
543                 public static event Hook EmitCodeHook;
544
545                 //
546                 // DefineTypes is used to fill in the members of each type.
547                 //
548                 static public void DefineTypes ()
549                 {
550                         ArrayList delegates = root.Delegates;
551                         if (delegates != null){
552                                 foreach (Delegate d in delegates)
553                                         d.Define ();
554                         }
555
556                         if (type_container_resolve_order != null){
557                                 foreach (TypeContainer tc in type_container_resolve_order) {
558                                         // When compiling corlib, these types have already been
559                                         // populated from BootCorlib_PopulateCoreTypes ().
560                                         if (!RootContext.StdLib &&
561                                             ((tc.Name == "System.Object") ||
562                                              (tc.Name == "System.Attribute") ||
563                                              (tc.Name == "System.ValueType") ||
564                                              (tc.Name == "System.Runtime.CompilerServices.IndexerNameAttribute")))
565                                                 continue;
566
567                                         tc.Define ();
568                                 }
569                         }
570                 }
571
572                 static public void EmitCode ()
573                 {
574                         if (type_container_resolve_order != null) {
575                                 foreach (TypeContainer tc in type_container_resolve_order)
576                                         tc.EmitType ();
577
578                                 if (Report.Errors > 0)
579                                         return;
580
581                                 foreach (TypeContainer tc in type_container_resolve_order)
582                                         tc.VerifyMembers ();
583                         }
584                         
585                         if (root.Delegates != null) {
586                                 foreach (Delegate d in root.Delegates)
587                                         d.Emit ();
588                         }                       
589                         //
590                         // Run any hooks after all the types have been defined.
591                         // This is used to create nested auxiliary classes for example
592                         //
593
594                         if (EmitCodeHook != null)
595                                 EmitCodeHook ();
596
597                         CodeGen.Assembly.Emit (root);
598                         CodeGen.Module.Emit (root);
599                 }
600                 
601                 //
602                 // Public Field, used to track which method is the public entry
603                 // point.
604                 //
605                 static public MethodInfo EntryPoint;
606
607                 //
608                 // Track the location of the entry point.
609                 //
610                 static public Location EntryPointLocation;
611
612                 //
613                 // These are used to generate unique names on the structs and fields.
614                 //
615                 static int field_count;
616                 
617                 //
618                 // Makes an initialized struct, returns the field builder that
619                 // references the data.  Thanks go to Sergey Chaban for researching
620                 // how to do this.  And coming up with a shorter mechanism than I
621                 // was able to figure out.
622                 //
623                 // This works but makes an implicit public struct $ArrayType$SIZE and
624                 // makes the fields point to it.  We could get more control if we did
625                 // use instead:
626                 //
627                 // 1. DefineNestedType on the impl_details_class with our struct.
628                 //
629                 // 2. Define the field on the impl_details_class
630                 //
631                 static public FieldBuilder MakeStaticData (byte [] data)
632                 {
633                         FieldBuilder fb;
634                         
635                         if (impl_details_class == null){
636                                 impl_details_class = CodeGen.Module.Builder.DefineType (
637                                         "<PrivateImplementationDetails>",
638                                         TypeAttributes.NotPublic,
639                                         TypeManager.object_type);
640                                 
641                                 RegisterCompilerGeneratedType (impl_details_class);
642                         }
643
644                         fb = impl_details_class.DefineInitializedData (
645                                 "$$field-" + (field_count++), data,
646                                 FieldAttributes.Static | FieldAttributes.Assembly);
647                         
648                         return fb;
649                 }
650
651                 public static void CheckUnsafeOption (Location loc)
652                 {
653                         if (!Unsafe) {
654                                 Report.Error (227, loc, 
655                                         "Unsafe code requires the `unsafe' command line option to be specified");
656                         }
657                 }
658         }
659 }
660               
661