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