2
// module.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.
11
// Copyright 2011 Xamarin Inc
15
using System.Collections.Generic;
16
using System.Runtime.InteropServices;
17
using Mono.CompilerServices.SymbolWriter;
21
using IKVM.Reflection;
22
using IKVM.Reflection.Emit;
24
using System.Reflection;
25
using System.Reflection.Emit;
31
// Module (top-level type) container
33
public sealed class ModuleContainer : TypeContainer
37
// Compiler generated container for static data
39
sealed class StaticDataContainer : CompilerGeneratedContainer
41
readonly Dictionary<int, Struct> size_types;
44
public StaticDataContainer (ModuleContainer module)
45
: base (module, new MemberName ("<PrivateImplementationDetails>" + module.builder.ModuleVersionId.ToString ("B"), Location.Null),
46
Modifiers.STATIC | Modifiers.INTERNAL)
48
size_types = new Dictionary<int, Struct> ();
51
public override void CloseContainer ()
53
base.CloseContainer ();
55
foreach (var entry in size_types) {
56
entry.Value.CloseContainer ();
60
public FieldSpec DefineInitializedData (byte[] data, Location loc)
63
if (!size_types.TryGetValue (data.Length, out size_type)) {
65
// Build common type for this data length. We cannot use
66
// DefineInitializedData because it creates public type,
67
// and its name is not unique among modules
69
size_type = new Struct (this, new MemberName ("$ArrayType=" + data.Length, loc), Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, null);
70
size_type.CreateContainer ();
71
size_type.DefineContainer ();
73
size_types.Add (data.Length, size_type);
75
// It has to work even if StructLayoutAttribute does not exist
76
size_type.TypeBuilder.__SetLayout (1, data.Length);
79
var name = "$field-" + fields.ToString ("X");
81
const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL;
82
var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
83
fbuilder.__SetDataAndRVA (data);
85
return new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
89
StaticDataContainer static_data;
92
// Makes const data field inside internal type container
94
public FieldSpec MakeStaticData (byte[] data, Location loc)
96
if (static_data == null) {
97
static_data = new StaticDataContainer (this);
98
static_data.CreateContainer ();
99
static_data.DefineContainer ();
101
AddCompilerGeneratedClass (static_data);
104
return static_data.DefineInitializedData (data, loc);
108
public CharSet? DefaultCharSet;
109
public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
111
readonly Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
112
readonly Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> array_types;
113
readonly Dictionary<TypeSpec, PointerContainer> pointer_types;
114
readonly Dictionary<TypeSpec, ReferenceContainer> reference_types;
115
readonly Dictionary<TypeSpec, MethodSpec> attrs_cache;
117
AssemblyDefinition assembly;
118
readonly CompilerContext context;
119
readonly RootNamespace global_ns;
120
readonly Dictionary<string, RootNamespace> alias_ns;
122
ModuleBuilder builder;
124
bool has_extenstion_method;
126
PredefinedAttributes predefined_attributes;
127
PredefinedTypes predefined_types;
128
PredefinedMembers predefined_members;
130
static readonly string[] attribute_targets = new string[] { "assembly", "module" };
132
public ModuleContainer (CompilerContext context)
133
: base (null, MemberName.Null, null, 0)
135
this.context = context;
137
caching_flags &= ~(Flags.Obsolete_Undetected | Flags.Excluded_Undetected);
139
containers = new List<TypeContainer> ();
140
anonymous_types = new Dictionary<int, List<AnonymousTypeClass>> ();
141
global_ns = new GlobalRootNamespace ();
142
alias_ns = new Dictionary<string, RootNamespace> ();
143
array_types = new Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ();
144
pointer_types = new Dictionary<TypeSpec, PointerContainer> ();
145
reference_types = new Dictionary<TypeSpec, ReferenceContainer> ();
146
attrs_cache = new Dictionary<TypeSpec, MethodSpec> ();
151
internal Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ArrayTypesCache {
158
// Cache for parameter-less attributes
160
internal Dictionary<TypeSpec, MethodSpec> AttributeConstructorCache {
166
public override AttributeTargets AttributeTargets {
168
return AttributeTargets.Assembly;
172
public ModuleBuilder Builder {
178
public override CompilerContext Compiler {
184
public int CounterAnonymousTypes { get; set; }
185
public int CounterAnonymousMethods { get; set; }
186
public int CounterAnonymousContainers { get; set; }
187
public int CounterSwitchTypes { get; set; }
189
public AssemblyDefinition DeclaringAssembly {
195
internal DocumentationBuilder DocumentationBuilder {
199
public override string DocCommentHeader {
201
throw new NotSupportedException ();
205
public Evaluator Evaluator {
209
public bool HasDefaultCharSet {
211
return DefaultCharSet.HasValue;
215
public bool HasExtensionMethod {
217
return has_extenstion_method;
220
has_extenstion_method = value;
224
public bool HasTypesFullyDefined {
229
// Returns module global:: namespace
231
public RootNamespace GlobalRootNamespace {
237
public override ModuleContainer Module {
243
internal Dictionary<TypeSpec, PointerContainer> PointerTypesCache {
245
return pointer_types;
249
internal PredefinedAttributes PredefinedAttributes {
251
return predefined_attributes;
255
internal PredefinedMembers PredefinedMembers {
257
return predefined_members;
261
internal PredefinedTypes PredefinedTypes {
263
return predefined_types;
267
internal Dictionary<TypeSpec, ReferenceContainer> ReferenceTypesCache {
269
return reference_types;
273
public override string[] ValidAttributeTargets {
275
return attribute_targets;
281
public override void Accept (StructuralVisitor visitor)
283
visitor.Visit (this);
286
public void AddAnonymousType (AnonymousTypeClass type)
288
List<AnonymousTypeClass> existing;
289
if (!anonymous_types.TryGetValue (type.Parameters.Count, out existing))
290
if (existing == null) {
291
existing = new List<AnonymousTypeClass> ();
292
anonymous_types.Add (type.Parameters.Count, existing);
298
public void AddAttribute (Attribute attr, IMemberContext context)
300
attr.AttachTo (this, context);
302
if (attributes == null) {
303
attributes = new Attributes (attr);
307
attributes.AddAttribute (attr);
310
public override void AddTypeContainer (TypeContainer tc)
315
public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
317
if (a.Target == AttributeTargets.Assembly) {
318
assembly.ApplyAttributeBuilder (a, ctor, cdata, pa);
322
if (a.Type == pa.DefaultCharset) {
323
switch (a.GetCharSetValue ()) {
328
DefaultCharSet = CharSet.Auto;
329
DefaultCharSetType = TypeAttributes.AutoClass;
331
case CharSet.Unicode:
332
DefaultCharSet = CharSet.Unicode;
333
DefaultCharSetType = TypeAttributes.UnicodeClass;
336
Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid",
337
a.GetSignatureForError ());
340
} else if (a.Type == pa.CLSCompliant) {
341
Attribute cls = DeclaringAssembly.CLSCompliantAttribute;
343
Report.Warning (3012, 1, a.Location,
344
"You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
345
} else if (DeclaringAssembly.IsCLSCompliant != a.GetBoolean ()) {
346
Report.SymbolRelatedToPreviousError (cls.Location, cls.GetSignatureForError ());
347
Report.Warning (3017, 1, a.Location,
348
"You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly");
353
builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
356
public override void CloseContainer ()
358
if (anonymous_types != null) {
359
foreach (var atypes in anonymous_types)
360
foreach (var at in atypes.Value)
361
at.CloseContainer ();
364
base.CloseContainer ();
367
public TypeBuilder CreateBuilder (string name, TypeAttributes attr, int typeSize)
369
return builder.DefineType (name, attr, null, typeSize);
373
// Creates alias global namespace
375
public RootNamespace CreateRootNamespace (string alias)
377
if (alias == global_ns.Alias) {
378
RootNamespace.Error_GlobalNamespaceRedefined (Report, Location.Null);
383
if (!alias_ns.TryGetValue (alias, out rn)) {
384
rn = new RootNamespace (alias);
385
alias_ns.Add (alias, rn);
391
public void Create (AssemblyDefinition assembly, ModuleBuilder moduleBuilder)
393
this.assembly = assembly;
394
builder = moduleBuilder;
397
public override bool Define ()
403
HasTypesFullyDefined = true;
408
public override bool DefineContainer ()
412
return base.DefineContainer ();
415
public override void EmitContainer ()
417
if (OptAttributes != null)
418
OptAttributes.Emit ();
420
if (Compiler.Settings.Unsafe) {
421
var pa = PredefinedAttributes.UnverifiableCode;
423
pa.EmitAttribute (builder);
426
foreach (var tc in containers) {
430
base.EmitContainer ();
432
if (Compiler.Report.Errors == 0)
435
if (anonymous_types != null) {
436
foreach (var atypes in anonymous_types)
437
foreach (var at in atypes.Value)
442
internal override void GenerateDocComment (DocumentationBuilder builder)
444
foreach (var tc in containers)
445
tc.GenerateDocComment (builder);
448
public AnonymousTypeClass GetAnonymousType (IList<AnonymousTypeParameter> parameters)
450
List<AnonymousTypeClass> candidates;
451
if (!anonymous_types.TryGetValue (parameters.Count, out candidates))
455
foreach (AnonymousTypeClass at in candidates) {
456
for (i = 0; i < parameters.Count; ++i) {
457
if (!parameters [i].Equals (at.Parameters [i]))
461
if (i == parameters.Count)
468
public override void GetCompletionStartingWith (string prefix, List<string> results)
470
var names = Evaluator.GetVarNames ();
471
results.AddRange (names.Where (l => l.StartsWith (prefix)));
474
public RootNamespace GetRootNamespace (string name)
477
alias_ns.TryGetValue (name, out rn);
481
public override string GetSignatureForError ()
486
public void InitializePredefinedTypes ()
488
predefined_attributes = new PredefinedAttributes (this);
489
predefined_types = new PredefinedTypes (this);
490
predefined_members = new PredefinedMembers (this);
493
public override bool IsClsComplianceRequired ()
495
return DeclaringAssembly.IsCLSCompliant;
498
public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type)
500
Attribute a = OptAttributes.Search ("assembly", a_type);
507
public void SetDeclaringAssembly (AssemblyDefinition assembly)
509
// TODO: This setter is quite ugly but I have not found a way around it yet
510
this.assembly = assembly;