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