Merge remote branch 'upstream/master'
[mono.git] / mcs / class / IKVM.Reflection / Emit / ModuleBuilder.cs
1 /*
2   Copyright (C) 2008-2010 Jeroen Frijters
3
4   This software is provided 'as-is', without any express or implied
5   warranty.  In no event will the authors be held liable for any damages
6   arising from the use of this software.
7
8   Permission is granted to anyone to use this software for any purpose,
9   including commercial applications, and to alter it and redistribute it
10   freely, subject to the following restrictions:
11
12   1. The origin of this software must not be misrepresented; you must not
13      claim that you wrote the original software. If you use this software
14      in a product, an acknowledgment in the product documentation would be
15      appreciated but is not required.
16   2. Altered source versions must be plainly marked as such, and must not be
17      misrepresented as being the original software.
18   3. This notice may not be removed or altered from any source distribution.
19
20   Jeroen Frijters
21   jeroen@frijters.net
22   
23 */
24 using System;
25 using System.Collections.Generic;
26 using System.IO;
27 using System.Diagnostics;
28 using System.Diagnostics.SymbolStore;
29 using System.Security.Cryptography;
30 using System.Runtime.CompilerServices;
31 using System.Runtime.InteropServices;
32 using IKVM.Reflection.Impl;
33 using IKVM.Reflection.Metadata;
34 using IKVM.Reflection.Writer;
35
36 namespace IKVM.Reflection.Emit
37 {
38         public sealed class ModuleBuilder : Module, ITypeOwner
39         {
40                 private static readonly bool usePublicKeyAssemblyReference = false;
41                 private readonly Guid mvid = Guid.NewGuid();
42                 private long imageBaseAddress = 0x00400000;
43                 private readonly AssemblyBuilder asm;
44                 internal readonly string moduleName;
45                 internal readonly string fileName;
46                 internal readonly ISymbolWriterImpl symbolWriter;
47                 private readonly TypeBuilder moduleType;
48                 private readonly List<TypeBuilder> types = new List<TypeBuilder>();
49                 private readonly Dictionary<Type, int> typeTokens = new Dictionary<Type, int>();
50                 private readonly Dictionary<Type, int> memberRefTypeTokens = new Dictionary<Type, int>();
51                 private readonly Dictionary<string, TypeBuilder> fullNameToType = new Dictionary<string, TypeBuilder>();
52                 internal readonly ByteBuffer methodBodies = new ByteBuffer(128 * 1024);
53                 internal readonly List<int> tokenFixupOffsets = new List<int>();
54                 internal readonly ByteBuffer initializedData = new ByteBuffer(512);
55                 internal readonly ByteBuffer manifestResources = new ByteBuffer(512);
56                 internal ResourceSection unmanagedResources;
57                 private readonly Dictionary<MemberInfo, int> importedMembers = new Dictionary<MemberInfo, int>();
58                 private readonly Dictionary<MemberRefKey, int> importedMemberRefs = new Dictionary<MemberRefKey, int>();
59                 private readonly Dictionary<Assembly, int> referencedAssemblies = new Dictionary<Assembly, int>();
60                 private List<AssemblyName> referencedAssemblyNames;
61                 private int nextPseudoToken = -1;
62                 private readonly List<int> resolvedTokens = new List<int>();
63                 internal readonly TableHeap Tables = new TableHeap();
64                 internal readonly StringHeap Strings = new StringHeap();
65                 internal readonly UserStringHeap UserStrings = new UserStringHeap();
66                 internal readonly GuidHeap Guids = new GuidHeap();
67                 internal readonly BlobHeap Blobs = new BlobHeap();
68
69                 struct MemberRefKey : IEquatable<MemberRefKey>
70                 {
71                         private readonly Type type;
72                         private readonly string name;
73                         private readonly Signature signature;
74
75                         internal MemberRefKey(Type type, string name, Signature signature)
76                         {
77                                 this.type = type;
78                                 this.name = name;
79                                 this.signature = signature;
80                         }
81
82                         public bool Equals(MemberRefKey other)
83                         {
84                                 return other.type.Equals(type)
85                                         && other.name == name
86                                         && other.signature.Equals(signature);
87                         }
88
89                         public override bool Equals(object obj)
90                         {
91                                 MemberRefKey? other = obj as MemberRefKey?;
92                                 return other != null && Equals(other);
93                         }
94
95                         public override int GetHashCode()
96                         {
97                                 return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode();
98                         }
99                 }
100
101                 internal ModuleBuilder(AssemblyBuilder asm, string moduleName, string fileName, bool emitSymbolInfo)
102                         : base(asm.universe)
103                 {
104                         this.asm = asm;
105                         this.moduleName = moduleName;
106                         this.fileName = fileName;
107                         if (emitSymbolInfo)
108                         {
109                                 symbolWriter = SymbolSupport.CreateSymbolWriterFor(this);
110                         }
111                         // <Module> must be the first record in the TypeDef table
112                         moduleType = new TypeBuilder(this, "<Module>", null, 0);
113                         types.Add(moduleType);
114                 }
115
116                 internal void PopulatePropertyAndEventTables()
117                 {
118                         // LAMESPEC the PropertyMap and EventMap tables are not required to be sorted by the CLI spec,
119                         // but .NET sorts them and Mono requires them to be sorted, so we have to populate the
120                         // tables in the right order
121                         foreach (TypeBuilder type in types)
122                         {
123                                 type.PopulatePropertyAndEventTables();
124                         }
125                 }
126
127                 internal void WriteTypeDefTable(MetadataWriter mw)
128                 {
129                         int fieldList = 1;
130                         int methodList = 1;
131                         foreach (TypeBuilder type in types)
132                         {
133                                 type.WriteTypeDefRecord(mw, ref fieldList, ref methodList);
134                         }
135                 }
136
137                 internal void WriteMethodDefTable(int baseRVA, MetadataWriter mw)
138                 {
139                         int paramList = 1;
140                         foreach (TypeBuilder type in types)
141                         {
142                                 type.WriteMethodDefRecords(baseRVA, mw, ref paramList);
143                         }
144                 }
145
146                 internal void WriteParamTable(MetadataWriter mw)
147                 {
148                         foreach (TypeBuilder type in types)
149                         {
150                                 type.WriteParamRecords(mw);
151                         }
152                 }
153
154                 internal void WriteFieldTable(MetadataWriter mw)
155                 {
156                         foreach (TypeBuilder type in types)
157                         {
158                                 type.WriteFieldRecords(mw);
159                         }
160                 }
161
162                 internal int AllocPseudoToken()
163                 {
164                         return nextPseudoToken--;
165                 }
166
167                 public TypeBuilder DefineType(string name)
168                 {
169                         return DefineType(name, TypeAttributes.Class);
170                 }
171
172                 public TypeBuilder DefineType(string name, TypeAttributes attr)
173                 {
174                         return DefineType(name, attr, null);
175                 }
176
177                 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent)
178                 {
179                         return DefineType(name, attr, parent, PackingSize.Unspecified, 0);
180                 }
181
182                 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, int typesize)
183                 {
184                         return DefineType(name, attr, parent, PackingSize.Unspecified, typesize);
185                 }
186
187                 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packsize)
188                 {
189                         return DefineType(name, attr, parent, packsize, 0);
190                 }
191
192                 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
193                 {
194                         TypeBuilder tb = DefineType(name, attr, parent);
195                         foreach (Type iface in interfaces)
196                         {
197                                 tb.AddInterfaceImplementation(iface);
198                         }
199                         return tb;
200                 }
201
202                 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
203                 {
204                         if (parent == null && (attr & TypeAttributes.Interface) == 0)
205                         {
206                                 parent = universe.System_Object;
207                         }
208                         TypeBuilder typeBuilder = new TypeBuilder(this, name, parent, attr);
209                         PostDefineType(typeBuilder, packingSize, typesize);
210                         return typeBuilder;
211                 }
212
213                 public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type underlyingType)
214                 {
215                         TypeBuilder tb = DefineType(name, (visibility & TypeAttributes.VisibilityMask) | TypeAttributes.Sealed, universe.System_Enum);
216                         FieldBuilder fb = tb.DefineField("value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
217                         return new EnumBuilder(tb, fb);
218                 }
219
220                 internal TypeBuilder DefineNestedTypeHelper(TypeBuilder enclosingType, string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
221                 {
222                         if (parent == null && (attr & TypeAttributes.Interface) == 0)
223                         {
224                                 parent = universe.System_Object;
225                         }
226                         TypeBuilder typeBuilder = new TypeBuilder(enclosingType, name, parent, attr);
227                         PostDefineType(typeBuilder, packingSize, typesize);
228                         if (enclosingType != null)
229                         {
230                                 NestedClassTable.Record rec = new NestedClassTable.Record();
231                                 rec.NestedClass = typeBuilder.MetadataToken;
232                                 rec.EnclosingClass = enclosingType.MetadataToken;
233                                 this.NestedClass.AddRecord(rec);
234                         }
235                         return typeBuilder;
236                 }
237
238                 private void PostDefineType(TypeBuilder typeBuilder, PackingSize packingSize, int typesize)
239                 {
240                         types.Add(typeBuilder);
241                         fullNameToType.Add(typeBuilder.FullName, typeBuilder);
242                         if (packingSize != PackingSize.Unspecified || typesize != 0)
243                         {
244                                 ClassLayoutTable.Record rec = new ClassLayoutTable.Record();
245                                 rec.PackingSize = (short)packingSize;
246                                 rec.ClassSize = typesize;
247                                 rec.Parent = typeBuilder.MetadataToken;
248                                 this.ClassLayout.AddRecord(rec);
249                         }
250                 }
251
252                 public FieldBuilder __DefineField(string name, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
253                 {
254                         return moduleType.DefineField(name, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
255                 }
256
257                 public ConstructorBuilder __DefineModuleInitializer(MethodAttributes visibility)
258                 {
259                         return moduleType.DefineConstructor(visibility | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, Type.EmptyTypes);
260                 }
261
262                 public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
263                 {
264                         return moduleType.DefineUninitializedData(name, size, attributes);
265                 }
266
267                 public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
268                 {
269                         return moduleType.DefineInitializedData(name, data, attributes);
270                 }
271
272                 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
273                 {
274                         return moduleType.DefineMethod(name, attributes, returnType, parameterTypes);
275                 }
276
277                 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
278                 {
279                         return moduleType.DefineMethod(name, attributes, callingConvention, returnType, parameterTypes);
280                 }
281
282                 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
283                 {
284                         return moduleType.DefineMethod(name, attributes, callingConvention, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
285                 }
286
287                 public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
288                 {
289                         return moduleType.DefinePInvokeMethod(name, dllName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
290                 }
291
292                 public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
293                 {
294                         return moduleType.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
295                 }
296
297                 public void CreateGlobalFunctions()
298                 {
299                         moduleType.CreateType();
300                 }
301
302                 internal void AddTypeForwarder(Type type)
303                 {
304                         ExportType(type);
305                         foreach (Type nested in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
306                         {
307                                 // we export all nested types (i.e. even the private ones)
308                                 // (this behavior is the same as the C# compiler)
309                                 AddTypeForwarder(nested);
310                         }
311                 }
312
313                 private int ExportType(Type type)
314                 {
315                         ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
316                         rec.TypeDefId = type.MetadataToken;
317                         rec.TypeName = this.Strings.Add(TypeNameParser.Unescape(type.Name));
318                         if (type.IsNested)
319                         {
320                                 rec.Flags = 0;
321                                 rec.TypeNamespace = 0;
322                                 rec.Implementation = ExportType(type.DeclaringType);
323                         }
324                         else
325                         {
326                                 rec.Flags = 0x00200000; // CorTypeAttr.tdForwarder
327                                 string ns = type.Namespace;
328                                 rec.TypeNamespace = ns == null ? 0 : this.Strings.Add(TypeNameParser.Unescape(ns));
329                                 rec.Implementation = ImportAssemblyRef(type.Assembly);
330                         }
331                         return 0x27000000 | this.ExportedType.FindOrAddRecord(rec);
332                 }
333
334                 public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
335                 {
336                         SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
337                 }
338
339                 public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
340                 {
341                         SetCustomAttribute(0x00000001, customBuilder);
342                 }
343
344                 internal void SetCustomAttribute(int token, CustomAttributeBuilder customBuilder)
345                 {
346                         Debug.Assert(!customBuilder.IsPseudoCustomAttribute);
347                         CustomAttributeTable.Record rec = new CustomAttributeTable.Record();
348                         rec.Parent = token;
349                         rec.Type = this.GetConstructorToken(customBuilder.Constructor).Token;
350                         rec.Value = customBuilder.WriteBlob(this);
351                         this.CustomAttribute.AddRecord(rec);
352                 }
353
354                 internal void AddDeclarativeSecurity(int token, System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
355                 {
356                         DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
357                         rec.Action = (short)securityAction;
358                         rec.Parent = token;
359                         // like Ref.Emit, we're using the .NET 1.x xml format
360                         rec.PermissionSet = this.Blobs.Add(ByteBuffer.Wrap(System.Text.Encoding.Unicode.GetBytes(permissionSet.ToXml().ToString())));
361                         this.DeclSecurity.AddRecord(rec);
362                 }
363
364                 internal void AddDeclarativeSecurity(int token, List<CustomAttributeBuilder> declarativeSecurity)
365                 {
366                         Dictionary<int, List<CustomAttributeBuilder>> ordered = new Dictionary<int, List<CustomAttributeBuilder>>();
367                         foreach (CustomAttributeBuilder cab in declarativeSecurity)
368                         {
369                                 int action;
370                                 // check for HostProtectionAttribute without SecurityAction
371                                 if (cab.ConstructorArgumentCount == 0)
372                                 {
373                                         action = (int)System.Security.Permissions.SecurityAction.LinkDemand;
374                                 }
375                                 else
376                                 {
377                                         action = (int)cab.GetConstructorArgument(0);
378                                 }
379                                 List<CustomAttributeBuilder> list;
380                                 if (!ordered.TryGetValue(action, out list))
381                                 {
382                                         list = new List<CustomAttributeBuilder>();
383                                         ordered.Add(action, list);
384                                 }
385                                 list.Add(cab);
386                         }
387                         foreach (KeyValuePair<int, List<CustomAttributeBuilder>> kv in ordered)
388                         {
389                                 DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
390                                 rec.Action = (short)kv.Key;
391                                 rec.Parent = token;
392                                 rec.PermissionSet = WriteDeclSecurityBlob(kv.Value);
393                                 this.DeclSecurity.AddRecord(rec);
394                         }
395                 }
396
397                 private int WriteDeclSecurityBlob(List<CustomAttributeBuilder> list)
398                 {
399                         ByteBuffer namedArgs = new ByteBuffer(100);
400                         ByteBuffer bb = new ByteBuffer(list.Count * 100);
401                         bb.Write((byte)'.');
402                         bb.WriteCompressedInt(list.Count);
403                         foreach (CustomAttributeBuilder cab in list)
404                         {
405                                 bb.Write(cab.Constructor.DeclaringType.AssemblyQualifiedName);
406                                 namedArgs.Clear();
407                                 cab.WriteNamedArgumentsForDeclSecurity(this, namedArgs);
408                                 bb.WriteCompressedInt(namedArgs.Length);
409                                 bb.Write(namedArgs);
410                         }
411                         return this.Blobs.Add(bb);
412                 }
413
414                 public void DefineManifestResource(string name, Stream stream, ResourceAttributes attribute)
415                 {
416                         ManifestResourceTable.Record rec = new ManifestResourceTable.Record();
417                         rec.Offset = manifestResources.Position;
418                         rec.Flags = (int)attribute;
419                         rec.Name = this.Strings.Add(name);
420                         rec.Implementation = 0;
421                         this.ManifestResource.AddRecord(rec);
422                         manifestResources.Write(0);     // placeholder for the length
423                         manifestResources.Write(stream);
424                         int savePosition = manifestResources.Position;
425                         manifestResources.Position = rec.Offset;
426                         manifestResources.Write(savePosition - (manifestResources.Position + 4));
427                         manifestResources.Position = savePosition;
428                 }
429
430                 public override Assembly Assembly
431                 {
432                         get { return asm; }
433                 }
434
435                 internal override Type GetTypeImpl(string typeName)
436                 {
437                         TypeBuilder type;
438                         fullNameToType.TryGetValue(typeName, out type);
439                         return type;
440                 }
441
442                 internal override void GetTypesImpl(List<Type> list)
443                 {
444                         foreach (Type type in types)
445                         {
446                                 if (type != moduleType)
447                                 {
448                                         list.Add(type);
449                                 }
450                         }
451                 }
452
453                 public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
454                 {
455                         return symbolWriter.DefineDocument(url, language, languageVendor, documentType);
456                 }
457
458                 public TypeToken GetTypeToken(string name)
459                 {
460                         return new TypeToken(GetType(name, true, false).MetadataToken);
461                 }
462
463                 public TypeToken GetTypeToken(Type type)
464                 {
465                         if (type.Module == this)
466                         {
467                                 return new TypeToken(type.GetModuleBuilderToken());
468                         }
469                         else
470                         {
471                                 return new TypeToken(ImportType(type));
472                         }
473                 }
474
475                 internal int GetTypeTokenForMemberRef(Type type)
476                 {
477                         if (type.IsGenericTypeDefinition)
478                         {
479                                 int token;
480                                 if (!memberRefTypeTokens.TryGetValue(type, out token))
481                                 {
482                                         ByteBuffer spec = new ByteBuffer(5);
483                                         Signature.WriteTypeSpec(this, spec, type);
484                                         token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
485                                         memberRefTypeTokens.Add(type, token);
486                                 }
487                                 return token;
488                         }
489                         else if (type.IsModulePseudoType)
490                         {
491                                 return 0x1A000000 | this.ModuleRef.FindOrAddRecord(this.Strings.Add(type.Module.ScopeName));
492                         }
493                         else
494                         {
495                                 return GetTypeToken(type).Token;
496                         }
497                 }
498
499                 private static bool IsFromGenericTypeDefinition(MemberInfo member)
500                 {
501                         Type decl = member.DeclaringType;
502                         return decl != null && decl.IsGenericTypeDefinition;
503                 }
504
505                 public FieldToken GetFieldToken(FieldInfo field)
506                 {
507                         // NOTE for some reason, when TypeBuilder.GetFieldToken() is used on a field in a generic type definition,
508                         // a memberref token is returned (confirmed on .NET) unlike for Get(Method|Constructor)Token which always
509                         // simply returns the MethodDef token (if the method is from the same module).
510                         FieldBuilder fb = field as FieldBuilder;
511                         if (fb != null && fb.Module == this && !IsFromGenericTypeDefinition(fb))
512                         {
513                                 return new FieldToken(fb.MetadataToken);
514                         }
515                         else
516                         {
517                                 return new FieldToken(ImportMember(field));
518                         }
519                 }
520
521                 public MethodToken GetMethodToken(MethodInfo method)
522                 {
523                         MethodBuilder mb = method as MethodBuilder;
524                         if (mb != null && mb.ModuleBuilder == this)
525                         {
526                                 return new MethodToken(mb.MetadataToken);
527                         }
528                         else
529                         {
530                                 return new MethodToken(ImportMember(method));
531                         }
532                 }
533
534                 // when we refer to a method on a generic type definition in the IL stream,
535                 // we need to use a MemberRef (even if the method is in the same module)
536                 internal MethodToken GetMethodTokenForIL(MethodInfo method)
537                 {
538                         if (method.IsGenericMethodDefinition)
539                         {
540                                 method = method.MakeGenericMethod(method.GetGenericArguments());
541                         }
542                         if (IsFromGenericTypeDefinition(method))
543                         {
544                                 return new MethodToken(ImportMember(method));
545                         }
546                         else
547                         {
548                                 return GetMethodToken(method);
549                         }
550                 }
551
552                 public MethodToken GetConstructorToken(ConstructorInfo constructor)
553                 {
554                         if (constructor.Module == this && constructor.GetMethodInfo() is MethodBuilder)
555                         {
556                                 return new MethodToken(constructor.MetadataToken);
557                         }
558                         else
559                         {
560                                 return new MethodToken(ImportMember(constructor));
561                         }
562                 }
563
564                 internal int ImportMember(MethodBase member)
565                 {
566                         int token;
567                         if (!importedMembers.TryGetValue(member, out token))
568                         {
569                                 token = member.ImportTo(this);
570                                 importedMembers.Add(member, token);
571                         }
572                         return token;
573                 }
574
575                 internal int ImportMember(FieldInfo member)
576                 {
577                         int token;
578                         if (!importedMembers.TryGetValue(member, out token))
579                         {
580                                 token = member.ImportTo(this);
581                                 importedMembers.Add(member, token);
582                         }
583                         return token;
584                 }
585
586                 internal int ImportMethodOrField(Type declaringType, string name, Signature sig)
587                 {
588                         int token;
589                         if (!importedMemberRefs.TryGetValue(new MemberRefKey(declaringType, name, sig), out token))
590                         {
591                                 MemberRefTable.Record rec = new MemberRefTable.Record();
592                                 rec.Class = GetTypeTokenForMemberRef(declaringType);
593                                 rec.Name = this.Strings.Add(name);
594                                 ByteBuffer bb = new ByteBuffer(16);
595                                 sig.WriteSig(this, bb);
596                                 rec.Signature = this.Blobs.Add(bb);
597                                 token = 0x0A000000 | this.MemberRef.AddRecord(rec);
598                                 importedMemberRefs.Add(new MemberRefKey(declaringType, name, sig), token);
599                         }
600                         return token;
601                 }
602
603                 internal int ImportType(Type type)
604                 {
605                         int token;
606                         if (!typeTokens.TryGetValue(type, out token))
607                         {
608                                 if (type.HasElementType || (type.IsGenericType && !type.IsGenericTypeDefinition))
609                                 {
610                                         ByteBuffer spec = new ByteBuffer(5);
611                                         Signature.WriteTypeSpec(this, spec, type);
612                                         token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
613                                 }
614                                 else
615                                 {
616                                         TypeRefTable.Record rec = new TypeRefTable.Record();
617                                         if (type.IsNested)
618                                         {
619                                                 rec.ResolutionScope = GetTypeToken(type.DeclaringType).Token;
620                                                 rec.TypeName = this.Strings.Add(TypeNameParser.Unescape(type.Name));
621                                                 rec.TypeNameSpace = 0;
622                                         }
623                                         else
624                                         {
625                                                 rec.ResolutionScope = ImportAssemblyRef(type.Assembly);
626                                                 rec.TypeName = this.Strings.Add(TypeNameParser.Unescape(type.Name));
627                                                 string ns = type.Namespace;
628                                                 rec.TypeNameSpace = ns == null ? 0 : this.Strings.Add(TypeNameParser.Unescape(ns));
629                                         }
630                                         token = 0x01000000 | this.TypeRef.AddRecord(rec);
631                                 }
632                                 typeTokens.Add(type, token);
633                         }
634                         return token;
635                 }
636
637                 private int ImportAssemblyRef(Assembly asm)
638                 {
639                         int token;
640                         if (!referencedAssemblies.TryGetValue(asm, out token))
641                         {
642                                 // We can't write the AssemblyRef record here yet, because the identity of the assembly can still change
643                                 // (if it's an AssemblyBuilder).
644                                 // We set the high bit of rid in the token to make sure we emit obviously broken metadata,
645                                 // if we forget to patch up the token somewhere.
646                                 token = 0x23800001 + referencedAssemblies.Count;
647                                 referencedAssemblies.Add(asm, token);
648                         }
649                         return token;
650                 }
651
652                 internal void FillAssemblyRefTable()
653                 {
654                         int[] realtokens = new int[referencedAssemblies.Count];
655                         foreach (KeyValuePair<Assembly, int> kv in referencedAssemblies)
656                         {
657                                 realtokens[(kv.Value & 0x7FFFFF) - 1] = FindOrAddAssemblyRef(kv.Key.GetName());
658                         }
659                         // now fixup the resolution scopes in TypeRef
660                         for (int i = 0; i < this.TypeRef.records.Length; i++)
661                         {
662                                 int resolutionScope = this.TypeRef.records[i].ResolutionScope;
663                                 if ((resolutionScope >> 24) == AssemblyRefTable.Index)
664                                 {
665                                         this.TypeRef.records[i].ResolutionScope = realtokens[(resolutionScope & 0x7FFFFF) - 1];
666                                 }
667                         }
668                         // and implementation in ExportedType
669                         for (int i = 0; i < this.ExportedType.records.Length; i++)
670                         {
671                                 int implementation = this.ExportedType.records[i].Implementation;
672                                 if ((implementation >> 24) == AssemblyRefTable.Index)
673                                 {
674                                         this.ExportedType.records[i].Implementation = realtokens[(implementation & 0x7FFFFF) - 1];
675                                 }
676                         }
677                 }
678
679                 private int FindOrAddAssemblyRef(AssemblyName name)
680                 {
681                         AssemblyRefTable.Record rec = new AssemblyRefTable.Record();
682                         Version ver = name.Version;
683                         rec.MajorVersion = (ushort)ver.Major;
684                         rec.MinorVersion = (ushort)ver.Minor;
685                         rec.BuildNumber = (ushort)ver.Build;
686                         rec.RevisionNumber = (ushort)ver.Revision;
687                         rec.Flags = (int)(name.Flags & AssemblyNameFlags.Retargetable);
688                         byte[] publicKeyOrToken = null;
689                         if (usePublicKeyAssemblyReference)
690                         {
691                                 publicKeyOrToken = name.GetPublicKey();
692                         }
693                         if (publicKeyOrToken == null || publicKeyOrToken.Length == 0)
694                         {
695                                 publicKeyOrToken = name.GetPublicKeyToken();
696                         }
697                         else
698                         {
699                                 const int PublicKey = 0x0001;
700                                 rec.Flags |= PublicKey;
701                         }
702                         rec.PublicKeyOrToken = this.Blobs.Add(ByteBuffer.Wrap(publicKeyOrToken));
703                         rec.Name = this.Strings.Add(name.Name);
704                         if (name.CultureInfo != null)
705                         {
706                                 rec.Culture = this.Strings.Add(name.CultureInfo.Name);
707                         }
708                         else
709                         {
710                                 rec.Culture = 0;
711                         }
712                         rec.HashValue = 0;
713                         return 0x23000000 | this.AssemblyRef.FindOrAddRecord(rec);
714                 }
715
716                 internal void WriteSymbolTokenMap()
717                 {
718                         for (int i = 0; i < resolvedTokens.Count; i++)
719                         {
720                                 int newToken = resolvedTokens[i];
721                                 // The symbol API doesn't support remapping arbitrary integers, the types have to be the same,
722                                 // so we copy the type from the newToken, because our pseudo tokens don't have a type.
723                                 // (see MethodToken.SymbolToken)
724                                 int oldToken = (i + 1) | (newToken & ~0xFFFFFF);
725                                 SymbolSupport.RemapToken(symbolWriter, oldToken, newToken);
726                         }
727                 }
728
729                 internal void RegisterTokenFixup(int pseudoToken, int realToken)
730                 {
731                         int index = -(pseudoToken + 1);
732                         while (resolvedTokens.Count <= index)
733                         {
734                                 resolvedTokens.Add(0);
735                         }
736                         resolvedTokens[index] = realToken;
737                 }
738
739                 internal bool IsPseudoToken(int token)
740                 {
741                         return token < 0;
742                 }
743
744                 internal int ResolvePseudoToken(int pseudoToken)
745                 {
746                         int index = -(pseudoToken + 1);
747                         return resolvedTokens[index];
748                 }
749
750                 internal void FixupMethodBodyTokens()
751                 {
752                         int methodToken = 0x06000001;
753                         int fieldToken = 0x04000001;
754                         int parameterToken = 0x08000001;
755                         foreach (TypeBuilder type in types)
756                         {
757                                 type.ResolveMethodAndFieldTokens(ref methodToken, ref fieldToken, ref parameterToken);
758                         }
759                         foreach (int offset in tokenFixupOffsets)
760                         {
761                                 methodBodies.Position = offset;
762                                 int pseudoToken = methodBodies.GetInt32AtCurrentPosition();
763                                 methodBodies.Write(ResolvePseudoToken(pseudoToken));
764                         }
765                 }
766
767                 private int GetHeaderLength()
768                 {
769                         return
770                                 4 + // Signature
771                                 2 + // MajorVersion
772                                 2 + // MinorVersion
773                                 4 + // Reserved
774                                 4 + // ImageRuntimeVersion Length
775                                 StringToPaddedUTF8Length(asm.ImageRuntimeVersion) +
776                                 2 + // Flags
777                                 2 + // Streams
778                                 4 + // #~ Offset
779                                 4 + // #~ Size
780                                 4 + // StringToPaddedUTF8Length("#~")
781                                 4 + // #Strings Offset
782                                 4 + // #Strings Size
783                                 12 + // StringToPaddedUTF8Length("#Strings")
784                                 4 + // #US Offset
785                                 4 + // #US Size
786                                 4 + // StringToPaddedUTF8Length("#US")
787                                 4 + // #GUID Offset
788                                 4 + // #GUID Size
789                                 8 + // StringToPaddedUTF8Length("#GUID")
790                                 (Blobs.IsEmpty ? 0 :
791                                 (
792                                 4 + // #Blob Offset
793                                 4 + // #Blob Size
794                                 8   // StringToPaddedUTF8Length("#Blob")
795                                 ));
796                 }
797
798                 internal int MetadataLength
799                 {
800                         get
801                         {
802                                 return GetHeaderLength() + (Blobs.IsEmpty ? 0 : Blobs.Length) + Tables.Length + Strings.Length + UserStrings.Length + Guids.Length;
803                         }
804                 }
805
806                 internal void WriteMetadata(MetadataWriter mw)
807                 {
808                         mw.Write(0x424A5342);                   // Signature ("BSJB")
809                         mw.Write((ushort)1);                    // MajorVersion
810                         mw.Write((ushort)1);                    // MinorVersion
811                         mw.Write(0);                                    // Reserved
812                         byte[] version = StringToPaddedUTF8(asm.ImageRuntimeVersion);
813                         mw.Write(version.Length);               // Length
814                         mw.Write(version);
815                         mw.Write((ushort)0);                    // Flags
816                         // #Blob is the only optional heap
817                         if (Blobs.IsEmpty)
818                         {
819                                 mw.Write((ushort)4);            // Streams
820                         }
821                         else
822                         {
823                                 mw.Write((ushort)5);            // Streams
824                         }
825
826                         int offset = GetHeaderLength();
827
828                         // Streams
829                         mw.Write(offset);                               // Offset
830                         mw.Write(Tables.Length);                // Size
831                         mw.Write(StringToPaddedUTF8("#~"));
832                         offset += Tables.Length;
833
834                         mw.Write(offset);                               // Offset
835                         mw.Write(Strings.Length);               // Size
836                         mw.Write(StringToPaddedUTF8("#Strings"));
837                         offset += Strings.Length;
838
839                         mw.Write(offset);                               // Offset
840                         mw.Write(UserStrings.Length);   // Size
841                         mw.Write(StringToPaddedUTF8("#US"));
842                         offset += UserStrings.Length;
843
844                         mw.Write(offset);                               // Offset
845                         mw.Write(Guids.Length);                 // Size
846                         mw.Write(StringToPaddedUTF8("#GUID"));
847                         offset += Guids.Length;
848
849                         if (!Blobs.IsEmpty)
850                         {
851                                 mw.Write(offset);                               // Offset
852                                 mw.Write(Blobs.Length);                 // Size
853                                 mw.Write(StringToPaddedUTF8("#Blob"));
854                         }
855
856                         Tables.Write(mw);
857                         Strings.Write(mw);
858                         UserStrings.Write(mw);
859                         Guids.Write(mw);
860                         if (!Blobs.IsEmpty)
861                         {
862                                 Blobs.Write(mw);
863                         }
864                 }
865
866                 private static int StringToPaddedUTF8Length(string str)
867                 {
868                         return (System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3;
869                 }
870
871                 private static byte[] StringToPaddedUTF8(string str)
872                 {
873                         byte[] buf = new byte[(System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3];
874                         System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, buf, 0);
875                         return buf;
876                 }
877
878                 internal override void ExportTypes(int fileToken, ModuleBuilder manifestModule)
879                 {
880                         manifestModule.ExportTypes(types.ToArray(), fileToken);
881                 }
882
883                 internal void ExportTypes(Type[] types, int fileToken)
884                 {
885                         Dictionary<Type, int> declaringTypes = new Dictionary<Type, int>();
886                         foreach (Type type in types)
887                         {
888                                 if (!type.IsModulePseudoType && IsVisible(type))
889                                 {
890                                         ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
891                                         rec.Flags = (int)type.Attributes;
892                                         rec.TypeDefId = type.MetadataToken & 0xFFFFFF;
893                                         rec.TypeName = this.Strings.Add(TypeNameParser.Unescape(type.Name));
894                                         string ns = type.Namespace;
895                                         rec.TypeNamespace = ns == null ? 0 : this.Strings.Add(TypeNameParser.Unescape(ns));
896                                         if (type.IsNested)
897                                         {
898                                                 rec.Implementation = declaringTypes[type.DeclaringType];
899                                         }
900                                         else
901                                         {
902                                                 rec.Implementation = fileToken;
903                                         }
904                                         int exportTypeToken = 0x27000000 | this.ExportedType.AddRecord(rec);
905                                         declaringTypes.Add(type, exportTypeToken);
906                                 }
907                         }
908                 }
909
910                 private static bool IsVisible(Type type)
911                 {
912                         // NOTE this is not the same as Type.IsVisible, because that doesn't take into account family access
913                         return type.IsPublic || ((type.IsNestedFamily || type.IsNestedFamORAssem || type.IsNestedPublic) && IsVisible(type.DeclaringType));
914                 }
915
916                 internal void AddConstant(int parentToken, object defaultValue)
917                 {
918                         ConstantTable.Record rec = new ConstantTable.Record();
919                         rec.Parent = parentToken;
920                         ByteBuffer val = new ByteBuffer(16);
921                         if (defaultValue == null)
922                         {
923                                 rec.Type = Signature.ELEMENT_TYPE_CLASS;
924                                 val.Write((int)0);
925                         }
926                         else if (defaultValue is bool)
927                         {
928                                 rec.Type = Signature.ELEMENT_TYPE_BOOLEAN;
929                                 val.Write((bool)defaultValue ? (byte)1 : (byte)0);
930                         }
931                         else if (defaultValue is char)
932                         {
933                                 rec.Type = Signature.ELEMENT_TYPE_CHAR;
934                                 val.Write((char)defaultValue);
935                         }
936                         else if (defaultValue is sbyte)
937                         {
938                                 rec.Type = Signature.ELEMENT_TYPE_I1;
939                                 val.Write((sbyte)defaultValue);
940                         }
941                         else if (defaultValue is byte)
942                         {
943                                 rec.Type = Signature.ELEMENT_TYPE_U1;
944                                 val.Write((byte)defaultValue);
945                         }
946                         else if (defaultValue is short)
947                         {
948                                 rec.Type = Signature.ELEMENT_TYPE_I2;
949                                 val.Write((short)defaultValue);
950                         }
951                         else if (defaultValue is ushort)
952                         {
953                                 rec.Type = Signature.ELEMENT_TYPE_U2;
954                                 val.Write((ushort)defaultValue);
955                         }
956                         else if (defaultValue is int)
957                         {
958                                 rec.Type = Signature.ELEMENT_TYPE_I4;
959                                 val.Write((int)defaultValue);
960                         }
961                         else if (defaultValue is uint)
962                         {
963                                 rec.Type = Signature.ELEMENT_TYPE_U4;
964                                 val.Write((uint)defaultValue);
965                         }
966                         else if (defaultValue is long)
967                         {
968                                 rec.Type = Signature.ELEMENT_TYPE_I8;
969                                 val.Write((long)defaultValue);
970                         }
971                         else if (defaultValue is ulong)
972                         {
973                                 rec.Type = Signature.ELEMENT_TYPE_U8;
974                                 val.Write((ulong)defaultValue);
975                         }
976                         else if (defaultValue is float)
977                         {
978                                 rec.Type = Signature.ELEMENT_TYPE_R4;
979                                 val.Write((float)defaultValue);
980                         }
981                         else if (defaultValue is double)
982                         {
983                                 rec.Type = Signature.ELEMENT_TYPE_R8;
984                                 val.Write((double)defaultValue);
985                         }
986                         else if (defaultValue is string)
987                         {
988                                 rec.Type = Signature.ELEMENT_TYPE_STRING;
989                                 foreach (char c in (string)defaultValue)
990                                 {
991                                         val.Write(c);
992                                 }
993                         }
994                         else if (defaultValue is DateTime)
995                         {
996                                 rec.Type = Signature.ELEMENT_TYPE_I8;
997                                 val.Write(((DateTime)defaultValue).Ticks);
998                         }
999                         else
1000                         {
1001                                 throw new ArgumentException();
1002                         }
1003                         rec.Value = this.Blobs.Add(val);
1004                         this.Constant.AddRecord(rec);
1005                 }
1006
1007                 ModuleBuilder ITypeOwner.ModuleBuilder
1008                 {
1009                         get { return this; }
1010                 }
1011
1012                 public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1013                 {
1014                         if (genericTypeArguments != null || genericMethodArguments != null)
1015                         {
1016                                 throw new NotImplementedException();
1017                         }
1018                         return types[(metadataToken & 0xFFFFFF) - 1];
1019                 }
1020
1021                 public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1022                 {
1023                         if (genericTypeArguments != null || genericMethodArguments != null)
1024                         {
1025                                 throw new NotImplementedException();
1026                         }
1027                         // this method is inefficient, but since it isn't used we don't care
1028                         if ((metadataToken >> 24) == MemberRefTable.Index)
1029                         {
1030                                 foreach (KeyValuePair<MemberInfo, int> kv in importedMembers)
1031                                 {
1032                                         if (kv.Value == metadataToken)
1033                                         {
1034                                                 return (MethodBase)kv.Key;
1035                                         }
1036                                 }
1037                         }
1038                         // HACK if we're given a SymbolToken, we need to convert back
1039                         if ((metadataToken & 0xFF000000) == 0x06000000)
1040                         {
1041                                 metadataToken = -(metadataToken & 0x00FFFFFF);
1042                         }
1043                         foreach (Type type in types)
1044                         {
1045                                 MethodBase method = ((TypeBuilder)type).LookupMethod(metadataToken);
1046                                 if (method != null)
1047                                 {
1048                                         return method;
1049                                 }
1050                         }
1051                         return ((TypeBuilder)moduleType).LookupMethod(metadataToken);
1052                 }
1053
1054                 public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1055                 {
1056                         throw new NotImplementedException();
1057                 }
1058
1059                 public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1060                 {
1061                         throw new NotImplementedException();
1062                 }
1063
1064                 public override string ResolveString(int metadataToken)
1065                 {
1066                         throw new NotImplementedException();
1067                 }
1068
1069                 public override string FullyQualifiedName
1070                 {
1071                         get { return Path.GetFullPath(Path.Combine(asm.dir, fileName)); }
1072                 }
1073
1074                 public override string Name
1075                 {
1076                         get { return fileName; }
1077                 }
1078
1079                 public override Guid ModuleVersionId
1080                 {
1081                         get { return mvid; }
1082                 }
1083
1084                 public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
1085                 {
1086                         throw new NotImplementedException();
1087                 }
1088
1089                 public override string ScopeName
1090                 {
1091                         get { return moduleName; }
1092                 }
1093
1094                 public ISymbolWriter GetSymWriter()
1095                 {
1096                         return symbolWriter;
1097                 }
1098
1099                 public void DefineUnmanagedResource(string resourceFileName)
1100                 {
1101                         // This method reads the specified resource file (Win32 .res file) and converts it into the appropriate format and embeds it in the .rsrc section,
1102                         // also setting the Resource Directory entry.
1103                         unmanagedResources = new ResourceSection();
1104                         unmanagedResources.ExtractResources(System.IO.File.ReadAllBytes(resourceFileName));
1105                 }
1106
1107                 public bool IsTransient()
1108                 {
1109                         return false;
1110                 }
1111
1112                 public void SetUserEntryPoint(MethodInfo entryPoint)
1113                 {
1114                         int token = entryPoint.MetadataToken;
1115                         if (token < 0)
1116                         {
1117                                 token = -token | 0x06000000;
1118                         }
1119                         if (symbolWriter != null)
1120                         {
1121                                 symbolWriter.SetUserEntryPoint(new SymbolToken(token));
1122                         }
1123                 }
1124
1125                 public StringToken GetStringConstant(string str)
1126                 {
1127                         return new StringToken(this.UserStrings.Add(str) | (0x70 << 24));
1128                 }
1129
1130                 public SignatureToken GetSignatureToken(SignatureHelper sigHelper)
1131                 {
1132                         return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(sigHelper.GetSignature(this))) | (StandAloneSigTable.Index << 24));
1133                 }
1134
1135                 public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength)
1136                 {
1137                         return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(ByteBuffer.Wrap(sigBytes, sigLength))) | (StandAloneSigTable.Index << 24));
1138                 }
1139
1140                 public MethodInfo GetArrayMethod(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1141                 {
1142                         return new ArrayMethod(this, arrayClass, methodName, callingConvention, returnType, parameterTypes);
1143                 }
1144
1145                 public MethodToken GetArrayMethodToken(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1146                 {
1147                         return GetMethodToken(GetArrayMethod(arrayClass, methodName, callingConvention, returnType, parameterTypes));
1148                 }
1149
1150                 internal override Type GetModuleType()
1151                 {
1152                         return moduleType;
1153                 }
1154
1155                 internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
1156                 {
1157                         return Blobs.GetBlob(blobIndex);
1158                 }
1159
1160                 internal int GetSignatureBlobIndex(Signature sig)
1161                 {
1162                         ByteBuffer bb = new ByteBuffer(16);
1163                         sig.WriteSig(this, bb);
1164                         return this.Blobs.Add(bb);
1165                 }
1166
1167                 // non-standard API
1168                 public long __ImageBase
1169                 {
1170                         get { return imageBaseAddress; }
1171                         set { imageBaseAddress = value; }
1172                 }
1173
1174                 public override int MDStreamVersion
1175                 {
1176                         get { return asm.mdStreamVersion; }
1177                 }
1178
1179                 private int AddTypeRefByName(int resolutionScope, string ns, string name)
1180                 {
1181                         TypeRefTable.Record rec = new TypeRefTable.Record();
1182                         rec.ResolutionScope = resolutionScope;
1183                         rec.TypeName = this.Strings.Add(name);
1184                         rec.TypeNameSpace = ns == null ? 0 : this.Strings.Add(ns);
1185                         return 0x01000000 | this.TypeRef.AddRecord(rec);
1186                 }
1187
1188                 public void __Save(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1189                 {
1190                         PopulatePropertyAndEventTables();
1191                         IList<CustomAttributeData> attributes = asm.GetCustomAttributesData(null);
1192                         if (attributes.Count > 0)
1193                         {
1194                                 int mscorlib = ImportAssemblyRef(universe.Mscorlib);
1195                                 int[] placeholderTokens = new int[4];
1196                                 string[] placeholderTypeNames = new string[] { "AssemblyAttributesGoHere", "AssemblyAttributesGoHereM", "AssemblyAttributesGoHereS", "AssemblyAttributesGoHereSM" };
1197                                 foreach (CustomAttributeData cad in attributes)
1198                                 {
1199                                         int index;
1200                                         if (cad.Constructor.DeclaringType.BaseType == universe.System_Security_Permissions_CodeAccessSecurityAttribute)
1201                                         {
1202                                                 if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1203                                                 {
1204                                                         index = 3;
1205                                                 }
1206                                                 else
1207                                                 {
1208                                                         index = 2;
1209                                                 }
1210                                         }
1211                                         else if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1212                                         {
1213                                                 index = 1;
1214                                         }
1215                                         else
1216                                         {
1217                                                 index = 0;
1218                                         }
1219                                         if (placeholderTokens[index] == 0)
1220                                         {
1221                                                 // we manually add a TypeRef without looking it up in mscorlib, because Mono and Silverlight's mscorlib don't have these types
1222                                                 placeholderTokens[index] = AddTypeRefByName(mscorlib, "System.Runtime.CompilerServices", placeholderTypeNames[index]);
1223                                         }
1224                                         SetCustomAttribute(placeholderTokens[index], cad.__ToBuilder());
1225                                 }
1226                         }
1227                         FillAssemblyRefTable();
1228                         ModuleWriter.WriteModule(null, null, this, PEFileKinds.Dll, portableExecutableKind, imageFileMachine, unmanagedResources, 0);
1229                 }
1230
1231                 public void __AddAssemblyReference(AssemblyName assemblyName)
1232                 {
1233                         if (referencedAssemblyNames == null)
1234                         {
1235                                 referencedAssemblyNames = new List<AssemblyName>();
1236                         }
1237                         FindOrAddAssemblyRef(assemblyName);
1238                         referencedAssemblyNames.Add((AssemblyName)assemblyName.Clone());
1239                 }
1240
1241                 public override AssemblyName[] __GetReferencedAssemblies()
1242                 {
1243                         List<AssemblyName> list = new List<AssemblyName>();
1244                         if (referencedAssemblyNames != null)
1245                         {
1246                                 foreach (AssemblyName name in referencedAssemblyNames)
1247                                 {
1248                                         if (!list.Contains(name))
1249                                         {
1250                                                 list.Add(name);
1251                                         }
1252                                 }
1253                         }
1254                         foreach (Assembly asm in referencedAssemblies.Keys)
1255                         {
1256                                 AssemblyName name = asm.GetName();
1257                                 if (!list.Contains(name))
1258                                 {
1259                                         list.Add(name);
1260                                 }
1261                         }
1262                         return list.ToArray();
1263                 }
1264         }
1265
1266         class ArrayMethod : MethodInfo
1267         {
1268                 private readonly Module module;
1269                 private readonly Type arrayClass;
1270                 private readonly string methodName;
1271                 private readonly CallingConventions callingConvention;
1272                 private readonly Type returnType;
1273                 protected readonly Type[] parameterTypes;
1274                 private MethodSignature methodSignature;
1275
1276                 internal ArrayMethod(Module module, Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1277                 {
1278                         this.module = module;
1279                         this.arrayClass = arrayClass;
1280                         this.methodName = methodName;
1281                         this.callingConvention = callingConvention;
1282                         this.returnType = returnType ?? module.universe.System_Void;
1283                         this.parameterTypes = Util.Copy(parameterTypes);
1284                 }
1285
1286                 public override MethodBody GetMethodBody()
1287                 {
1288                         throw new InvalidOperationException();
1289                 }
1290
1291                 public override MethodImplAttributes GetMethodImplementationFlags()
1292                 {
1293                         throw new NotSupportedException();
1294                 }
1295
1296                 public override ParameterInfo[] GetParameters()
1297                 {
1298                         throw new NotSupportedException();
1299                 }
1300
1301                 internal override int ImportTo(ModuleBuilder module)
1302                 {
1303                         return module.ImportMethodOrField(arrayClass, methodName, MethodSignature);
1304                 }
1305
1306                 public override MethodAttributes Attributes
1307                 {
1308                         get { throw new NotSupportedException(); }
1309                 }
1310
1311                 public override CallingConventions CallingConvention
1312                 {
1313                         get { return callingConvention; }
1314                 }
1315
1316                 public override Type DeclaringType
1317                 {
1318                         get { return arrayClass; }
1319                 }
1320
1321                 internal override MethodSignature MethodSignature
1322                 {
1323                         get
1324                         {
1325                                 if (methodSignature == null)
1326                                 {
1327                                         methodSignature = MethodSignature.MakeFromBuilder(returnType, parameterTypes, null, callingConvention, 0);
1328                                 }
1329                                 return methodSignature;
1330                         }
1331                 }
1332
1333                 public override Module Module
1334                 {
1335                         // like .NET, we return the module that GetArrayMethod was called on, not the module associated with the array type
1336                         get { return module; }
1337                 }
1338
1339                 public override string Name
1340                 {
1341                         get { return methodName; }
1342                 }
1343
1344                 internal override int ParameterCount
1345                 {
1346                         get { return parameterTypes.Length; }
1347                 }
1348
1349                 public override ParameterInfo ReturnParameter
1350                 {
1351                         get { throw new NotImplementedException(); }
1352                 }
1353
1354                 public override Type ReturnType
1355                 {
1356                         get { return returnType; }
1357                 }
1358
1359                 internal override bool HasThis
1360                 {
1361                         get { return (callingConvention & (CallingConventions.HasThis | CallingConventions.ExplicitThis)) == CallingConventions.HasThis; }
1362                 }
1363         }
1364 }