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
34 // Compiler generated container for static data
36 sealed class StaticDataContainer : CompilerGeneratedClass
38 Dictionary<int, Struct> size_types;
41 static MethodInfo set_data;
44 public StaticDataContainer (ModuleContainer module)
45 : base (module, new MemberName ("<PrivateImplementationDetails>" + module.builder.ModuleVersionId.ToString ("B"), Location.Null), Modifiers.STATIC)
47 size_types = new Dictionary<int, Struct> ();
50 public override void CloseType ()
54 foreach (var entry in size_types) {
55 entry.Value.CloseType ();
59 public FieldSpec DefineInitializedData (byte[] data, Location loc)
62 if (!size_types.TryGetValue (data.Length, out size_type)) {
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
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 ();
72 size_types.Add (data.Length, size_type);
74 var pa = Module.PredefinedAttributes.StructLayout;
75 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.short_type)) {
76 var argsEncoded = new AttributeEncoder ();
77 argsEncoded.Encode ((short) LayoutKind.Explicit);
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) }
88 pa.EmitAttribute (size_type.TypeBuilder, argsEncoded);
92 var name = "$field-" + fields.ToString ("X");
94 const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL;
95 var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
97 fbuilder.__SetDataAndRVA (data);
100 set_data = typeof (FieldBuilder).GetMethod ("SetRVAData", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
103 set_data.Invoke (fbuilder, new object[] { data });
105 Report.RuntimeMissingSupport (loc, "SetRVAData");
109 return new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
113 public CharSet? DefaultCharSet;
114 public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
116 Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
117 StaticDataContainer static_data;
119 AssemblyDefinition assembly;
120 readonly CompilerContext context;
121 readonly RootNamespace global_ns;
122 Dictionary<string, RootNamespace> alias_ns;
124 ModuleBuilder builder;
126 bool has_extenstion_method;
128 PredefinedAttributes predefined_attributes;
129 PredefinedTypes predefined_types;
131 static readonly string[] attribute_targets = new string[] { "assembly", "module" };
133 public ModuleContainer (CompilerContext context)
134 : base (null, null, MemberName.Null, null, 0)
136 this.context = context;
138 caching_flags &= ~(Flags.Obsolete_Undetected | Flags.Excluded_Undetected);
140 types = new List<TypeContainer> ();
141 anonymous_types = new Dictionary<int, List<AnonymousTypeClass>> ();
142 global_ns = new GlobalRootNamespace ();
143 alias_ns = new Dictionary<string, RootNamespace> ();
148 public override AttributeTargets AttributeTargets {
150 return AttributeTargets.Assembly;
154 public ModuleBuilder Builder {
160 public override CompilerContext Compiler {
166 public override AssemblyDefinition DeclaringAssembly {
172 public bool HasDefaultCharSet {
174 return DefaultCharSet.HasValue;
178 public bool HasExtensionMethod {
180 return has_extenstion_method;
183 has_extenstion_method = value;
188 // Returns module global:: namespace
190 public RootNamespace GlobalRootNamespace {
196 public override ModuleContainer Module {
202 internal PredefinedAttributes PredefinedAttributes {
204 return predefined_attributes;
208 internal PredefinedTypes PredefinedTypes {
210 return predefined_types;
214 public override string[] ValidAttributeTargets {
216 return attribute_targets;
222 public void AddAnonymousType (AnonymousTypeClass type)
224 List<AnonymousTypeClass> existing;
225 if (!anonymous_types.TryGetValue (type.Parameters.Count, out existing))
226 if (existing == null) {
227 existing = new List<AnonymousTypeClass> ();
228 anonymous_types.Add (type.Parameters.Count, existing);
234 public void AddAttributes (List<Attribute> attrs)
236 AddAttributes (attrs, this);
239 public void AddAttributes (List<Attribute> attrs, IMemberContext context)
241 foreach (Attribute a in attrs)
242 a.AttachTo (this, context);
244 if (attributes == null) {
245 attributes = new Attributes (attrs);
248 attributes.AddAttributes (attrs);
251 public override TypeContainer AddPartial (TypeContainer nextPart)
253 return AddPartial (nextPart, nextPart.Name);
256 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
258 if (a.Target == AttributeTargets.Assembly) {
259 assembly.ApplyAttributeBuilder (a, ctor, cdata, pa);
263 if (a.Type == pa.DefaultCharset) {
264 switch (a.GetCharSetValue ()) {
269 DefaultCharSet = CharSet.Auto;
270 DefaultCharSetType = TypeAttributes.AutoClass;
272 case CharSet.Unicode:
273 DefaultCharSet = CharSet.Unicode;
274 DefaultCharSetType = TypeAttributes.UnicodeClass;
277 Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid",
278 a.GetSignatureForError ());
281 } else if (a.Type == pa.CLSCompliant) {
282 Attribute cls = DeclaringAssembly.CLSCompliantAttribute;
284 Report.Warning (3012, 1, a.Location,
285 "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
286 } else if (DeclaringAssembly.IsCLSCompliant != a.GetBoolean ()) {
287 Report.SymbolRelatedToPreviousError (cls.Location, cls.GetSignatureForError ());
288 Report.Warning (3017, 1, a.Location,
289 "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly");
294 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
297 public override void CloseType ()
299 foreach (TypeContainer tc in types) {
303 if (compiler_generated != null)
304 foreach (CompilerGeneratedClass c in compiler_generated)
308 public TypeBuilder CreateBuilder (string name, TypeAttributes attr, int typeSize)
310 return builder.DefineType (name, attr, null, typeSize);
314 // Creates alias global namespace
316 public RootNamespace CreateRootNamespace (string alias)
318 if (alias == global_ns.Alias) {
319 NamespaceEntry.Error_GlobalNamespaceRedefined (Location.Null, Report);
324 if (!alias_ns.TryGetValue (alias, out rn)) {
325 rn = new RootNamespace (alias);
326 alias_ns.Add (alias, rn);
332 public void Create (AssemblyDefinition assembly, ModuleBuilder moduleBuilder)
334 this.assembly = assembly;
335 builder = moduleBuilder;
338 public new void CreateType ()
340 foreach (TypeContainer tc in types)
344 public new void Define ()
346 // FIXME: Temporary hack for repl to reset
349 InitializePredefinedTypes ();
351 foreach (TypeContainer tc in types)
354 foreach (TypeContainer tc in types)
355 tc.ResolveTypeParameters ();
357 foreach (TypeContainer tc in types) {
360 } catch (Exception e) {
361 throw new InternalErrorException (tc, e);
366 public override void Emit ()
368 if (OptAttributes != null)
369 OptAttributes.Emit ();
371 if (RootContext.Unsafe) {
372 var pa = PredefinedAttributes.UnverifiableCode;
374 pa.EmitAttribute (builder);
377 foreach (var tc in types)
378 tc.DefineConstants ();
380 foreach (TypeContainer tc in types)
383 if (Compiler.Report.Errors > 0)
386 foreach (TypeContainer tc in types)
389 if (compiler_generated != null)
390 foreach (var c in compiler_generated)
394 public AnonymousTypeClass GetAnonymousType (IList<AnonymousTypeParameter> parameters)
396 List<AnonymousTypeClass> candidates;
397 if (!anonymous_types.TryGetValue (parameters.Count, out candidates))
401 foreach (AnonymousTypeClass at in candidates) {
402 for (i = 0; i < parameters.Count; ++i) {
403 if (!parameters [i].Equals (at.Parameters [i]))
407 if (i == parameters.Count)
414 public RootNamespace GetRootNamespace (string name)
417 alias_ns.TryGetValue (name, out rn);
421 public override string GetSignatureForError ()
426 public void InitializePredefinedTypes ()
428 predefined_attributes = new PredefinedAttributes (this);
429 predefined_types = new PredefinedTypes (this);
432 public override bool IsClsComplianceRequired ()
434 return DeclaringAssembly.IsCLSCompliant;
438 // Makes const data field inside internal type container
440 public FieldSpec MakeStaticData (byte[] data, Location loc)
442 if (static_data == null) {
443 static_data = new StaticDataContainer (this);
444 static_data.CreateType ();
445 static_data.DefineType ();
447 AddCompilerGeneratedClass (static_data);
450 return static_data.DefineInitializedData (data, loc);
453 protected override bool AddMemberType (TypeContainer ds)
455 if (!AddToContainer (ds, ds.Name))
457 ds.NamespaceEntry.NS.AddType (ds.Definition);
461 protected override void RemoveMemberType (DeclSpace ds)
463 ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
464 base.RemoveMemberType (ds);
467 public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type)
469 Attribute a = OptAttributes.Search ("assembly", a_type);
476 public void SetDeclaringAssembly (AssemblyDefinition assembly)
478 // TODO: This setter is quite ugly but I have not found a way around it yet
479 this.assembly = assembly;
483 class RootDeclSpace : TypeContainer {
484 public RootDeclSpace (NamespaceEntry ns)
485 : base (ns, null, MemberName.Null, null, 0)
487 PartialContainer = RootContext.ToplevelTypes;
490 public override AttributeTargets AttributeTargets {
491 get { throw new InternalErrorException ("should not be called"); }
494 public override CompilerContext Compiler {
496 return PartialContainer.Compiler;
500 public override string DocCommentHeader {
501 get { throw new InternalErrorException ("should not be called"); }
504 public override void DefineType ()
506 throw new InternalErrorException ("should not be called");
509 public override ModuleContainer Module {
511 return PartialContainer.Module;
515 public override bool IsClsComplianceRequired ()
517 return PartialContainer.IsClsComplianceRequired ();
520 public override FullNamedExpression LookupNamespaceAlias (string name)
522 return NamespaceEntry.LookupNamespaceAlias (name);