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