Removed SetCorlibTypeBuilders call
[mono.git] / mcs / mcs / roottypes.cs
1 //
2 // roottypes.cs: keeps a tree representation of the generated code
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 //          Marek Safar  (marek.safar@gmail.com)
6 //
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 //
9 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
11 //
12
13 using System;
14 using System.Collections.Generic;
15 using System.Runtime.InteropServices;
16 using Mono.CompilerServices.SymbolWriter;
17
18 #if STATIC
19 using IKVM.Reflection;
20 using IKVM.Reflection.Emit;
21 #else
22 using System.Reflection;
23 using System.Reflection.Emit;
24 #endif
25
26 namespace Mono.CSharp
27 {
28         //
29         // Module (top-level type) container
30         //
31         public class ModuleContainer : TypeContainer
32         {
33                 //
34                 // Compiler generated container for static data
35                 //
36                 sealed class StaticDataContainer : CompilerGeneratedClass
37                 {
38                         Dictionary<int, Struct> size_types;
39                         new int fields;
40 #if !STATIC
41                         static MethodInfo set_data;
42 #endif
43
44                         public StaticDataContainer (ModuleContainer module)
45                                 : base (module, new MemberName ("<PrivateImplementationDetails>" + module.builder.ModuleVersionId.ToString ("B"), Location.Null), Modifiers.STATIC)
46                         {
47                                 size_types = new Dictionary<int, Struct> ();
48                         }
49
50                         public override void CloseType ()
51                         {
52                                 base.CloseType ();
53
54                                 foreach (var entry in size_types) {
55                                         entry.Value.CloseType ();
56                                 }
57                         }
58
59                         public FieldSpec DefineInitializedData (byte[] data, Location loc)
60                         {
61                                 Struct size_type;
62                                 if (!size_types.TryGetValue (data.Length, out size_type)) {
63                                         //
64                                         // Build common type for this data length. We cannot use
65                                         // DefineInitializedData because it creates public type,
66                                         // and its name is not unique among modules
67                                         //
68                                         size_type = new Struct (null, this, new MemberName ("$ArrayType=" + data.Length, Location), Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, null);
69                                         size_type.CreateType ();
70                                         size_type.DefineType ();
71
72                                         size_types.Add (data.Length, size_type);
73
74                                         var pa = Module.PredefinedAttributes.StructLayout;
75                                         if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.short_type)) {
76                                                 var argsEncoded = new AttributeEncoder (false);
77                                                 argsEncoded.Encode ((short) LayoutKind.Explicit);
78
79                                                 var field_size = pa.GetField ("Size", TypeManager.int32_type, Location);
80                                                 var pack = pa.GetField ("Pack", TypeManager.int32_type, Location);
81                                                 if (field_size != null) {
82                                                         argsEncoded.EncodeNamedArguments (
83                                                                 new[] { field_size, pack },
84                                                                 new[] { new IntConstant ((int) data.Length, Location), new IntConstant (1, Location) }
85                                                         );
86                                                 }
87
88                                                 pa.EmitAttribute (size_type.TypeBuilder, argsEncoded);
89                                         }
90                                 }
91
92                                 var name = "$field-" + fields.ToString ("X");
93                                 ++fields;
94                                 const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL;
95                                 var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
96 #if STATIC
97                                 fbuilder.__SetDataAndRVA (data);
98 #else
99                                 if (set_data == null)
100                                         set_data = typeof (FieldBuilder).GetMethod ("SetRVAData", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
101
102                                 try {
103                                         set_data.Invoke (fbuilder, new object[] { data });
104                                 } catch {
105                                         Report.RuntimeMissingSupport (loc, "SetRVAData");
106                                 }
107 #endif
108
109                                 return new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
110                         }
111                 }
112
113                 public CharSet DefaultCharSet = CharSet.Ansi;
114                 public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
115
116                 Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
117                 StaticDataContainer static_data;
118
119                 AssemblyDefinition assembly;
120                 readonly CompilerContext context;
121                 readonly RootNamespace global_ns;
122                 Dictionary<string, RootNamespace> alias_ns;
123
124                 ModuleBuilder builder;
125
126                 bool has_default_charset;
127                 bool has_extenstion_method;
128
129                 PredefinedAttributes predefined_attributes;
130                 PredefinedTypes predefined_types;
131
132                 static readonly string[] attribute_targets = new string[] { "assembly", "module" };
133
134                 public ModuleContainer (CompilerContext context)
135                         : base (null, null, MemberName.Null, null, 0)
136                 {
137                         this.context = context;
138
139                         caching_flags &= ~(Flags.Obsolete_Undetected | Flags.Excluded_Undetected);
140
141                         types = new List<TypeContainer> ();
142                         anonymous_types = new Dictionary<int, List<AnonymousTypeClass>> ();
143                         global_ns = new GlobalRootNamespace ();
144                         alias_ns = new Dictionary<string, RootNamespace> ();
145                 }
146
147                 #region Properties
148
149                 public override AttributeTargets AttributeTargets {
150                         get {
151                                 return AttributeTargets.Assembly;
152                         }
153                 }
154
155                 public ModuleBuilder Builder {
156                         get {
157                                 return builder;
158                         }
159                 }
160
161                 public override CompilerContext Compiler {
162                         get {
163                                 return context;
164                         }
165                 }
166
167                 public override AssemblyDefinition DeclaringAssembly {
168                         get {
169                                 return assembly;
170                         }
171                 }
172
173                 public bool HasDefaultCharSet {
174                         get {
175                                 return has_default_charset;
176                         }
177                 }
178
179                 public bool HasExtensionMethod {
180                         get {
181                                 return has_extenstion_method;
182                         }
183                         set {
184                                 has_extenstion_method = value;
185                         }
186                 }
187
188                 //
189                 // Returns module global:: namespace
190                 //
191                 public RootNamespace GlobalRootNamespace {
192                     get {
193                         return global_ns;
194                     }
195                 }
196
197                 public override ModuleContainer Module {
198                         get {
199                                 return this;
200                         }
201                 }
202
203                 internal PredefinedAttributes PredefinedAttributes {
204                         get {
205                                 return predefined_attributes;
206                         }
207                 }
208
209                 internal PredefinedTypes PredefinedTypes {
210                         get {
211                                 return predefined_types;
212                         }
213                 }
214
215                 public override string[] ValidAttributeTargets {
216                         get {
217                                 return attribute_targets;
218                         }
219                 }
220
221                 #endregion
222
223                 public void AddAnonymousType (AnonymousTypeClass type)
224                 {
225                         List<AnonymousTypeClass> existing;
226                         if (!anonymous_types.TryGetValue (type.Parameters.Count, out existing))
227                         if (existing == null) {
228                                 existing = new List<AnonymousTypeClass> ();
229                                 anonymous_types.Add (type.Parameters.Count, existing);
230                         }
231
232                         existing.Add (type);
233                 }
234
235                 public void AddAttributes (List<Attribute> attrs)
236                 {
237                         AddAttributes (attrs, this);
238                 }
239
240                 public void AddAttributes (List<Attribute> attrs, IMemberContext context)
241                 {
242                         foreach (Attribute a in attrs)
243                                 a.AttachTo (this, context);
244
245                         if (attributes == null) {
246                                 attributes = new Attributes (attrs);
247                                 return;
248                         }
249                         attributes.AddAttributes (attrs);
250                 }
251
252                 public override TypeContainer AddPartial (TypeContainer nextPart)
253                 {
254                         return AddPartial (nextPart, nextPart.Name);
255                 }
256
257                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
258                 {
259                         if (a.Target == AttributeTargets.Assembly) {
260                                 assembly.ApplyAttributeBuilder (a, ctor, cdata, pa);
261                                 return;
262                         }
263
264                         if (a.Type == pa.CLSCompliant) {
265                                 Attribute cls = DeclaringAssembly.CLSCompliantAttribute;
266                                 if (cls == null) {
267                                         Report.Warning (3012, 1, a.Location,
268                                                 "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
269                                 } else if (DeclaringAssembly.IsCLSCompliant != a.GetBoolean ()) {
270                                         Report.SymbolRelatedToPreviousError (cls.Location, cls.GetSignatureForError ());
271                                         Report.Warning (3017, 1, a.Location,
272                                                 "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly");
273                                         return;
274                                 }
275                         }
276
277                         builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
278                 }
279
280                 public override void CloseType ()
281                 {
282                         foreach (TypeContainer tc in types) {
283                                 tc.CloseType ();
284                         }
285
286                         if (compiler_generated != null)
287                                 foreach (CompilerGeneratedClass c in compiler_generated)
288                                         c.CloseType ();
289                 }
290
291                 public TypeBuilder CreateBuilder (string name, TypeAttributes attr, int typeSize)
292                 {
293                         return builder.DefineType (name, attr, null, typeSize);
294                 }
295
296                 //
297                 // Creates alias global namespace
298                 //
299                 public RootNamespace CreateRootNamespace (string alias)
300                 {
301                         if (alias == global_ns.Alias) {
302                                 NamespaceEntry.Error_GlobalNamespaceRedefined (Location.Null, Report);
303                                 return global_ns;
304                         }
305
306                         RootNamespace rn;
307                         if (!alias_ns.TryGetValue (alias, out rn)) {
308                                 rn = new RootNamespace (alias);
309                                 alias_ns.Add (alias, rn);
310                         }
311
312                         return rn;
313                 }
314
315                 public new void Define ()
316                 {
317                         builder = assembly.CreateModuleBuilder ();
318
319                         // FIXME: Temporary hack for repl to reset
320                         static_data = null;
321
322                         // TODO: It should be done much later when the types are resolved
323                         // but that require DefineType clean-up
324                         ResolveGlobalAttributes ();
325
326                         foreach (TypeContainer tc in types)
327                                 tc.CreateType ();
328
329                         InitializePredefinedTypes ();
330
331                         foreach (TypeContainer tc in types)
332                                 tc.DefineType ();
333
334                         foreach (TypeContainer tc in types)
335                                 tc.ResolveTypeParameters ();
336
337                         foreach (TypeContainer tc in types) {
338                                 try {
339                                         tc.Define ();
340                                 } catch (Exception e) {
341                                         throw new InternalErrorException (tc, e);
342                                 }
343                         }
344                 }
345
346                 public override void Emit ()
347                 {
348                         if (OptAttributes != null)
349                                 OptAttributes.Emit ();
350
351                         if (RootContext.Unsafe) {
352                                 var pa = PredefinedAttributes.UnverifiableCode;
353                                 if (pa.IsDefined)
354                                         pa.EmitAttribute (builder);
355                         }
356
357                         foreach (var tc in types)
358                                 tc.DefineConstants ();
359
360                         foreach (TypeContainer tc in types)
361                                 tc.EmitType ();
362
363                         if (Compiler.Report.Errors > 0)
364                                 return;
365
366                         foreach (TypeContainer tc in types)
367                                 tc.VerifyMembers ();
368
369                         if (compiler_generated != null)
370                                 foreach (var c in compiler_generated)
371                                         c.EmitType ();
372                 }
373
374                 public AnonymousTypeClass GetAnonymousType (IList<AnonymousTypeParameter> parameters)
375                 {
376                         List<AnonymousTypeClass> candidates;
377                         if (!anonymous_types.TryGetValue (parameters.Count, out candidates))
378                                 return null;
379
380                         int i;
381                         foreach (AnonymousTypeClass at in candidates) {
382                                 for (i = 0; i < parameters.Count; ++i) {
383                                         if (!parameters [i].Equals (at.Parameters [i]))
384                                                 break;
385                                 }
386
387                                 if (i == parameters.Count)
388                                         return at;
389                         }
390
391                         return null;
392                 }
393
394                 public RootNamespace GetRootNamespace (string name)
395                 {
396                         RootNamespace rn;
397                         alias_ns.TryGetValue (name, out rn);
398                         return rn;
399                 }
400
401                 public override string GetSignatureForError ()
402                 {
403                         return "<module>";
404                 }
405
406                 public void InitializePredefinedTypes ()
407                 {
408                         predefined_attributes = new PredefinedAttributes (this);
409                         predefined_types = new PredefinedTypes (this);
410                 }
411
412                 public override bool IsClsComplianceRequired ()
413                 {
414                         return DeclaringAssembly.IsCLSCompliant;
415                 }
416
417                 //
418                 // Makes const data field inside internal type container
419                 //
420                 public FieldSpec MakeStaticData (byte[] data, Location loc)
421                 {
422                         if (static_data == null) {
423                                 static_data = new StaticDataContainer (this);
424                                 static_data.CreateType ();
425                                 static_data.DefineType ();
426
427                                 AddCompilerGeneratedClass (static_data);
428                         }
429
430                         return static_data.DefineInitializedData (data, loc);
431                 }
432
433                 protected override bool AddMemberType (TypeContainer ds)
434                 {
435                         if (!AddToContainer (ds, ds.Name))
436                                 return false;
437                         ds.NamespaceEntry.NS.AddType (ds.Definition);
438                         return true;
439                 }
440
441                 protected override void RemoveMemberType (DeclSpace ds)
442                 {
443                         ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
444                         base.RemoveMemberType (ds);
445                 }
446
447                 /// <summary>
448                 /// It is called very early therefore can resolve only predefined attributes
449                 /// </summary>
450                 void ResolveGlobalAttributes ()
451                 {
452                         if (OptAttributes == null)
453                                 return;
454
455                         if (!OptAttributes.CheckTargets ())
456                                 return;
457
458                         // FIXME: Define is wrong as the type may not exist yet
459                         var DefaultCharSet_attr = new PredefinedAttribute (this, "System.Runtime.InteropServices", "DefaultCharSetAttribute");
460                         DefaultCharSet_attr.Define ();
461                         Attribute a = ResolveModuleAttribute (DefaultCharSet_attr);
462                         if (a != null) {
463                                 has_default_charset = true;
464                                 DefaultCharSet = a.GetCharSetValue ();
465                                 switch (DefaultCharSet) {
466                                 case CharSet.Ansi:
467                                 case CharSet.None:
468                                         break;
469                                 case CharSet.Auto:
470                                         DefaultCharSetType = TypeAttributes.AutoClass;
471                                         break;
472                                 case CharSet.Unicode:
473                                         DefaultCharSetType = TypeAttributes.UnicodeClass;
474                                         break;
475                                 default:
476                                         Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid", 
477                                                 DefaultCharSet_attr.GetSignatureForError ());
478                                         break;
479                                 }
480                         }
481                 }
482
483                 public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type)
484                 {
485                         Attribute a = OptAttributes.Search ("assembly", a_type);
486                         if (a != null) {
487                                 a.Resolve ();
488                         }
489                         return a;
490                 }
491
492                 Attribute ResolveModuleAttribute (PredefinedAttribute a_type)
493                 {
494                         Attribute a = OptAttributes.Search ("module", a_type);
495                         if (a != null) {
496                                 a.Resolve ();
497                         }
498                         return a;
499                 }
500
501                 public void SetDeclaringAssembly (AssemblyDefinition assembly)
502                 {
503                         // TODO: This setter is quite ugly but I have not found a way around it yet
504                         this.assembly = assembly;
505                 }
506         }
507
508         class RootDeclSpace : TypeContainer {
509                 public RootDeclSpace (NamespaceEntry ns)
510                         : base (ns, null, MemberName.Null, null, 0)
511                 {
512                         PartialContainer = RootContext.ToplevelTypes;
513                 }
514
515                 public override AttributeTargets AttributeTargets {
516                         get { throw new InternalErrorException ("should not be called"); }
517                 }
518
519                 public override CompilerContext Compiler {
520                         get {
521                                 return PartialContainer.Compiler;
522                         }
523                 }
524
525                 public override string DocCommentHeader {
526                         get { throw new InternalErrorException ("should not be called"); }
527                 }
528
529                 public override void DefineType ()
530                 {
531                         throw new InternalErrorException ("should not be called");
532                 }
533
534                 public override ModuleContainer Module {
535                         get {
536                                 return PartialContainer.Module;
537                         }
538                 }
539
540                 public override bool IsClsComplianceRequired ()
541                 {
542                         return PartialContainer.IsClsComplianceRequired ();
543                 }
544
545                 public override FullNamedExpression LookupNamespaceAlias (string name)
546                 {
547                         return NamespaceEntry.LookupNamespaceAlias (name);
548                 }
549         }
550 }