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