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 sealed class ModuleContainer : TypeContainer
35
// Compiler generated container for static data
37
sealed class StaticDataContainer : CompilerGeneratedClass
39
readonly 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);
71
var ctor = Module.PredefinedMembers.StructLayoutAttributeCtor.Resolve (Location);
73
var argsEncoded = new AttributeEncoder ();
74
argsEncoded.Encode ((short) LayoutKind.Explicit);
76
var field_size = Module.PredefinedMembers.StructLayoutSize.Resolve (Location);
77
var pack = Module.PredefinedMembers.StructLayoutPack.Resolve (Location);
78
if (field_size != null && pack != null) {
79
argsEncoded.EncodeNamedArguments (
80
new[] { field_size, pack },
81
new[] { new IntConstant (Compiler.BuiltinTypes, (int) data.Length, Location), new IntConstant (Compiler.BuiltinTypes, 1, Location) }
84
size_type.TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), argsEncoded.ToArray ());
89
var name = "$field-" + fields.ToString ("X");
91
const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL;
92
var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
93
fbuilder.__SetDataAndRVA (data);
95
return new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
99
StaticDataContainer static_data;
102
// Makes const data field inside internal type container
104
public FieldSpec MakeStaticData (byte[] data, Location loc)
106
if (static_data == null) {
107
static_data = new StaticDataContainer (this);
108
static_data.CreateType ();
109
static_data.DefineType ();
111
AddCompilerGeneratedClass (static_data);
114
return static_data.DefineInitializedData (data, loc);
118
public CharSet? DefaultCharSet;
119
public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
121
readonly Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
122
readonly Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> array_types;
123
readonly Dictionary<TypeSpec, PointerContainer> pointer_types;
124
readonly Dictionary<TypeSpec, ReferenceContainer> reference_types;
125
readonly Dictionary<TypeSpec, MethodSpec> attrs_cache;
127
// Used for unique namespaces/types during parsing
128
Dictionary<MemberName, ITypesContainer> defined_type_containers;
130
AssemblyDefinition assembly;
131
readonly CompilerContext context;
132
readonly RootNamespace global_ns;
133
readonly Dictionary<string, RootNamespace> alias_ns;
135
ModuleBuilder builder;
137
bool has_extenstion_method;
139
PredefinedAttributes predefined_attributes;
140
PredefinedTypes predefined_types;
141
PredefinedMembers predefined_members;
143
static readonly string[] attribute_targets = new string[] { "assembly", "module" };
145
public ModuleContainer (CompilerContext context)
146
: base (null, null, MemberName.Null, null, 0)
148
this.context = context;
150
caching_flags &= ~(Flags.Obsolete_Undetected | Flags.Excluded_Undetected);
152
types = new List<TypeContainer> ();
153
anonymous_types = new Dictionary<int, List<AnonymousTypeClass>> ();
154
global_ns = new GlobalRootNamespace ();
155
alias_ns = new Dictionary<string, RootNamespace> ();
156
array_types = new Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ();
157
pointer_types = new Dictionary<TypeSpec, PointerContainer> ();
158
reference_types = new Dictionary<TypeSpec, ReferenceContainer> ();
159
attrs_cache = new Dictionary<TypeSpec, MethodSpec> ();
161
defined_type_containers = new Dictionary<MemberName, ITypesContainer> ();
166
internal Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ArrayTypesCache {
173
// Cache for parameter-less attributes
175
internal Dictionary<TypeSpec, MethodSpec> AttributeConstructorCache {
181
public override AttributeTargets AttributeTargets {
183
return AttributeTargets.Assembly;
187
public ModuleBuilder Builder {
193
public override CompilerContext Compiler {
199
public override AssemblyDefinition DeclaringAssembly {
205
internal DocumentationBuilder DocumentationBuilder {
209
public Evaluator Evaluator {
213
public bool HasDefaultCharSet {
215
return DefaultCharSet.HasValue;
219
public bool HasExtensionMethod {
221
return has_extenstion_method;
224
has_extenstion_method = value;
228
public bool HasTypesFullyDefined {
233
// Returns module global:: namespace
235
public RootNamespace GlobalRootNamespace {
241
public override ModuleContainer Module {
247
internal Dictionary<TypeSpec, PointerContainer> PointerTypesCache {
249
return pointer_types;
253
internal PredefinedAttributes PredefinedAttributes {
255
return predefined_attributes;
259
internal PredefinedMembers PredefinedMembers {
261
return predefined_members;
265
internal PredefinedTypes PredefinedTypes {
267
return predefined_types;
271
internal Dictionary<TypeSpec, ReferenceContainer> ReferenceTypesCache {
273
return reference_types;
277
public override string[] ValidAttributeTargets {
279
return attribute_targets;
285
public override void Accept (StructuralVisitor visitor)
287
visitor.Visit (this);
290
public void AddAnonymousType (AnonymousTypeClass type)
292
List<AnonymousTypeClass> existing;
293
if (!anonymous_types.TryGetValue (type.Parameters.Count, out existing))
294
if (existing == null) {
295
existing = new List<AnonymousTypeClass> ();
296
anonymous_types.Add (type.Parameters.Count, existing);
302
public void AddAttribute (Attribute attr, IMemberContext context)
304
attr.AttachTo (this, context);
306
if (attributes == null) {
307
attributes = new Attributes (attr);
311
attributes.AddAttribute (attr);
314
public override TypeContainer AddPartial (TypeContainer nextPart)
316
return AddPartial (nextPart, nextPart.Name);
319
public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
321
if (a.Target == AttributeTargets.Assembly) {
322
assembly.ApplyAttributeBuilder (a, ctor, cdata, pa);
326
if (a.Type == pa.DefaultCharset) {
327
switch (a.GetCharSetValue ()) {
332
DefaultCharSet = CharSet.Auto;
333
DefaultCharSetType = TypeAttributes.AutoClass;
335
case CharSet.Unicode:
336
DefaultCharSet = CharSet.Unicode;
337
DefaultCharSetType = TypeAttributes.UnicodeClass;
340
Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid",
341
a.GetSignatureForError ());
344
} else if (a.Type == pa.CLSCompliant) {
345
Attribute cls = DeclaringAssembly.CLSCompliantAttribute;
347
Report.Warning (3012, 1, a.Location,
348
"You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
349
} else if (DeclaringAssembly.IsCLSCompliant != a.GetBoolean ()) {
350
Report.SymbolRelatedToPreviousError (cls.Location, cls.GetSignatureForError ());
351
Report.Warning (3017, 1, a.Location,
352
"You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly");
357
builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
360
public override void CloseType ()
362
foreach (TypeContainer tc in types) {
366
if (compiler_generated != null)
367
foreach (CompilerGeneratedClass c in compiler_generated)
371
public TypeBuilder CreateBuilder (string name, TypeAttributes attr, int typeSize)
373
return builder.DefineType (name, attr, null, typeSize);
377
// Creates alias global namespace
379
public RootNamespace CreateRootNamespace (string alias)
381
if (alias == global_ns.Alias) {
382
NamespaceContainer.Error_GlobalNamespaceRedefined (Location.Null, Report);
387
if (!alias_ns.TryGetValue (alias, out rn)) {
388
rn = new RootNamespace (alias);
389
alias_ns.Add (alias, rn);
395
public void Create (AssemblyDefinition assembly, ModuleBuilder moduleBuilder)
397
this.assembly = assembly;
398
builder = moduleBuilder;
401
public new void CreateType ()
403
// Release cache used by parser only
404
if (Evaluator == null)
405
defined_type_containers = null;
407
defined_type_containers.Clear ();
409
foreach (TypeContainer tc in types)
413
public new void Define ()
415
foreach (TypeContainer tc in types)
418
foreach (TypeContainer tc in types)
419
tc.ResolveTypeParameters ();
421
foreach (TypeContainer tc in types) {
424
} catch (Exception e) {
425
throw new InternalErrorException (tc, e);
429
HasTypesFullyDefined = true;
432
public override void Emit ()
434
if (OptAttributes != null)
435
OptAttributes.Emit ();
437
if (Compiler.Settings.Unsafe) {
438
var pa = PredefinedAttributes.UnverifiableCode;
440
pa.EmitAttribute (builder);
443
foreach (var tc in types)
444
tc.DefineConstants ();
446
foreach (TypeContainer tc in types)
449
if (Compiler.Report.Errors > 0)
452
foreach (TypeContainer tc in types)
455
if (compiler_generated != null)
456
foreach (var c in compiler_generated)
460
internal override void GenerateDocComment (DocumentationBuilder builder)
462
foreach (var tc in types)
463
tc.GenerateDocComment (builder);
466
public AnonymousTypeClass GetAnonymousType (IList<AnonymousTypeParameter> parameters)
468
List<AnonymousTypeClass> candidates;
469
if (!anonymous_types.TryGetValue (parameters.Count, out candidates))
473
foreach (AnonymousTypeClass at in candidates) {
474
for (i = 0; i < parameters.Count; ++i) {
475
if (!parameters [i].Equals (at.Parameters [i]))
479
if (i == parameters.Count)
486
public RootNamespace GetRootNamespace (string name)
489
alias_ns.TryGetValue (name, out rn);
493
public override string GetSignatureForError ()
498
public void InitializePredefinedTypes ()
500
predefined_attributes = new PredefinedAttributes (this);
501
predefined_types = new PredefinedTypes (this);
502
predefined_members = new PredefinedMembers (this);
505
public override bool IsClsComplianceRequired ()
507
return DeclaringAssembly.IsCLSCompliant;
510
protected override bool AddMemberType (TypeContainer tc)
512
if (AddTypesContainer (tc)) {
513
if ((tc.ModFlags & Modifiers.PARTIAL) != 0)
514
defined_names.Add (tc.Name, tc);
516
tc.NamespaceEntry.NS.AddType (this, tc.Definition);
523
public bool AddTypesContainer (ITypesContainer container)
525
var mn = container.MemberName;
526
ITypesContainer found;
527
if (!defined_type_containers.TryGetValue (mn, out found)) {
528
defined_type_containers.Add (mn, container);
532
if (container is NamespaceContainer && found is NamespaceContainer)
535
var container_tc = container as TypeContainer;
536
var found_tc = found as TypeContainer;
537
if (container_tc != null && found_tc != null && container_tc.Kind == found_tc.Kind) {
538
if ((found_tc.ModFlags & container_tc.ModFlags & Modifiers.PARTIAL) != 0) {
542
if (((found_tc.ModFlags | container_tc.ModFlags) & Modifiers.PARTIAL) != 0) {
543
Report.SymbolRelatedToPreviousError (found_tc);
544
Error_MissingPartialModifier (container_tc);
549
string ns = mn.Left != null ? mn.Left.GetSignatureForError () : Module.GlobalRootNamespace.GetSignatureForError ();
550
mn = new MemberName (mn.Name, mn.TypeArguments, mn.Location);
552
Report.SymbolRelatedToPreviousError (found.Location, "");
553
Report.Error (101, container.Location,
554
"The namespace `{0}' already contains a definition for `{1}'",
555
ns, mn.GetSignatureForError ());
559
protected override void RemoveMemberType (TypeContainer ds)
561
defined_type_containers.Remove (ds.MemberName);
562
ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
563
base.RemoveMemberType (ds);
566
public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type)
568
Attribute a = OptAttributes.Search ("assembly", a_type);
575
public void SetDeclaringAssembly (AssemblyDefinition assembly)
577
// TODO: This setter is quite ugly but I have not found a way around it yet
578
this.assembly = assembly;
582
sealed class RootDeclSpace : TypeContainer {
583
public RootDeclSpace (ModuleContainer module, NamespaceContainer ns)
584
: base (ns, null, MemberName.Null, null, 0)
586
PartialContainer = module;
589
public override AttributeTargets AttributeTargets {
590
get { throw new InternalErrorException ("should not be called"); }
593
public override CompilerContext Compiler {
595
return PartialContainer.Compiler;
599
public override string DocCommentHeader {
600
get { throw new InternalErrorException ("should not be called"); }
603
public override void DefineType ()
605
throw new InternalErrorException ("should not be called");
608
public override ModuleContainer Module {
610
return PartialContainer.Module;
614
public override void Accept (StructuralVisitor visitor)
616
throw new InternalErrorException ("should not be called");
619
public override bool IsClsComplianceRequired ()
621
return PartialContainer.IsClsComplianceRequired ();
624
public override IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope)
629
public override FullNamedExpression LookupNamespaceAlias (string name)
631
return NamespaceEntry.LookupNamespaceAlias (name);