Merge branch 'bugfix'
[mono.git] / mcs / class / IKVM.Reflection / Emit / ModuleBuilder.cs
1 /*
2   Copyright (C) 2008-2011 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 Guid mvid = Guid.NewGuid();
42                 private long imageBaseAddress = 0x00400000;
43                 private long stackReserve = -1;
44                 private readonly AssemblyBuilder asm;
45                 internal readonly string moduleName;
46                 internal readonly string fileName;
47                 internal readonly ISymbolWriterImpl symbolWriter;
48                 private readonly TypeBuilder moduleType;
49                 private readonly List<TypeBuilder> types = new List<TypeBuilder>();
50                 private readonly Dictionary<Type, int> typeTokens = new Dictionary<Type, int>();
51                 private readonly Dictionary<Type, int> memberRefTypeTokens = new Dictionary<Type, int>();
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, null, "<Module>");
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                         string ns = null;
205                         int lastdot = name.LastIndexOf('.');
206                         if (lastdot > 0)
207                         {
208                                 ns = name.Substring(0, lastdot);
209                                 name = name.Substring(lastdot + 1);
210                         }
211                         TypeBuilder typeBuilder = __DefineType(ns, name);
212                         typeBuilder.__SetAttributes(attr);
213                         typeBuilder.SetParent(parent);
214                         if (packingSize != PackingSize.Unspecified || typesize != 0)
215                         {
216                                 typeBuilder.__SetLayout((int)packingSize, typesize);
217                         }
218                         return typeBuilder;
219                 }
220
221                 public TypeBuilder __DefineType(string ns, string name)
222                 {
223                         return DefineType(this, ns, name);
224                 }
225
226                 internal TypeBuilder DefineType(ITypeOwner owner, string ns, string name)
227                 {
228                         TypeBuilder typeBuilder = new TypeBuilder(owner, ns, name);
229                         types.Add(typeBuilder);
230                         return typeBuilder;
231                 }
232
233                 public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type underlyingType)
234                 {
235                         TypeBuilder tb = DefineType(name, (visibility & TypeAttributes.VisibilityMask) | TypeAttributes.Sealed, universe.System_Enum);
236                         FieldBuilder fb = tb.DefineField("value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
237                         return new EnumBuilder(tb, fb);
238                 }
239
240                 public FieldBuilder __DefineField(string name, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
241                 {
242                         return moduleType.DefineField(name, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
243                 }
244
245                 public ConstructorBuilder __DefineModuleInitializer(MethodAttributes visibility)
246                 {
247                         return moduleType.DefineConstructor(visibility | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, Type.EmptyTypes);
248                 }
249
250                 public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
251                 {
252                         return moduleType.DefineUninitializedData(name, size, attributes);
253                 }
254
255                 public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
256                 {
257                         return moduleType.DefineInitializedData(name, data, attributes);
258                 }
259
260                 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
261                 {
262                         return moduleType.DefineMethod(name, attributes, returnType, parameterTypes);
263                 }
264
265                 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
266                 {
267                         return moduleType.DefineMethod(name, attributes, callingConvention, returnType, parameterTypes);
268                 }
269
270                 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
271                 {
272                         return moduleType.DefineMethod(name, attributes, callingConvention, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
273                 }
274
275                 public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
276                 {
277                         return moduleType.DefinePInvokeMethod(name, dllName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
278                 }
279
280                 public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
281                 {
282                         return moduleType.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
283                 }
284
285                 public void CreateGlobalFunctions()
286                 {
287                         moduleType.CreateType();
288                 }
289
290                 internal void AddTypeForwarder(Type type)
291                 {
292                         ExportType(type);
293                         if (!type.__IsMissing)
294                         {
295                                 foreach (Type nested in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
296                                 {
297                                         // we export all nested types (i.e. even the private ones)
298                                         // (this behavior is the same as the C# compiler)
299                                         AddTypeForwarder(nested);
300                                 }
301                         }
302                 }
303
304                 private int ExportType(Type type)
305                 {
306                         ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
307                         MissingType missing = type as MissingType;
308                         if (missing != null)
309                         {
310                                 rec.TypeDefId = missing.GetMetadataTokenForMissing();
311                         }
312                         else
313                         {
314                                 rec.TypeDefId = type.MetadataToken;
315                         }
316                         rec.TypeName = this.Strings.Add(type.__Name);
317                         if (type.IsNested)
318                         {
319                                 rec.Flags = 0;
320                                 rec.TypeNamespace = 0;
321                                 rec.Implementation = ExportType(type.DeclaringType);
322                         }
323                         else
324                         {
325                                 rec.Flags = 0x00200000; // CorTypeAttr.tdForwarder
326                                 string ns = type.__Namespace;
327                                 rec.TypeNamespace = ns == null ? 0 : this.Strings.Add(ns);
328                                 rec.Implementation = ImportAssemblyRef(type.Assembly);
329                         }
330                         return 0x27000000 | this.ExportedType.FindOrAddRecord(rec);
331                 }
332
333                 public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
334                 {
335                         SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
336                 }
337
338                 public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
339                 {
340                         SetCustomAttribute(0x00000001, customBuilder);
341                 }
342
343                 internal void SetCustomAttribute(int token, CustomAttributeBuilder customBuilder)
344                 {
345                         Debug.Assert(!customBuilder.IsPseudoCustomAttribute);
346                         CustomAttributeTable.Record rec = new CustomAttributeTable.Record();
347                         rec.Parent = token;
348                         rec.Type = this.GetConstructorToken(customBuilder.Constructor).Token;
349                         rec.Value = customBuilder.WriteBlob(this);
350                         this.CustomAttribute.AddRecord(rec);
351                 }
352
353                 internal void AddDeclarativeSecurity(int token, System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
354                 {
355                         DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
356                         rec.Action = (short)securityAction;
357                         rec.Parent = token;
358                         // like Ref.Emit, we're using the .NET 1.x xml format
359                         rec.PermissionSet = this.Blobs.Add(ByteBuffer.Wrap(System.Text.Encoding.Unicode.GetBytes(permissionSet.ToXml().ToString())));
360                         this.DeclSecurity.AddRecord(rec);
361                 }
362
363                 internal void AddDeclarativeSecurity(int token, List<CustomAttributeBuilder> declarativeSecurity)
364                 {
365                         Dictionary<int, List<CustomAttributeBuilder>> ordered = new Dictionary<int, List<CustomAttributeBuilder>>();
366                         foreach (CustomAttributeBuilder cab in declarativeSecurity)
367                         {
368                                 int action;
369                                 // check for HostProtectionAttribute without SecurityAction
370                                 if (cab.ConstructorArgumentCount == 0)
371                                 {
372                                         action = (int)System.Security.Permissions.SecurityAction.LinkDemand;
373                                 }
374                                 else
375                                 {
376                                         action = (int)cab.GetConstructorArgument(0);
377                                 }
378                                 List<CustomAttributeBuilder> list;
379                                 if (!ordered.TryGetValue(action, out list))
380                                 {
381                                         list = new List<CustomAttributeBuilder>();
382                                         ordered.Add(action, list);
383                                 }
384                                 list.Add(cab);
385                         }
386                         foreach (KeyValuePair<int, List<CustomAttributeBuilder>> kv in ordered)
387                         {
388                                 DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
389                                 rec.Action = (short)kv.Key;
390                                 rec.Parent = token;
391                                 rec.PermissionSet = WriteDeclSecurityBlob(kv.Value);
392                                 this.DeclSecurity.AddRecord(rec);
393                         }
394                 }
395
396                 private int WriteDeclSecurityBlob(List<CustomAttributeBuilder> list)
397                 {
398                         string xml;
399                         if (list.Count == 1 && (xml = list[0].GetLegacyDeclSecurity()) != null)
400                         {
401                                 // write .NET 1.1 format
402                                 return this.Blobs.Add(ByteBuffer.Wrap(System.Text.Encoding.Unicode.GetBytes(xml)));
403                         }
404                         ByteBuffer namedArgs = new ByteBuffer(100);
405                         ByteBuffer bb = new ByteBuffer(list.Count * 100);
406                         bb.Write((byte)'.');
407                         bb.WriteCompressedInt(list.Count);
408                         foreach (CustomAttributeBuilder cab in list)
409                         {
410                                 bb.Write(cab.Constructor.DeclaringType.AssemblyQualifiedName);
411                                 namedArgs.Clear();
412                                 cab.WriteNamedArgumentsForDeclSecurity(this, namedArgs);
413                                 bb.WriteCompressedInt(namedArgs.Length);
414                                 bb.Write(namedArgs);
415                         }
416                         return this.Blobs.Add(bb);
417                 }
418
419                 public void DefineManifestResource(string name, Stream stream, ResourceAttributes attribute)
420                 {
421                         manifestResources.Align(8);
422                         ManifestResourceTable.Record rec = new ManifestResourceTable.Record();
423                         rec.Offset = manifestResources.Position;
424                         rec.Flags = (int)attribute;
425                         rec.Name = this.Strings.Add(name);
426                         rec.Implementation = 0;
427                         this.ManifestResource.AddRecord(rec);
428                         manifestResources.Write(0);     // placeholder for the length
429                         manifestResources.Write(stream);
430                         int savePosition = manifestResources.Position;
431                         manifestResources.Position = rec.Offset;
432                         manifestResources.Write(savePosition - (manifestResources.Position + 4));
433                         manifestResources.Position = savePosition;
434                 }
435
436                 public override Assembly Assembly
437                 {
438                         get { return asm; }
439                 }
440
441                 internal override Type FindType(TypeName name)
442                 {
443                         foreach (Type type in types)
444                         {
445                                 if (type.__Namespace == name.Namespace && type.__Name == name.Name)
446                                 {
447                                         return type;
448                                 }
449                         }
450                         return null;
451                 }
452
453                 internal override void GetTypesImpl(List<Type> list)
454                 {
455                         foreach (Type type in types)
456                         {
457                                 if (type != moduleType)
458                                 {
459                                         list.Add(type);
460                                 }
461                         }
462                 }
463
464                 public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
465                 {
466                         return symbolWriter.DefineDocument(url, language, languageVendor, documentType);
467                 }
468
469                 public TypeToken GetTypeToken(string name)
470                 {
471                         return new TypeToken(GetType(name, true, false).MetadataToken);
472                 }
473
474                 public TypeToken GetTypeToken(Type type)
475                 {
476                         if (type.Module == this)
477                         {
478                                 return new TypeToken(type.GetModuleBuilderToken());
479                         }
480                         else
481                         {
482                                 return new TypeToken(ImportType(type));
483                         }
484                 }
485
486                 internal int GetTypeTokenForMemberRef(Type type)
487                 {
488                         if (type.__IsMissing)
489                         {
490                                 return ImportType(type);
491                         }
492                         else if (type.IsGenericTypeDefinition)
493                         {
494                                 int token;
495                                 if (!memberRefTypeTokens.TryGetValue(type, out token))
496                                 {
497                                         ByteBuffer spec = new ByteBuffer(5);
498                                         Signature.WriteTypeSpec(this, spec, type);
499                                         token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
500                                         memberRefTypeTokens.Add(type, token);
501                                 }
502                                 return token;
503                         }
504                         else if (type.IsModulePseudoType)
505                         {
506                                 return 0x1A000000 | this.ModuleRef.FindOrAddRecord(this.Strings.Add(type.Module.ScopeName));
507                         }
508                         else
509                         {
510                                 return GetTypeToken(type).Token;
511                         }
512                 }
513
514                 private static bool IsFromGenericTypeDefinition(MemberInfo member)
515                 {
516                         Type decl = member.DeclaringType;
517                         return decl != null && !decl.__IsMissing && decl.IsGenericTypeDefinition;
518                 }
519
520                 public FieldToken GetFieldToken(FieldInfo field)
521                 {
522                         // NOTE for some reason, when TypeBuilder.GetFieldToken() is used on a field in a generic type definition,
523                         // a memberref token is returned (confirmed on .NET) unlike for Get(Method|Constructor)Token which always
524                         // simply returns the MethodDef token (if the method is from the same module).
525                         FieldBuilder fb = field as FieldBuilder;
526                         if (fb != null && fb.Module == this && !IsFromGenericTypeDefinition(fb))
527                         {
528                                 return new FieldToken(fb.MetadataToken);
529                         }
530                         else
531                         {
532                                 return new FieldToken(ImportMember(field));
533                         }
534                 }
535
536                 public MethodToken GetMethodToken(MethodInfo method)
537                 {
538                         MethodBuilder mb = method as MethodBuilder;
539                         if (mb != null && mb.ModuleBuilder == this)
540                         {
541                                 return new MethodToken(mb.MetadataToken);
542                         }
543                         else
544                         {
545                                 return new MethodToken(ImportMember(method));
546                         }
547                 }
548
549                 // when we refer to a method on a generic type definition in the IL stream,
550                 // we need to use a MemberRef (even if the method is in the same module)
551                 internal MethodToken GetMethodTokenForIL(MethodInfo method)
552                 {
553                         if (method.IsGenericMethodDefinition)
554                         {
555                                 method = method.MakeGenericMethod(method.GetGenericArguments());
556                         }
557                         if (IsFromGenericTypeDefinition(method))
558                         {
559                                 return new MethodToken(ImportMember(method));
560                         }
561                         else
562                         {
563                                 return GetMethodToken(method);
564                         }
565                 }
566
567                 public MethodToken GetConstructorToken(ConstructorInfo constructor)
568                 {
569                         if (constructor.Module == this && constructor.GetMethodInfo() is MethodBuilder)
570                         {
571                                 return new MethodToken(constructor.MetadataToken);
572                         }
573                         else
574                         {
575                                 return new MethodToken(ImportMember(constructor));
576                         }
577                 }
578
579                 internal int ImportMember(MethodBase member)
580                 {
581                         int token;
582                         if (!importedMembers.TryGetValue(member, out token))
583                         {
584                                 token = member.ImportTo(this);
585                                 importedMembers.Add(member, token);
586                         }
587                         return token;
588                 }
589
590                 internal int ImportMember(FieldInfo member)
591                 {
592                         int token;
593                         if (!importedMembers.TryGetValue(member, out token))
594                         {
595                                 token = member.ImportTo(this);
596                                 importedMembers.Add(member, token);
597                         }
598                         return token;
599                 }
600
601                 internal int ImportMethodOrField(Type declaringType, string name, Signature sig)
602                 {
603                         int token;
604                         if (!importedMemberRefs.TryGetValue(new MemberRefKey(declaringType, name, sig), out token))
605                         {
606                                 MemberRefTable.Record rec = new MemberRefTable.Record();
607                                 rec.Class = GetTypeTokenForMemberRef(declaringType);
608                                 rec.Name = this.Strings.Add(name);
609                                 ByteBuffer bb = new ByteBuffer(16);
610                                 sig.WriteSig(this, bb);
611                                 rec.Signature = this.Blobs.Add(bb);
612                                 token = 0x0A000000 | this.MemberRef.AddRecord(rec);
613                                 importedMemberRefs.Add(new MemberRefKey(declaringType, name, sig), token);
614                         }
615                         return token;
616                 }
617
618                 internal int ImportType(Type type)
619                 {
620                         int token;
621                         if (!typeTokens.TryGetValue(type, out token))
622                         {
623                                 if (type.HasElementType || type.IsGenericTypeInstance)
624                                 {
625                                         ByteBuffer spec = new ByteBuffer(5);
626                                         Signature.WriteTypeSpec(this, spec, type);
627                                         token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
628                                 }
629                                 else
630                                 {
631                                         TypeRefTable.Record rec = new TypeRefTable.Record();
632                                         if (type.IsNested)
633                                         {
634                                                 rec.ResolutionScope = GetTypeToken(type.DeclaringType).Token;
635                                         }
636                                         else
637                                         {
638                                                 rec.ResolutionScope = ImportAssemblyRef(type.Assembly);
639                                         }
640                                         rec.TypeName = this.Strings.Add(type.__Name);
641                                         string ns = type.__Namespace;
642                                         rec.TypeNameSpace = ns == null ? 0 : this.Strings.Add(ns);
643                                         token = 0x01000000 | this.TypeRef.AddRecord(rec);
644                                 }
645                                 typeTokens.Add(type, token);
646                         }
647                         return token;
648                 }
649
650                 private int ImportAssemblyRef(Assembly asm)
651                 {
652                         int token;
653                         if (!referencedAssemblies.TryGetValue(asm, out token))
654                         {
655                                 // We can't write the AssemblyRef record here yet, because the identity of the assembly can still change
656                                 // (if it's an AssemblyBuilder).
657                                 // We set the high bit of rid in the token to make sure we emit obviously broken metadata,
658                                 // if we forget to patch up the token somewhere.
659                                 token = 0x23800001 + referencedAssemblies.Count;
660                                 referencedAssemblies.Add(asm, token);
661                         }
662                         return token;
663                 }
664
665                 internal void FillAssemblyRefTable()
666                 {
667                         int[] realtokens = new int[referencedAssemblies.Count];
668                         foreach (KeyValuePair<Assembly, int> kv in referencedAssemblies)
669                         {
670                                 realtokens[(kv.Value & 0x7FFFFF) - 1] = FindOrAddAssemblyRef(kv.Key.GetName());
671                         }
672                         // now fixup the resolution scopes in TypeRef
673                         for (int i = 0; i < this.TypeRef.records.Length; i++)
674                         {
675                                 int resolutionScope = this.TypeRef.records[i].ResolutionScope;
676                                 if ((resolutionScope >> 24) == AssemblyRefTable.Index)
677                                 {
678                                         this.TypeRef.records[i].ResolutionScope = realtokens[(resolutionScope & 0x7FFFFF) - 1];
679                                 }
680                         }
681                         // and implementation in ExportedType
682                         for (int i = 0; i < this.ExportedType.records.Length; i++)
683                         {
684                                 int implementation = this.ExportedType.records[i].Implementation;
685                                 if ((implementation >> 24) == AssemblyRefTable.Index)
686                                 {
687                                         this.ExportedType.records[i].Implementation = realtokens[(implementation & 0x7FFFFF) - 1];
688                                 }
689                         }
690                 }
691
692                 private int FindOrAddAssemblyRef(AssemblyName name)
693                 {
694                         AssemblyRefTable.Record rec = new AssemblyRefTable.Record();
695                         Version ver = name.Version ?? new Version(0, 0, 0, 0);
696                         rec.MajorVersion = (ushort)ver.Major;
697                         rec.MinorVersion = (ushort)ver.Minor;
698                         rec.BuildNumber = (ushort)ver.Build;
699                         rec.RevisionNumber = (ushort)ver.Revision;
700                         rec.Flags = (int)(name.Flags & AssemblyNameFlags.Retargetable);
701                         byte[] publicKeyOrToken = null;
702                         if (usePublicKeyAssemblyReference)
703                         {
704                                 publicKeyOrToken = name.GetPublicKey();
705                         }
706                         if (publicKeyOrToken == null || publicKeyOrToken.Length == 0)
707                         {
708                                 publicKeyOrToken = name.GetPublicKeyToken() ?? Empty<byte>.Array;
709                         }
710                         else
711                         {
712                                 const int PublicKey = 0x0001;
713                                 rec.Flags |= PublicKey;
714                         }
715                         rec.PublicKeyOrToken = this.Blobs.Add(ByteBuffer.Wrap(publicKeyOrToken));
716                         rec.Name = this.Strings.Add(name.Name);
717                         if (name.CultureInfo != null)
718                         {
719                                 rec.Culture = this.Strings.Add(name.CultureInfo.Name);
720                         }
721                         else
722                         {
723                                 rec.Culture = 0;
724                         }
725                         if (name.hash != null)
726                         {
727                                 rec.HashValue = this.Blobs.Add(ByteBuffer.Wrap(name.hash));
728                         }
729                         else
730                         {
731                                 rec.HashValue = 0;
732                         }
733                         return 0x23000000 | this.AssemblyRef.FindOrAddRecord(rec);
734                 }
735
736                 internal void WriteSymbolTokenMap()
737                 {
738                         for (int i = 0; i < resolvedTokens.Count; i++)
739                         {
740                                 int newToken = resolvedTokens[i];
741                                 // The symbol API doesn't support remapping arbitrary integers, the types have to be the same,
742                                 // so we copy the type from the newToken, because our pseudo tokens don't have a type.
743                                 // (see MethodToken.SymbolToken)
744                                 int oldToken = (i + 1) | (newToken & ~0xFFFFFF);
745                                 SymbolSupport.RemapToken(symbolWriter, oldToken, newToken);
746                         }
747                 }
748
749                 internal void RegisterTokenFixup(int pseudoToken, int realToken)
750                 {
751                         int index = -(pseudoToken + 1);
752                         while (resolvedTokens.Count <= index)
753                         {
754                                 resolvedTokens.Add(0);
755                         }
756                         resolvedTokens[index] = realToken;
757                 }
758
759                 internal bool IsPseudoToken(int token)
760                 {
761                         return token < 0;
762                 }
763
764                 internal int ResolvePseudoToken(int pseudoToken)
765                 {
766                         int index = -(pseudoToken + 1);
767                         return resolvedTokens[index];
768                 }
769
770                 internal void FixupMethodBodyTokens()
771                 {
772                         int methodToken = 0x06000001;
773                         int fieldToken = 0x04000001;
774                         int parameterToken = 0x08000001;
775                         foreach (TypeBuilder type in types)
776                         {
777                                 type.ResolveMethodAndFieldTokens(ref methodToken, ref fieldToken, ref parameterToken);
778                         }
779                         foreach (int offset in tokenFixupOffsets)
780                         {
781                                 methodBodies.Position = offset;
782                                 int pseudoToken = methodBodies.GetInt32AtCurrentPosition();
783                                 methodBodies.Write(ResolvePseudoToken(pseudoToken));
784                         }
785                 }
786
787                 private int GetHeaderLength()
788                 {
789                         return
790                                 4 + // Signature
791                                 2 + // MajorVersion
792                                 2 + // MinorVersion
793                                 4 + // Reserved
794                                 4 + // ImageRuntimeVersion Length
795                                 StringToPaddedUTF8Length(asm.ImageRuntimeVersion) +
796                                 2 + // Flags
797                                 2 + // Streams
798                                 4 + // #~ Offset
799                                 4 + // #~ Size
800                                 4 + // StringToPaddedUTF8Length("#~")
801                                 4 + // #Strings Offset
802                                 4 + // #Strings Size
803                                 12 + // StringToPaddedUTF8Length("#Strings")
804                                 4 + // #US Offset
805                                 4 + // #US Size
806                                 4 + // StringToPaddedUTF8Length("#US")
807                                 4 + // #GUID Offset
808                                 4 + // #GUID Size
809                                 8 + // StringToPaddedUTF8Length("#GUID")
810                                 (Blobs.IsEmpty ? 0 :
811                                 (
812                                 4 + // #Blob Offset
813                                 4 + // #Blob Size
814                                 8   // StringToPaddedUTF8Length("#Blob")
815                                 ));
816                 }
817
818                 internal int MetadataLength
819                 {
820                         get
821                         {
822                                 return GetHeaderLength() + (Blobs.IsEmpty ? 0 : Blobs.Length) + Tables.Length + Strings.Length + UserStrings.Length + Guids.Length;
823                         }
824                 }
825
826                 internal void WriteMetadata(MetadataWriter mw)
827                 {
828                         mw.Write(0x424A5342);                   // Signature ("BSJB")
829                         mw.Write((ushort)1);                    // MajorVersion
830                         mw.Write((ushort)1);                    // MinorVersion
831                         mw.Write(0);                                    // Reserved
832                         byte[] version = StringToPaddedUTF8(asm.ImageRuntimeVersion);
833                         mw.Write(version.Length);               // Length
834                         mw.Write(version);
835                         mw.Write((ushort)0);                    // Flags
836                         // #Blob is the only optional heap
837                         if (Blobs.IsEmpty)
838                         {
839                                 mw.Write((ushort)4);            // Streams
840                         }
841                         else
842                         {
843                                 mw.Write((ushort)5);            // Streams
844                         }
845
846                         int offset = GetHeaderLength();
847
848                         // Streams
849                         mw.Write(offset);                               // Offset
850                         mw.Write(Tables.Length);                // Size
851                         mw.Write(StringToPaddedUTF8("#~"));
852                         offset += Tables.Length;
853
854                         mw.Write(offset);                               // Offset
855                         mw.Write(Strings.Length);               // Size
856                         mw.Write(StringToPaddedUTF8("#Strings"));
857                         offset += Strings.Length;
858
859                         mw.Write(offset);                               // Offset
860                         mw.Write(UserStrings.Length);   // Size
861                         mw.Write(StringToPaddedUTF8("#US"));
862                         offset += UserStrings.Length;
863
864                         mw.Write(offset);                               // Offset
865                         mw.Write(Guids.Length);                 // Size
866                         mw.Write(StringToPaddedUTF8("#GUID"));
867                         offset += Guids.Length;
868
869                         if (!Blobs.IsEmpty)
870                         {
871                                 mw.Write(offset);                               // Offset
872                                 mw.Write(Blobs.Length);                 // Size
873                                 mw.Write(StringToPaddedUTF8("#Blob"));
874                         }
875
876                         Tables.Write(mw);
877                         Strings.Write(mw);
878                         UserStrings.Write(mw);
879                         Guids.Write(mw);
880                         if (!Blobs.IsEmpty)
881                         {
882                                 Blobs.Write(mw);
883                         }
884                 }
885
886                 private static int StringToPaddedUTF8Length(string str)
887                 {
888                         return (System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3;
889                 }
890
891                 private static byte[] StringToPaddedUTF8(string str)
892                 {
893                         byte[] buf = new byte[(System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3];
894                         System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, buf, 0);
895                         return buf;
896                 }
897
898                 internal override void ExportTypes(int fileToken, ModuleBuilder manifestModule)
899                 {
900                         manifestModule.ExportTypes(types.ToArray(), fileToken);
901                 }
902
903                 internal void ExportTypes(Type[] types, int fileToken)
904                 {
905                         Dictionary<Type, int> declaringTypes = new Dictionary<Type, int>();
906                         foreach (Type type in types)
907                         {
908                                 if (!type.IsModulePseudoType && IsVisible(type))
909                                 {
910                                         ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
911                                         rec.Flags = (int)type.Attributes;
912                                         rec.TypeDefId = type.MetadataToken & 0xFFFFFF;
913                                         rec.TypeName = this.Strings.Add(type.__Name);
914                                         string ns = type.__Namespace;
915                                         rec.TypeNamespace = ns == null ? 0 : this.Strings.Add(ns);
916                                         if (type.IsNested)
917                                         {
918                                                 rec.Implementation = declaringTypes[type.DeclaringType];
919                                         }
920                                         else
921                                         {
922                                                 rec.Implementation = fileToken;
923                                         }
924                                         int exportTypeToken = 0x27000000 | this.ExportedType.AddRecord(rec);
925                                         declaringTypes.Add(type, exportTypeToken);
926                                 }
927                         }
928                 }
929
930                 private static bool IsVisible(Type type)
931                 {
932                         // NOTE this is not the same as Type.IsVisible, because that doesn't take into account family access
933                         return type.IsPublic || ((type.IsNestedFamily || type.IsNestedFamORAssem || type.IsNestedPublic) && IsVisible(type.DeclaringType));
934                 }
935
936                 internal void AddConstant(int parentToken, object defaultValue)
937                 {
938                         ConstantTable.Record rec = new ConstantTable.Record();
939                         rec.Parent = parentToken;
940                         ByteBuffer val = new ByteBuffer(16);
941                         if (defaultValue == null)
942                         {
943                                 rec.Type = Signature.ELEMENT_TYPE_CLASS;
944                                 val.Write((int)0);
945                         }
946                         else if (defaultValue is bool)
947                         {
948                                 rec.Type = Signature.ELEMENT_TYPE_BOOLEAN;
949                                 val.Write((bool)defaultValue ? (byte)1 : (byte)0);
950                         }
951                         else if (defaultValue is char)
952                         {
953                                 rec.Type = Signature.ELEMENT_TYPE_CHAR;
954                                 val.Write((char)defaultValue);
955                         }
956                         else if (defaultValue is sbyte)
957                         {
958                                 rec.Type = Signature.ELEMENT_TYPE_I1;
959                                 val.Write((sbyte)defaultValue);
960                         }
961                         else if (defaultValue is byte)
962                         {
963                                 rec.Type = Signature.ELEMENT_TYPE_U1;
964                                 val.Write((byte)defaultValue);
965                         }
966                         else if (defaultValue is short)
967                         {
968                                 rec.Type = Signature.ELEMENT_TYPE_I2;
969                                 val.Write((short)defaultValue);
970                         }
971                         else if (defaultValue is ushort)
972                         {
973                                 rec.Type = Signature.ELEMENT_TYPE_U2;
974                                 val.Write((ushort)defaultValue);
975                         }
976                         else if (defaultValue is int)
977                         {
978                                 rec.Type = Signature.ELEMENT_TYPE_I4;
979                                 val.Write((int)defaultValue);
980                         }
981                         else if (defaultValue is uint)
982                         {
983                                 rec.Type = Signature.ELEMENT_TYPE_U4;
984                                 val.Write((uint)defaultValue);
985                         }
986                         else if (defaultValue is long)
987                         {
988                                 rec.Type = Signature.ELEMENT_TYPE_I8;
989                                 val.Write((long)defaultValue);
990                         }
991                         else if (defaultValue is ulong)
992                         {
993                                 rec.Type = Signature.ELEMENT_TYPE_U8;
994                                 val.Write((ulong)defaultValue);
995                         }
996                         else if (defaultValue is float)
997                         {
998                                 rec.Type = Signature.ELEMENT_TYPE_R4;
999                                 val.Write((float)defaultValue);
1000                         }
1001                         else if (defaultValue is double)
1002                         {
1003                                 rec.Type = Signature.ELEMENT_TYPE_R8;
1004                                 val.Write((double)defaultValue);
1005                         }
1006                         else if (defaultValue is string)
1007                         {
1008                                 rec.Type = Signature.ELEMENT_TYPE_STRING;
1009                                 foreach (char c in (string)defaultValue)
1010                                 {
1011                                         val.Write(c);
1012                                 }
1013                         }
1014                         else if (defaultValue is DateTime)
1015                         {
1016                                 rec.Type = Signature.ELEMENT_TYPE_I8;
1017                                 val.Write(((DateTime)defaultValue).Ticks);
1018                         }
1019                         else
1020                         {
1021                                 throw new ArgumentException();
1022                         }
1023                         rec.Value = this.Blobs.Add(val);
1024                         this.Constant.AddRecord(rec);
1025                 }
1026
1027                 ModuleBuilder ITypeOwner.ModuleBuilder
1028                 {
1029                         get { return this; }
1030                 }
1031
1032                 public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1033                 {
1034                         if (genericTypeArguments != null || genericMethodArguments != null)
1035                         {
1036                                 throw new NotImplementedException();
1037                         }
1038                         return types[(metadataToken & 0xFFFFFF) - 1];
1039                 }
1040
1041                 public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1042                 {
1043                         if (genericTypeArguments != null || genericMethodArguments != null)
1044                         {
1045                                 throw new NotImplementedException();
1046                         }
1047                         // this method is inefficient, but since it isn't used we don't care
1048                         if ((metadataToken >> 24) == MemberRefTable.Index)
1049                         {
1050                                 foreach (KeyValuePair<MemberInfo, int> kv in importedMembers)
1051                                 {
1052                                         if (kv.Value == metadataToken)
1053                                         {
1054                                                 return (MethodBase)kv.Key;
1055                                         }
1056                                 }
1057                         }
1058                         // HACK if we're given a SymbolToken, we need to convert back
1059                         if ((metadataToken & 0xFF000000) == 0x06000000)
1060                         {
1061                                 metadataToken = -(metadataToken & 0x00FFFFFF);
1062                         }
1063                         foreach (Type type in types)
1064                         {
1065                                 MethodBase method = ((TypeBuilder)type).LookupMethod(metadataToken);
1066                                 if (method != null)
1067                                 {
1068                                         return method;
1069                                 }
1070                         }
1071                         return ((TypeBuilder)moduleType).LookupMethod(metadataToken);
1072                 }
1073
1074                 public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1075                 {
1076                         throw new NotImplementedException();
1077                 }
1078
1079                 public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1080                 {
1081                         throw new NotImplementedException();
1082                 }
1083
1084                 public override string ResolveString(int metadataToken)
1085                 {
1086                         throw new NotImplementedException();
1087                 }
1088
1089                 public override string FullyQualifiedName
1090                 {
1091                         get { return Path.GetFullPath(Path.Combine(asm.dir, fileName)); }
1092                 }
1093
1094                 public override string Name
1095                 {
1096                         get { return fileName; }
1097                 }
1098
1099                 public override Guid ModuleVersionId
1100                 {
1101                         get { return mvid; }
1102                 }
1103
1104                 public void __SetModuleVersionId(Guid guid)
1105                 {
1106                         mvid = guid;
1107                 }
1108
1109                 public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
1110                 {
1111                         throw new NotImplementedException();
1112                 }
1113
1114                 public override string ScopeName
1115                 {
1116                         get { return moduleName; }
1117                 }
1118
1119                 public ISymbolWriter GetSymWriter()
1120                 {
1121                         return symbolWriter;
1122                 }
1123
1124                 public void DefineUnmanagedResource(string resourceFileName)
1125                 {
1126                         // This method reads the specified resource file (Win32 .res file) and converts it into the appropriate format and embeds it in the .rsrc section,
1127                         // also setting the Resource Directory entry.
1128                         unmanagedResources = new ResourceSection();
1129                         unmanagedResources.ExtractResources(System.IO.File.ReadAllBytes(resourceFileName));
1130                 }
1131
1132                 public bool IsTransient()
1133                 {
1134                         return false;
1135                 }
1136
1137                 public void SetUserEntryPoint(MethodInfo entryPoint)
1138                 {
1139                         int token = entryPoint.MetadataToken;
1140                         if (token < 0)
1141                         {
1142                                 token = -token | 0x06000000;
1143                         }
1144                         if (symbolWriter != null)
1145                         {
1146                                 symbolWriter.SetUserEntryPoint(new SymbolToken(token));
1147                         }
1148                 }
1149
1150                 public StringToken GetStringConstant(string str)
1151                 {
1152                         return new StringToken(this.UserStrings.Add(str) | (0x70 << 24));
1153                 }
1154
1155                 public SignatureToken GetSignatureToken(SignatureHelper sigHelper)
1156                 {
1157                         return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(sigHelper.GetSignature(this))) | (StandAloneSigTable.Index << 24));
1158                 }
1159
1160                 public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength)
1161                 {
1162                         return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(ByteBuffer.Wrap(sigBytes, sigLength))) | (StandAloneSigTable.Index << 24));
1163                 }
1164
1165                 public MethodInfo GetArrayMethod(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1166                 {
1167                         return new ArrayMethod(this, arrayClass, methodName, callingConvention, returnType, parameterTypes);
1168                 }
1169
1170                 public MethodToken GetArrayMethodToken(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1171                 {
1172                         return GetMethodToken(GetArrayMethod(arrayClass, methodName, callingConvention, returnType, parameterTypes));
1173                 }
1174
1175                 internal override Type GetModuleType()
1176                 {
1177                         return moduleType;
1178                 }
1179
1180                 internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
1181                 {
1182                         return Blobs.GetBlob(blobIndex);
1183                 }
1184
1185                 internal int GetSignatureBlobIndex(Signature sig)
1186                 {
1187                         ByteBuffer bb = new ByteBuffer(16);
1188                         sig.WriteSig(this, bb);
1189                         return this.Blobs.Add(bb);
1190                 }
1191
1192                 // non-standard API
1193                 public new long __ImageBase
1194                 {
1195                         get { return imageBaseAddress; }
1196                         set { imageBaseAddress = value; }
1197                 }
1198
1199                 protected override long GetImageBaseImpl()
1200                 {
1201                         return imageBaseAddress;
1202                 }
1203
1204                 public override long __StackReserve
1205                 {
1206                         get { return stackReserve; }
1207                 }
1208
1209                 public void __SetStackReserve(long stackReserve)
1210                 {
1211                         this.stackReserve = stackReserve;
1212                 }
1213
1214                 internal ulong GetStackReserve(ulong defaultValue)
1215                 {
1216                         return stackReserve == -1 ? defaultValue : (ulong)stackReserve;
1217                 }
1218
1219                 public override int MDStreamVersion
1220                 {
1221                         get { return asm.mdStreamVersion; }
1222                 }
1223
1224                 private int AddTypeRefByName(int resolutionScope, string ns, string name)
1225                 {
1226                         TypeRefTable.Record rec = new TypeRefTable.Record();
1227                         rec.ResolutionScope = resolutionScope;
1228                         rec.TypeName = this.Strings.Add(name);
1229                         rec.TypeNameSpace = ns == null ? 0 : this.Strings.Add(ns);
1230                         return 0x01000000 | this.TypeRef.AddRecord(rec);
1231                 }
1232
1233                 public void __Save(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1234                 {
1235                         SaveImpl(null, portableExecutableKind, imageFileMachine);
1236                 }
1237
1238                 public void __Save(Stream stream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1239                 {
1240                         if (!stream.CanRead || !stream.CanWrite || !stream.CanSeek || stream.Position != 0)
1241                         {
1242                                 throw new ArgumentException("Stream must support read/write/seek and current position must be zero.", "stream");
1243                         }
1244                         SaveImpl(stream, portableExecutableKind, imageFileMachine);
1245                 }
1246
1247                 private void SaveImpl(Stream streamOrNull, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1248                 {
1249                         PopulatePropertyAndEventTables();
1250                         IList<CustomAttributeData> attributes = asm.GetCustomAttributesData(null);
1251                         if (attributes.Count > 0)
1252                         {
1253                                 int mscorlib = ImportAssemblyRef(universe.Mscorlib);
1254                                 int[] placeholderTokens = new int[4];
1255                                 string[] placeholderTypeNames = new string[] { "AssemblyAttributesGoHere", "AssemblyAttributesGoHereM", "AssemblyAttributesGoHereS", "AssemblyAttributesGoHereSM" };
1256                                 foreach (CustomAttributeData cad in attributes)
1257                                 {
1258                                         int index;
1259                                         if (cad.Constructor.DeclaringType.BaseType == universe.System_Security_Permissions_CodeAccessSecurityAttribute)
1260                                         {
1261                                                 if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1262                                                 {
1263                                                         index = 3;
1264                                                 }
1265                                                 else
1266                                                 {
1267                                                         index = 2;
1268                                                 }
1269                                         }
1270                                         else if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1271                                         {
1272                                                 index = 1;
1273                                         }
1274                                         else
1275                                         {
1276                                                 index = 0;
1277                                         }
1278                                         if (placeholderTokens[index] == 0)
1279                                         {
1280                                                 // we manually add a TypeRef without looking it up in mscorlib, because Mono and Silverlight's mscorlib don't have these types
1281                                                 placeholderTokens[index] = AddTypeRefByName(mscorlib, "System.Runtime.CompilerServices", placeholderTypeNames[index]);
1282                                         }
1283                                         SetCustomAttribute(placeholderTokens[index], cad.__ToBuilder());
1284                                 }
1285                         }
1286                         FillAssemblyRefTable();
1287                         ModuleWriter.WriteModule(null, null, this, PEFileKinds.Dll, portableExecutableKind, imageFileMachine, unmanagedResources, 0, streamOrNull);
1288                 }
1289
1290                 public void __AddAssemblyReference(AssemblyName assemblyName)
1291                 {
1292                         if (referencedAssemblyNames == null)
1293                         {
1294                                 referencedAssemblyNames = new List<AssemblyName>();
1295                         }
1296                         FindOrAddAssemblyRef(assemblyName);
1297                         referencedAssemblyNames.Add((AssemblyName)assemblyName.Clone());
1298                 }
1299
1300                 public override AssemblyName[] __GetReferencedAssemblies()
1301                 {
1302                         List<AssemblyName> list = new List<AssemblyName>();
1303                         if (referencedAssemblyNames != null)
1304                         {
1305                                 foreach (AssemblyName name in referencedAssemblyNames)
1306                                 {
1307                                         if (!list.Contains(name))
1308                                         {
1309                                                 list.Add(name);
1310                                         }
1311                                 }
1312                         }
1313                         foreach (Assembly asm in referencedAssemblies.Keys)
1314                         {
1315                                 AssemblyName name = asm.GetName();
1316                                 if (!list.Contains(name))
1317                                 {
1318                                         list.Add(name);
1319                                 }
1320                         }
1321                         return list.ToArray();
1322                 }
1323
1324                 public void __AddModuleReference(string module)
1325                 {
1326                         this.ModuleRef.FindOrAddRecord(module == null ? 0 : this.Strings.Add(module));
1327                 }
1328
1329                 public override string[] __GetReferencedModules()
1330                 {
1331                         string[] arr = new string[this.ModuleRef.RowCount];
1332                         for (int i = 0; i < arr.Length; i++)
1333                         {
1334                                 arr[i] = this.Strings.Find(this.ModuleRef.records[i]);
1335                         }
1336                         return arr;
1337                 }
1338
1339                 public override Type[] __GetReferencedTypes()
1340                 {
1341                         List<Type> list = new List<Type>();
1342                         foreach (KeyValuePair<Type, int> kv in typeTokens)
1343                         {
1344                                 if (kv.Value >> 24 == TypeRefTable.Index)
1345                                 {
1346                                         list.Add(kv.Key);
1347                                 }
1348                         }
1349                         return list.ToArray();
1350                 }
1351
1352                 public override Type[] __GetExportedTypes()
1353                 {
1354                         throw new NotImplementedException();
1355                 }
1356
1357                 public int __AddModule(int flags, string name, byte[] hash)
1358                 {
1359                         FileTable.Record file = new FileTable.Record();
1360                         file.Flags = flags;
1361                         file.Name = this.Strings.Add(name);
1362                         file.HashValue = this.Blobs.Add(ByteBuffer.Wrap(hash));
1363                         return 0x26000000 + this.File.AddRecord(file);
1364                 }
1365
1366                 public int __AddManifestResource(int offset, ResourceAttributes flags, string name, int implementation)
1367                 {
1368                         ManifestResourceTable.Record res = new ManifestResourceTable.Record();
1369                         res.Offset = offset;
1370                         res.Flags = (int)flags;
1371                         res.Name = this.Strings.Add(name);
1372                         res.Implementation = implementation;
1373                         return 0x28000000 + this.ManifestResource.AddRecord(res);
1374                 }
1375
1376                 public void __SetCustomAttributeFor(int token, CustomAttributeBuilder customBuilder)
1377                 {
1378                         SetCustomAttribute(token, customBuilder);
1379                 }
1380         }
1381
1382         class ArrayMethod : MethodInfo
1383         {
1384                 private readonly Module module;
1385                 private readonly Type arrayClass;
1386                 private readonly string methodName;
1387                 private readonly CallingConventions callingConvention;
1388                 private readonly Type returnType;
1389                 protected readonly Type[] parameterTypes;
1390                 private MethodSignature methodSignature;
1391
1392                 internal ArrayMethod(Module module, Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1393                 {
1394                         this.module = module;
1395                         this.arrayClass = arrayClass;
1396                         this.methodName = methodName;
1397                         this.callingConvention = callingConvention;
1398                         this.returnType = returnType ?? module.universe.System_Void;
1399                         this.parameterTypes = Util.Copy(parameterTypes);
1400                 }
1401
1402                 public override MethodBody GetMethodBody()
1403                 {
1404                         throw new InvalidOperationException();
1405                 }
1406
1407                 public override MethodImplAttributes GetMethodImplementationFlags()
1408                 {
1409                         throw new NotSupportedException();
1410                 }
1411
1412                 public override ParameterInfo[] GetParameters()
1413                 {
1414                         throw new NotSupportedException();
1415                 }
1416
1417                 internal override int ImportTo(ModuleBuilder module)
1418                 {
1419                         return module.ImportMethodOrField(arrayClass, methodName, MethodSignature);
1420                 }
1421
1422                 public override MethodAttributes Attributes
1423                 {
1424                         get { throw new NotSupportedException(); }
1425                 }
1426
1427                 public override CallingConventions CallingConvention
1428                 {
1429                         get { return callingConvention; }
1430                 }
1431
1432                 public override Type DeclaringType
1433                 {
1434                         get { return arrayClass; }
1435                 }
1436
1437                 internal override MethodSignature MethodSignature
1438                 {
1439                         get
1440                         {
1441                                 if (methodSignature == null)
1442                                 {
1443                                         methodSignature = MethodSignature.MakeFromBuilder(returnType, parameterTypes, null, callingConvention, 0);
1444                                 }
1445                                 return methodSignature;
1446                         }
1447                 }
1448
1449                 public override Module Module
1450                 {
1451                         // like .NET, we return the module that GetArrayMethod was called on, not the module associated with the array type
1452                         get { return module; }
1453                 }
1454
1455                 public override string Name
1456                 {
1457                         get { return methodName; }
1458                 }
1459
1460                 internal override int ParameterCount
1461                 {
1462                         get { return parameterTypes.Length; }
1463                 }
1464
1465                 public override ParameterInfo ReturnParameter
1466                 {
1467                         get { throw new NotImplementedException(); }
1468                 }
1469
1470                 public override Type ReturnType
1471                 {
1472                         get { return returnType; }
1473                 }
1474
1475                 internal override bool HasThis
1476                 {
1477                         get { return (callingConvention & (CallingConventions.HasThis | CallingConventions.ExplicitThis)) == CallingConventions.HasThis; }
1478                 }
1479         }
1480 }