2 // roottypes.cs: keeps a tree representation of the generated code
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Marek Safar (marek.safar@gmail.com)
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
14 using System.Collections.Generic;
15 using System.Runtime.InteropServices;
16 using Mono.CompilerServices.SymbolWriter;
19 using IKVM.Reflection;
20 using IKVM.Reflection.Emit;
22 using System.Reflection;
23 using System.Reflection.Emit;
29 // Module (top-level type) container
31 public class ModuleContainer : TypeContainer
35 // Compiler generated container for static data
37 sealed class StaticDataContainer : CompilerGeneratedClass
39 Dictionary<int, Struct> size_types;
42 public StaticDataContainer (ModuleContainer module)
43 : base (module, new MemberName ("<PrivateImplementationDetails>" + module.builder.ModuleVersionId.ToString ("B"), Location.Null), Modifiers.STATIC)
45 size_types = new Dictionary<int, Struct> ();
48 public override void CloseType ()
52 foreach (var entry in size_types) {
53 entry.Value.CloseType ();
57 public FieldSpec DefineInitializedData (byte[] data, Location loc)
60 if (!size_types.TryGetValue (data.Length, out size_type)) {
62 // Build common type for this data length. We cannot use
63 // DefineInitializedData because it creates public type,
64 // and its name is not unique among modules
66 size_type = new Struct (null, this, new MemberName ("$ArrayType=" + data.Length, Location), Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, null);
67 size_type.CreateType ();
68 size_type.DefineType ();
70 size_types.Add (data.Length, size_type);
72 var pa = Module.PredefinedAttributes.StructLayout;
73 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.short_type)) {
74 var argsEncoded = new AttributeEncoder ();
75 argsEncoded.Encode ((short) LayoutKind.Explicit);
77 var field_size = pa.GetField ("Size", TypeManager.int32_type, Location);
78 var pack = pa.GetField ("Pack", TypeManager.int32_type, Location);
79 if (field_size != null) {
80 argsEncoded.EncodeNamedArguments (
81 new[] { field_size, pack },
82 new[] { new IntConstant ((int) data.Length, Location), new IntConstant (1, Location) }
86 pa.EmitAttribute (size_type.TypeBuilder, argsEncoded);
90 var name = "$field-" + fields.ToString ("X");
92 const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL;
93 var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
94 fbuilder.__SetDataAndRVA (data);
96 return new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
100 StaticDataContainer static_data;
103 // Makes const data field inside internal type container
105 public FieldSpec MakeStaticData (byte[] data, Location loc)
107 if (static_data == null) {
108 static_data = new StaticDataContainer (this);
109 static_data.CreateType ();
110 static_data.DefineType ();
112 AddCompilerGeneratedClass (static_data);
115 return static_data.DefineInitializedData (data, loc);
119 public CharSet? DefaultCharSet;
120 public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
122 Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
123 Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> arrays;
125 AssemblyDefinition assembly;
126 readonly CompilerContext context;
127 readonly RootNamespace global_ns;
128 Dictionary<string, RootNamespace> alias_ns;
130 ModuleBuilder builder;
132 bool has_extenstion_method;
134 PredefinedAttributes predefined_attributes;
135 PredefinedTypes predefined_types;
137 static readonly string[] attribute_targets = new string[] { "assembly", "module" };
139 public ModuleContainer (CompilerContext context)
140 : base (null, null, MemberName.Null, null, 0)
142 this.context = context;
144 caching_flags &= ~(Flags.Obsolete_Undetected | Flags.Excluded_Undetected);
146 types = new List<TypeContainer> ();
147 anonymous_types = new Dictionary<int, List<AnonymousTypeClass>> ();
148 global_ns = new GlobalRootNamespace ();
149 alias_ns = new Dictionary<string, RootNamespace> ();
150 arrays = new Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ();
155 public Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ArraysCache {
161 public override AttributeTargets AttributeTargets {
163 return AttributeTargets.Assembly;
167 public ModuleBuilder Builder {
173 public override CompilerContext Compiler {
179 public override AssemblyDefinition DeclaringAssembly {
185 public bool HasDefaultCharSet {
187 return DefaultCharSet.HasValue;
191 public bool HasExtensionMethod {
193 return has_extenstion_method;
196 has_extenstion_method = value;
201 // Returns module global:: namespace
203 public RootNamespace GlobalRootNamespace {
209 public override ModuleContainer Module {
215 internal PredefinedAttributes PredefinedAttributes {
217 return predefined_attributes;
221 internal PredefinedTypes PredefinedTypes {
223 return predefined_types;
227 public override string[] ValidAttributeTargets {
229 return attribute_targets;
235 public override void Accept (StructuralVisitor visitor)
237 visitor.Visit (this);
240 public void AddAnonymousType (AnonymousTypeClass type)
242 List<AnonymousTypeClass> existing;
243 if (!anonymous_types.TryGetValue (type.Parameters.Count, out existing))
244 if (existing == null) {
245 existing = new List<AnonymousTypeClass> ();
246 anonymous_types.Add (type.Parameters.Count, existing);
252 public void AddAttributes (List<Attribute> attrs)
254 AddAttributes (attrs, this);
257 public void AddAttributes (List<Attribute> attrs, IMemberContext context)
259 foreach (Attribute a in attrs)
260 a.AttachTo (this, context);
262 if (attributes == null) {
263 attributes = new Attributes (attrs);
266 attributes.AddAttributes (attrs);
269 public override TypeContainer AddPartial (TypeContainer nextPart)
271 return AddPartial (nextPart, nextPart.Name);
274 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
276 if (a.Target == AttributeTargets.Assembly) {
277 assembly.ApplyAttributeBuilder (a, ctor, cdata, pa);
281 if (a.Type == pa.DefaultCharset) {
282 switch (a.GetCharSetValue ()) {
287 DefaultCharSet = CharSet.Auto;
288 DefaultCharSetType = TypeAttributes.AutoClass;
290 case CharSet.Unicode:
291 DefaultCharSet = CharSet.Unicode;
292 DefaultCharSetType = TypeAttributes.UnicodeClass;
295 Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid",
296 a.GetSignatureForError ());
299 } else if (a.Type == pa.CLSCompliant) {
300 Attribute cls = DeclaringAssembly.CLSCompliantAttribute;
302 Report.Warning (3012, 1, a.Location,
303 "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
304 } else if (DeclaringAssembly.IsCLSCompliant != a.GetBoolean ()) {
305 Report.SymbolRelatedToPreviousError (cls.Location, cls.GetSignatureForError ());
306 Report.Warning (3017, 1, a.Location,
307 "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly");
312 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
315 public override void CloseType ()
317 foreach (TypeContainer tc in types) {
321 if (compiler_generated != null)
322 foreach (CompilerGeneratedClass c in compiler_generated)
326 public TypeBuilder CreateBuilder (string name, TypeAttributes attr, int typeSize)
328 return builder.DefineType (name, attr, null, typeSize);
332 // Creates alias global namespace
334 public RootNamespace CreateRootNamespace (string alias)
336 if (alias == global_ns.Alias) {
337 NamespaceEntry.Error_GlobalNamespaceRedefined (Location.Null, Report);
342 if (!alias_ns.TryGetValue (alias, out rn)) {
343 rn = new RootNamespace (alias);
344 alias_ns.Add (alias, rn);
350 public void Create (AssemblyDefinition assembly, ModuleBuilder moduleBuilder)
352 this.assembly = assembly;
353 builder = moduleBuilder;
356 public new void CreateType ()
358 foreach (TypeContainer tc in types)
362 public new void Define ()
364 InitializePredefinedTypes ();
366 foreach (TypeContainer tc in types)
369 foreach (TypeContainer tc in types)
370 tc.ResolveTypeParameters ();
372 foreach (TypeContainer tc in types) {
375 } catch (Exception e) {
376 throw new InternalErrorException (tc, e);
381 public override void Emit ()
383 if (OptAttributes != null)
384 OptAttributes.Emit ();
386 if (Compiler.Settings.Unsafe) {
387 var pa = PredefinedAttributes.UnverifiableCode;
389 pa.EmitAttribute (builder);
392 foreach (var tc in types)
393 tc.DefineConstants ();
395 foreach (TypeContainer tc in types)
398 if (Compiler.Report.Errors > 0)
401 foreach (TypeContainer tc in types)
404 if (compiler_generated != null)
405 foreach (var c in compiler_generated)
409 public AnonymousTypeClass GetAnonymousType (IList<AnonymousTypeParameter> parameters)
411 List<AnonymousTypeClass> candidates;
412 if (!anonymous_types.TryGetValue (parameters.Count, out candidates))
416 foreach (AnonymousTypeClass at in candidates) {
417 for (i = 0; i < parameters.Count; ++i) {
418 if (!parameters [i].Equals (at.Parameters [i]))
422 if (i == parameters.Count)
429 public RootNamespace GetRootNamespace (string name)
432 alias_ns.TryGetValue (name, out rn);
436 public override string GetSignatureForError ()
441 public void InitializePredefinedTypes ()
443 predefined_attributes = new PredefinedAttributes (this);
444 predefined_types = new PredefinedTypes (this);
447 public override bool IsClsComplianceRequired ()
449 return DeclaringAssembly.IsCLSCompliant;
452 protected override bool AddMemberType (TypeContainer ds)
454 if (!AddToContainer (ds, ds.Name))
456 ds.NamespaceEntry.NS.AddType (ds.Definition);
460 protected override void RemoveMemberType (DeclSpace ds)
462 ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
463 base.RemoveMemberType (ds);
466 public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type)
468 Attribute a = OptAttributes.Search ("assembly", a_type);
475 public void SetDeclaringAssembly (AssemblyDefinition assembly)
477 // TODO: This setter is quite ugly but I have not found a way around it yet
478 this.assembly = assembly;
482 class RootDeclSpace : TypeContainer {
483 public RootDeclSpace (ModuleContainer module, NamespaceEntry ns)
484 : base (ns, null, MemberName.Null, null, 0)
486 PartialContainer = module;
489 public override AttributeTargets AttributeTargets {
490 get { throw new InternalErrorException ("should not be called"); }
493 public override CompilerContext Compiler {
495 return PartialContainer.Compiler;
499 public override string DocCommentHeader {
500 get { throw new InternalErrorException ("should not be called"); }
503 public override void DefineType ()
505 throw new InternalErrorException ("should not be called");
508 public override ModuleContainer Module {
510 return PartialContainer.Module;
514 public override void Accept (StructuralVisitor visitor)
516 throw new InternalErrorException ("should not be called");
519 public override bool IsClsComplianceRequired ()
521 return PartialContainer.IsClsComplianceRequired ();
524 public override FullNamedExpression LookupNamespaceAlias (string name)
526 return NamespaceEntry.LookupNamespaceAlias (name);