2 Copyright (C) 2008-2011 Jeroen Frijters
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.
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:
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.
25 using System.Collections.Generic;
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;
36 namespace IKVM.Reflection.Emit
38 public sealed class ModuleBuilder : Module, ITypeOwner
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;
72 internal struct VTableFixups
74 internal uint initializedDataOffset;
75 internal ushort count;
78 internal int SlotWidth
80 get { return (type & 0x02) == 0 ? 4 : 8; }
84 struct InterfaceImplCustomAttribute
87 internal int interfaceType;
88 internal int pseudoToken;
91 struct MemberRefKey : IEquatable<MemberRefKey>
93 private readonly Type type;
94 private readonly string name;
95 private readonly Signature signature;
97 internal MemberRefKey(Type type, string name, Signature signature)
101 this.signature = signature;
104 public bool Equals(MemberRefKey other)
106 return other.type.Equals(type)
107 && other.name == name
108 && other.signature.Equals(signature);
111 public override bool Equals(object obj)
113 MemberRefKey? other = obj as MemberRefKey?;
114 return other != null && Equals(other);
117 public override int GetHashCode()
119 return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode();
123 internal ModuleBuilder(AssemblyBuilder asm, string moduleName, string fileName, bool emitSymbolInfo)
127 this.moduleName = moduleName;
128 this.fileName = fileName;
131 symbolWriter = SymbolSupport.CreateSymbolWriterFor(this);
133 // <Module> must be the first record in the TypeDef table
134 moduleType = new TypeBuilder(this, null, "<Module>");
135 types.Add(moduleType);
138 internal void PopulatePropertyAndEventTables()
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)
145 type.PopulatePropertyAndEventTables();
149 internal void WriteTypeDefTable(MetadataWriter mw)
153 foreach (TypeBuilder type in types)
155 type.WriteTypeDefRecord(mw, ref fieldList, ref methodList);
159 internal void WriteMethodDefTable(int baseRVA, MetadataWriter mw)
162 foreach (TypeBuilder type in types)
164 type.WriteMethodDefRecords(baseRVA, mw, ref paramList);
168 internal void WriteParamTable(MetadataWriter mw)
170 foreach (TypeBuilder type in types)
172 type.WriteParamRecords(mw);
176 internal void WriteFieldTable(MetadataWriter mw)
178 foreach (TypeBuilder type in types)
180 type.WriteFieldRecords(mw);
184 internal int AllocPseudoToken()
186 return nextPseudoToken--;
189 public TypeBuilder DefineType(string name)
191 return DefineType(name, TypeAttributes.Class);
194 public TypeBuilder DefineType(string name, TypeAttributes attr)
196 return DefineType(name, attr, null);
199 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent)
201 return DefineType(name, attr, parent, PackingSize.Unspecified, 0);
204 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, int typesize)
206 return DefineType(name, attr, parent, PackingSize.Unspecified, typesize);
209 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packsize)
211 return DefineType(name, attr, parent, packsize, 0);
214 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
216 TypeBuilder tb = DefineType(name, attr, parent);
217 foreach (Type iface in interfaces)
219 tb.AddInterfaceImplementation(iface);
224 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
227 int lastdot = name.LastIndexOf('.');
230 ns = name.Substring(0, lastdot);
231 name = name.Substring(lastdot + 1);
233 TypeBuilder typeBuilder = __DefineType(ns, name);
234 typeBuilder.__SetAttributes(attr);
235 typeBuilder.SetParent(parent);
236 if (packingSize != PackingSize.Unspecified || typesize != 0)
238 typeBuilder.__SetLayout((int)packingSize, typesize);
243 public TypeBuilder __DefineType(string ns, string name)
245 return DefineType(this, ns, name);
248 internal TypeBuilder DefineType(ITypeOwner owner, string ns, string name)
250 TypeBuilder typeBuilder = new TypeBuilder(owner, ns, name);
251 types.Add(typeBuilder);
255 public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type underlyingType)
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);
262 public FieldBuilder __DefineField(string name, Type type, CustomModifiers customModifiers, FieldAttributes attributes)
264 return moduleType.__DefineField(name, type, customModifiers, attributes);
267 [Obsolete("Please use __DefineField(string, Type, CustomModifiers, FieldAttributes) instead.")]
268 public FieldBuilder __DefineField(string name, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
270 return moduleType.DefineField(name, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
273 public ConstructorBuilder __DefineModuleInitializer(MethodAttributes visibility)
275 return moduleType.DefineConstructor(visibility | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, Type.EmptyTypes);
278 public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
280 return moduleType.DefineUninitializedData(name, size, attributes);
283 public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
285 return moduleType.DefineInitializedData(name, data, attributes);
288 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
290 return moduleType.DefineMethod(name, attributes, returnType, parameterTypes);
293 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
295 return moduleType.DefineMethod(name, attributes, callingConvention, returnType, parameterTypes);
298 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
300 return moduleType.DefineMethod(name, attributes, callingConvention, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
303 public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
305 return moduleType.DefinePInvokeMethod(name, dllName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
308 public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
310 return moduleType.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
313 public void CreateGlobalFunctions()
315 moduleType.CreateType();
318 internal void AddTypeForwarder(Type type)
321 if (!type.__IsMissing)
323 foreach (Type nested in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
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);
332 private int ExportType(Type type)
334 ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
335 MissingType missing = type as MissingType;
338 rec.TypeDefId = missing.GetMetadataTokenForMissing();
342 rec.TypeDefId = type.MetadataToken;
344 rec.TypeName = this.Strings.Add(type.__Name);
348 rec.TypeNamespace = 0;
349 rec.Implementation = ExportType(type.DeclaringType);
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);
358 return 0x27000000 | this.ExportedType.FindOrAddRecord(rec);
361 public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
363 SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
366 public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
368 SetCustomAttribute(0x00000001, customBuilder);
371 internal void SetCustomAttribute(int token, CustomAttributeBuilder customBuilder)
373 Debug.Assert(!customBuilder.IsPseudoCustomAttribute);
374 CustomAttributeTable.Record rec = new CustomAttributeTable.Record();
376 rec.Type = this.GetConstructorToken(customBuilder.Constructor).Token;
377 rec.Value = customBuilder.WriteBlob(this);
378 this.CustomAttribute.AddRecord(rec);
381 internal void AddDeclarativeSecurity(int token, System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
383 DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
384 rec.Action = (short)securityAction;
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);
391 internal void AddDeclarativeSecurity(int token, List<CustomAttributeBuilder> declarativeSecurity)
393 Dictionary<int, List<CustomAttributeBuilder>> ordered = new Dictionary<int, List<CustomAttributeBuilder>>();
394 foreach (CustomAttributeBuilder cab in declarativeSecurity)
397 // check for HostProtectionAttribute without SecurityAction
398 if (cab.ConstructorArgumentCount == 0)
400 action = (int)System.Security.Permissions.SecurityAction.LinkDemand;
404 action = (int)cab.GetConstructorArgument(0);
406 List<CustomAttributeBuilder> list;
407 if (!ordered.TryGetValue(action, out list))
409 list = new List<CustomAttributeBuilder>();
410 ordered.Add(action, list);
414 foreach (KeyValuePair<int, List<CustomAttributeBuilder>> kv in ordered)
416 DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
417 rec.Action = (short)kv.Key;
419 rec.PermissionSet = WriteDeclSecurityBlob(kv.Value);
420 this.DeclSecurity.AddRecord(rec);
424 private int WriteDeclSecurityBlob(List<CustomAttributeBuilder> list)
427 if (list.Count == 1 && (xml = list[0].GetLegacyDeclSecurity()) != null)
429 // write .NET 1.1 format
430 return this.Blobs.Add(ByteBuffer.Wrap(System.Text.Encoding.Unicode.GetBytes(xml)));
432 ByteBuffer namedArgs = new ByteBuffer(100);
433 ByteBuffer bb = new ByteBuffer(list.Count * 100);
435 bb.WriteCompressedInt(list.Count);
436 foreach (CustomAttributeBuilder cab in list)
438 bb.Write(cab.Constructor.DeclaringType.AssemblyQualifiedName);
440 cab.WriteNamedArgumentsForDeclSecurity(this, namedArgs);
441 bb.WriteCompressedInt(namedArgs.Length);
444 return this.Blobs.Add(bb);
447 public void DefineManifestResource(string name, Stream stream, ResourceAttributes attribute)
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;
464 public override Assembly Assembly
469 internal override Type FindType(TypeName name)
471 foreach (Type type in types)
473 if (type.__Namespace == name.Namespace && type.__Name == name.Name)
481 internal override void GetTypesImpl(List<Type> list)
483 foreach (Type type in types)
485 if (type != moduleType)
492 public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
494 return symbolWriter.DefineDocument(url, language, languageVendor, documentType);
497 public TypeToken GetTypeToken(string name)
499 return new TypeToken(GetType(name, true, false).MetadataToken);
502 public TypeToken GetTypeToken(Type type)
504 if (type.Module == this)
506 return new TypeToken(type.GetModuleBuilderToken());
510 return new TypeToken(ImportType(type));
514 internal int GetTypeTokenForMemberRef(Type type)
516 if (type.__IsMissing)
518 return ImportType(type);
520 else if (type.IsGenericTypeDefinition)
523 if (!memberRefTypeTokens.TryGetValue(type, out token))
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);
532 else if (type.IsModulePseudoType)
534 return 0x1A000000 | this.ModuleRef.FindOrAddRecord(this.Strings.Add(type.Module.ScopeName));
538 return GetTypeToken(type).Token;
542 private static bool IsFromGenericTypeDefinition(MemberInfo member)
544 Type decl = member.DeclaringType;
545 return decl != null && !decl.__IsMissing && decl.IsGenericTypeDefinition;
548 public FieldToken GetFieldToken(FieldInfo field)
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))
556 return new FieldToken(fb.MetadataToken);
560 return new FieldToken(ImportMember(field));
564 public MethodToken GetMethodToken(MethodInfo method)
566 MethodBuilder mb = method as MethodBuilder;
567 if (mb != null && mb.ModuleBuilder == this)
569 return new MethodToken(mb.MetadataToken);
573 return new MethodToken(ImportMember(method));
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)
581 if (method.IsGenericMethodDefinition)
583 method = method.MakeGenericMethod(method.GetGenericArguments());
585 if (IsFromGenericTypeDefinition(method))
587 return new MethodToken(ImportMember(method));
591 return GetMethodToken(method);
595 public MethodToken GetConstructorToken(ConstructorInfo constructor)
597 if (constructor.Module == this && constructor.GetMethodInfo() is MethodBuilder)
599 return new MethodToken(constructor.MetadataToken);
603 return new MethodToken(ImportMember(constructor));
607 internal int ImportMember(MethodBase member)
610 if (!importedMembers.TryGetValue(member, out token))
612 token = member.ImportTo(this);
613 importedMembers.Add(member, token);
618 internal int ImportMember(FieldInfo member)
621 if (!importedMembers.TryGetValue(member, out token))
623 token = member.ImportTo(this);
624 importedMembers.Add(member, token);
629 internal int ImportMethodOrField(Type declaringType, string name, Signature sig)
632 if (!importedMemberRefs.TryGetValue(new MemberRefKey(declaringType, name, sig), out token))
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);
646 internal int ImportType(Type type)
649 if (!typeTokens.TryGetValue(type, out token))
651 if (type.HasElementType || type.IsGenericTypeInstance)
653 ByteBuffer spec = new ByteBuffer(5);
654 Signature.WriteTypeSpec(this, spec, type);
655 token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
659 TypeRefTable.Record rec = new TypeRefTable.Record();
662 rec.ResolutionScope = GetTypeToken(type.DeclaringType).Token;
666 rec.ResolutionScope = ImportAssemblyRef(type.Assembly);
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);
673 typeTokens.Add(type, token);
678 private int ImportAssemblyRef(Assembly asm)
681 if (!referencedAssemblies.TryGetValue(asm, out token))
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);
693 internal void FillAssemblyRefTable()
695 int[] realtokens = new int[referencedAssemblies.Count];
696 foreach (KeyValuePair<Assembly, int> kv in referencedAssemblies)
698 if ((kv.Value & 0x7F800000) == 0x23800000)
700 realtokens[(kv.Value & 0x7FFFFF) - 1] = FindOrAddAssemblyRef(kv.Key.GetName(), false);
703 // now fixup the resolution scopes in TypeRef
704 for (int i = 0; i < this.TypeRef.records.Length; i++)
706 int resolutionScope = this.TypeRef.records[i].ResolutionScope;
707 if ((resolutionScope & 0x7F800000) == 0x23800000)
709 this.TypeRef.records[i].ResolutionScope = realtokens[(resolutionScope & 0x7FFFFF) - 1];
712 // and implementation in ExportedType
713 for (int i = 0; i < this.ExportedType.records.Length; i++)
715 int implementation = this.ExportedType.records[i].Implementation;
716 if ((implementation & 0x7F800000) == 0x23800000)
718 this.ExportedType.records[i].Implementation = realtokens[(implementation & 0x7FFFFF) - 1];
723 private int FindOrAddAssemblyRef(AssemblyName name, bool alwaysAdd)
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)
736 rec.Flags |= (int)(name.RawFlags & afPA_Mask);
738 byte[] publicKeyOrToken = null;
739 if (usePublicKeyAssemblyReference)
741 publicKeyOrToken = name.GetPublicKey();
743 if (publicKeyOrToken == null || publicKeyOrToken.Length == 0)
745 publicKeyOrToken = name.GetPublicKeyToken() ?? Empty<byte>.Array;
749 const int PublicKey = 0x0001;
750 rec.Flags |= PublicKey;
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)
757 rec.HashValue = this.Blobs.Add(ByteBuffer.Wrap(name.hash));
763 return 0x23000000 | (alwaysAdd ? this.AssemblyRef.AddRecord(rec) : this.AssemblyRef.FindOrAddRecord(rec));
766 internal void WriteSymbolTokenMap()
768 for (int i = 0; i < resolvedTokens.Count; i++)
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);
779 internal void RegisterTokenFixup(int pseudoToken, int realToken)
781 int index = -(pseudoToken + 1);
782 while (resolvedTokens.Count <= index)
784 resolvedTokens.Add(0);
786 resolvedTokens[index] = realToken;
789 internal bool IsPseudoToken(int token)
794 internal int ResolvePseudoToken(int pseudoToken)
796 int index = -(pseudoToken + 1);
797 return resolvedTokens[index];
800 internal void ApplyUnmanagedExports(ImageFileMachine imageFileMachine)
802 if (unmanagedExports.Count != 0)
806 if (imageFileMachine == ImageFileMachine.I386)
816 List<MethodBuilder> methods = new List<MethodBuilder>();
817 for (int i = 0; i < unmanagedExports.Count; i++)
819 if (unmanagedExports[i].mb != null)
821 methods.Add(unmanagedExports[i].mb);
824 if (methods.Count != 0)
826 RelativeVirtualAddress rva = __AddVTableFixups(methods.ToArray(), type);
827 for (int i = 0; i < unmanagedExports.Count; i++)
829 if (unmanagedExports[i].mb != null)
831 UnmanagedExport exp = unmanagedExports[i];
832 exp.rva = new RelativeVirtualAddress(rva.initializedDataOffset + (uint)(methods.IndexOf(unmanagedExports[i].mb) * size));
833 unmanagedExports[i] = exp;
840 internal void FixupMethodBodyTokens()
842 int methodToken = 0x06000001;
843 int fieldToken = 0x04000001;
844 int parameterToken = 0x08000001;
845 foreach (TypeBuilder type in types)
847 type.ResolveMethodAndFieldTokens(ref methodToken, ref fieldToken, ref parameterToken);
849 foreach (int offset in tokenFixupOffsets)
851 methodBodies.Position = offset;
852 int pseudoToken = methodBodies.GetInt32AtCurrentPosition();
853 methodBodies.Write(ResolvePseudoToken(pseudoToken));
855 foreach (VTableFixups fixup in vtablefixups)
857 for (int i = 0; i < fixup.count; i++)
859 initializedData.Position = (int)fixup.initializedDataOffset + i * fixup.SlotWidth;
860 initializedData.Write(ResolvePseudoToken(initializedData.GetInt32AtCurrentPosition()));
865 private int GetHeaderLength()
872 4 + // ImageRuntimeVersion Length
873 StringToPaddedUTF8Length(asm.ImageRuntimeVersion) +
878 4 + // StringToPaddedUTF8Length("#~")
879 4 + // #Strings Offset
881 12 + // StringToPaddedUTF8Length("#Strings")
884 4 + // StringToPaddedUTF8Length("#US")
887 8 + // StringToPaddedUTF8Length("#GUID")
892 8 // StringToPaddedUTF8Length("#Blob")
896 internal int MetadataLength
900 return GetHeaderLength() + (Blobs.IsEmpty ? 0 : Blobs.Length) + Tables.Length + Strings.Length + UserStrings.Length + Guids.Length;
904 internal void WriteMetadata(MetadataWriter mw)
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
913 mw.Write((ushort)0); // Flags
914 // #Blob is the only optional heap
917 mw.Write((ushort)4); // Streams
921 mw.Write((ushort)5); // Streams
924 int offset = GetHeaderLength();
927 mw.Write(offset); // Offset
928 mw.Write(Tables.Length); // Size
929 mw.Write(StringToPaddedUTF8("#~"));
930 offset += Tables.Length;
932 mw.Write(offset); // Offset
933 mw.Write(Strings.Length); // Size
934 mw.Write(StringToPaddedUTF8("#Strings"));
935 offset += Strings.Length;
937 mw.Write(offset); // Offset
938 mw.Write(UserStrings.Length); // Size
939 mw.Write(StringToPaddedUTF8("#US"));
940 offset += UserStrings.Length;
942 mw.Write(offset); // Offset
943 mw.Write(Guids.Length); // Size
944 mw.Write(StringToPaddedUTF8("#GUID"));
945 offset += Guids.Length;
949 mw.Write(offset); // Offset
950 mw.Write(Blobs.Length); // Size
951 mw.Write(StringToPaddedUTF8("#Blob"));
956 UserStrings.Write(mw);
964 private static int StringToPaddedUTF8Length(string str)
966 return (System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3;
969 private static byte[] StringToPaddedUTF8(string str)
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);
976 internal override void ExportTypes(int fileToken, ModuleBuilder manifestModule)
978 manifestModule.ExportTypes(types.ToArray(), fileToken);
981 internal void ExportTypes(Type[] types, int fileToken)
983 Dictionary<Type, int> declaringTypes = new Dictionary<Type, int>();
984 foreach (Type type in types)
986 if (!type.IsModulePseudoType && IsVisible(type))
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);
996 rec.Implementation = declaringTypes[type.DeclaringType];
1000 rec.Implementation = fileToken;
1002 int exportTypeToken = 0x27000000 | this.ExportedType.AddRecord(rec);
1003 declaringTypes.Add(type, exportTypeToken);
1008 private static bool IsVisible(Type type)
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));
1014 internal void AddConstant(int parentToken, object defaultValue)
1016 ConstantTable.Record rec = new ConstantTable.Record();
1017 rec.Parent = parentToken;
1018 ByteBuffer val = new ByteBuffer(16);
1019 if (defaultValue == null)
1021 rec.Type = Signature.ELEMENT_TYPE_CLASS;
1024 else if (defaultValue is bool)
1026 rec.Type = Signature.ELEMENT_TYPE_BOOLEAN;
1027 val.Write((bool)defaultValue ? (byte)1 : (byte)0);
1029 else if (defaultValue is char)
1031 rec.Type = Signature.ELEMENT_TYPE_CHAR;
1032 val.Write((char)defaultValue);
1034 else if (defaultValue is sbyte)
1036 rec.Type = Signature.ELEMENT_TYPE_I1;
1037 val.Write((sbyte)defaultValue);
1039 else if (defaultValue is byte)
1041 rec.Type = Signature.ELEMENT_TYPE_U1;
1042 val.Write((byte)defaultValue);
1044 else if (defaultValue is short)
1046 rec.Type = Signature.ELEMENT_TYPE_I2;
1047 val.Write((short)defaultValue);
1049 else if (defaultValue is ushort)
1051 rec.Type = Signature.ELEMENT_TYPE_U2;
1052 val.Write((ushort)defaultValue);
1054 else if (defaultValue is int)
1056 rec.Type = Signature.ELEMENT_TYPE_I4;
1057 val.Write((int)defaultValue);
1059 else if (defaultValue is uint)
1061 rec.Type = Signature.ELEMENT_TYPE_U4;
1062 val.Write((uint)defaultValue);
1064 else if (defaultValue is long)
1066 rec.Type = Signature.ELEMENT_TYPE_I8;
1067 val.Write((long)defaultValue);
1069 else if (defaultValue is ulong)
1071 rec.Type = Signature.ELEMENT_TYPE_U8;
1072 val.Write((ulong)defaultValue);
1074 else if (defaultValue is float)
1076 rec.Type = Signature.ELEMENT_TYPE_R4;
1077 val.Write((float)defaultValue);
1079 else if (defaultValue is double)
1081 rec.Type = Signature.ELEMENT_TYPE_R8;
1082 val.Write((double)defaultValue);
1084 else if (defaultValue is string)
1086 rec.Type = Signature.ELEMENT_TYPE_STRING;
1087 foreach (char c in (string)defaultValue)
1092 else if (defaultValue is DateTime)
1094 rec.Type = Signature.ELEMENT_TYPE_I8;
1095 val.Write(((DateTime)defaultValue).Ticks);
1099 throw new ArgumentException();
1101 rec.Value = this.Blobs.Add(val);
1102 this.Constant.AddRecord(rec);
1105 ModuleBuilder ITypeOwner.ModuleBuilder
1107 get { return this; }
1110 public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1112 if (genericTypeArguments != null || genericMethodArguments != null)
1114 throw new NotImplementedException();
1116 return types[(metadataToken & 0xFFFFFF) - 1];
1119 public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1121 if (genericTypeArguments != null || genericMethodArguments != null)
1123 throw new NotImplementedException();
1125 // this method is inefficient, but since it isn't used we don't care
1126 if ((metadataToken >> 24) == MemberRefTable.Index)
1128 foreach (KeyValuePair<MemberInfo, int> kv in importedMembers)
1130 if (kv.Value == metadataToken)
1132 return (MethodBase)kv.Key;
1136 // HACK if we're given a SymbolToken, we need to convert back
1137 if ((metadataToken & 0xFF000000) == 0x06000000)
1139 metadataToken = -(metadataToken & 0x00FFFFFF);
1141 foreach (Type type in types)
1143 MethodBase method = ((TypeBuilder)type).LookupMethod(metadataToken);
1149 return ((TypeBuilder)moduleType).LookupMethod(metadataToken);
1152 public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1154 throw new NotImplementedException();
1157 public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1159 throw new NotImplementedException();
1162 public override string ResolveString(int metadataToken)
1164 throw new NotImplementedException();
1167 public override string FullyQualifiedName
1169 get { return Path.GetFullPath(Path.Combine(asm.dir, fileName)); }
1172 public override string Name
1174 get { return fileName; }
1177 public override Guid ModuleVersionId
1179 get { return mvid; }
1182 public void __SetModuleVersionId(Guid guid)
1187 public override Type[] __ResolveOptionalParameterTypes(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments, out CustomModifiers[] customModifiers)
1189 throw new NotImplementedException();
1192 public override string ScopeName
1194 get { return moduleName; }
1197 public ISymbolWriter GetSymWriter()
1199 return symbolWriter;
1202 public void DefineUnmanagedResource(string resourceFileName)
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));
1210 public bool IsTransient()
1215 public void SetUserEntryPoint(MethodInfo entryPoint)
1217 int token = entryPoint.MetadataToken;
1220 token = -token | 0x06000000;
1222 if (symbolWriter != null)
1224 symbolWriter.SetUserEntryPoint(new SymbolToken(token));
1228 public StringToken GetStringConstant(string str)
1230 return new StringToken(this.UserStrings.Add(str) | (0x70 << 24));
1233 public SignatureToken GetSignatureToken(SignatureHelper sigHelper)
1235 return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(sigHelper.GetSignature(this))) | (StandAloneSigTable.Index << 24));
1238 public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength)
1240 return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(ByteBuffer.Wrap(sigBytes, sigLength))) | (StandAloneSigTable.Index << 24));
1243 public MethodInfo GetArrayMethod(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1245 return new ArrayMethod(this, arrayClass, methodName, callingConvention, returnType, parameterTypes);
1248 public MethodToken GetArrayMethodToken(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1250 return GetMethodToken(GetArrayMethod(arrayClass, methodName, callingConvention, returnType, parameterTypes));
1253 internal override Type GetModuleType()
1258 internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
1260 return Blobs.GetBlob(blobIndex);
1263 internal int GetSignatureBlobIndex(Signature sig)
1265 ByteBuffer bb = new ByteBuffer(16);
1266 sig.WriteSig(this, bb);
1267 return this.Blobs.Add(bb);
1271 public new long __ImageBase
1273 get { return imageBaseAddress; }
1274 set { imageBaseAddress = value; }
1277 protected override long GetImageBaseImpl()
1279 return imageBaseAddress;
1282 public override long __StackReserve
1284 get { return stackReserve; }
1287 public void __SetStackReserve(long stackReserve)
1289 this.stackReserve = stackReserve;
1292 internal ulong GetStackReserve(ulong defaultValue)
1294 return stackReserve == -1 ? defaultValue : (ulong)stackReserve;
1297 public override int MDStreamVersion
1299 get { return asm.mdStreamVersion; }
1302 private int AddTypeRefByName(int resolutionScope, string ns, string name)
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);
1311 public void __Save(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1313 SaveImpl(null, portableExecutableKind, imageFileMachine);
1316 public void __Save(Stream stream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1318 if (!stream.CanRead || !stream.CanWrite || !stream.CanSeek || stream.Position != 0)
1320 throw new ArgumentException("Stream must support read/write/seek and current position must be zero.", "stream");
1322 SaveImpl(stream, portableExecutableKind, imageFileMachine);
1325 private void SaveImpl(Stream streamOrNull, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1327 PopulatePropertyAndEventTables();
1328 IList<CustomAttributeData> attributes = asm.GetCustomAttributesData(null);
1329 if (attributes.Count > 0)
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)
1337 if (cad.Constructor.DeclaringType.BaseType == universe.System_Security_Permissions_CodeAccessSecurityAttribute)
1339 if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1348 else if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1356 if (placeholderTokens[index] == 0)
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]);
1361 SetCustomAttribute(placeholderTokens[index], cad.__ToBuilder());
1364 FillAssemblyRefTable();
1365 ModuleWriter.WriteModule(null, null, this, PEFileKinds.Dll, portableExecutableKind, imageFileMachine, unmanagedResources, 0, streamOrNull);
1368 public void __AddAssemblyReference(AssemblyName assemblyName)
1370 __AddAssemblyReference(assemblyName, null);
1373 public void __AddAssemblyReference(AssemblyName assemblyName, Assembly assembly)
1375 if (referencedAssemblyNames == null)
1377 referencedAssemblyNames = new List<AssemblyName>();
1379 referencedAssemblyNames.Add((AssemblyName)assemblyName.Clone());
1380 int token = FindOrAddAssemblyRef(assemblyName, true);
1381 if (assembly != null)
1383 referencedAssemblies.Add(assembly, token);
1387 public override AssemblyName[] __GetReferencedAssemblies()
1389 List<AssemblyName> list = new List<AssemblyName>();
1390 if (referencedAssemblyNames != null)
1392 foreach (AssemblyName name in referencedAssemblyNames)
1394 if (!list.Contains(name))
1400 foreach (Assembly asm in referencedAssemblies.Keys)
1402 AssemblyName name = asm.GetName();
1403 if (!list.Contains(name))
1408 return list.ToArray();
1411 public void __AddModuleReference(string module)
1413 this.ModuleRef.FindOrAddRecord(module == null ? 0 : this.Strings.Add(module));
1416 public override string[] __GetReferencedModules()
1418 string[] arr = new string[this.ModuleRef.RowCount];
1419 for (int i = 0; i < arr.Length; i++)
1421 arr[i] = this.Strings.Find(this.ModuleRef.records[i]);
1426 public override Type[] __GetReferencedTypes()
1428 List<Type> list = new List<Type>();
1429 foreach (KeyValuePair<Type, int> kv in typeTokens)
1431 if (kv.Value >> 24 == TypeRefTable.Index)
1436 return list.ToArray();
1439 public override Type[] __GetExportedTypes()
1441 throw new NotImplementedException();
1444 public int __AddModule(int flags, string name, byte[] hash)
1446 FileTable.Record file = new FileTable.Record();
1448 file.Name = this.Strings.Add(name);
1449 file.HashValue = this.Blobs.Add(ByteBuffer.Wrap(hash));
1450 return 0x26000000 + this.File.AddRecord(file);
1453 public int __AddManifestResource(int offset, ResourceAttributes flags, string name, int implementation)
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);
1463 public void __SetCustomAttributeFor(int token, CustomAttributeBuilder customBuilder)
1465 SetCustomAttribute(token, customBuilder);
1468 public RelativeVirtualAddress __AddVTableFixups(MethodBuilder[] methods, int type)
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)
1477 initializedData.Write(mb.MetadataToken);
1478 if (fixups.SlotWidth == 8)
1480 initializedData.Write(0);
1483 vtablefixups.Add(fixups);
1484 return new RelativeVirtualAddress(fixups.initializedDataOffset);
1487 public void __AddUnmanagedExportStub(string name, int ordinal, RelativeVirtualAddress rva)
1489 AddUnmanagedExport(name, ordinal, null, rva);
1492 internal void AddUnmanagedExport(string name, int ordinal, MethodBuilder methodBuilder, RelativeVirtualAddress rva)
1494 UnmanagedExport export;
1496 export.ordinal = ordinal;
1497 export.mb = methodBuilder;
1499 unmanagedExports.Add(export);
1502 internal void SetInterfaceImplementationCustomAttribute(TypeBuilder typeBuilder, Type interfaceType, CustomAttributeBuilder cab)
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)
1508 interfaceImplCustomAttributes = new List<InterfaceImplCustomAttribute>();
1510 InterfaceImplCustomAttribute rec;
1511 rec.type = typeBuilder.MetadataToken;
1512 int token = GetTypeToken(interfaceType).Token;
1513 switch (token >> 24)
1515 case TypeDefTable.Index:
1516 token = (token & 0xFFFFFF) << 2 | 0;
1518 case TypeRefTable.Index:
1519 token = (token & 0xFFFFFF) << 2 | 1;
1521 case TypeSpecTable.Index:
1522 token = (token & 0xFFFFFF) << 2 | 2;
1525 throw new InvalidOperationException();
1527 rec.interfaceType = token;
1528 rec.pseudoToken = AllocPseudoToken();
1529 interfaceImplCustomAttributes.Add(rec);
1530 SetCustomAttribute(rec.pseudoToken, cab);
1533 internal void ResolveInterfaceImplPseudoTokens()
1535 if (interfaceImplCustomAttributes != null)
1537 foreach (InterfaceImplCustomAttribute rec in interfaceImplCustomAttributes)
1539 for (int i = 0; i < InterfaceImpl.records.Length; i++)
1541 if (InterfaceImpl.records[i].Class == rec.type && InterfaceImpl.records[i].Interface == rec.interfaceType)
1543 RegisterTokenFixup(rec.pseudoToken, (InterfaceImplTable.Index << 24) | (i + 1));
1552 struct UnmanagedExport
1554 internal string name;
1555 internal int ordinal;
1556 internal RelativeVirtualAddress rva;
1557 internal MethodBuilder mb;
1560 public struct RelativeVirtualAddress
1562 internal readonly uint initializedDataOffset;
1564 internal RelativeVirtualAddress(uint initializedDataOffset)
1566 this.initializedDataOffset = initializedDataOffset;
1569 public static RelativeVirtualAddress operator +(RelativeVirtualAddress rva, int offset)
1571 return new RelativeVirtualAddress(rva.initializedDataOffset + (uint)offset);
1575 class ArrayMethod : MethodInfo
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;
1585 internal ArrayMethod(Module module, Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
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);
1595 public override MethodBody GetMethodBody()
1597 throw new InvalidOperationException();
1600 public override MethodImplAttributes GetMethodImplementationFlags()
1602 throw new NotSupportedException();
1605 public override ParameterInfo[] GetParameters()
1607 throw new NotSupportedException();
1610 internal override int ImportTo(ModuleBuilder module)
1612 return module.ImportMethodOrField(arrayClass, methodName, MethodSignature);
1615 public override MethodAttributes Attributes
1617 get { throw new NotSupportedException(); }
1620 public override CallingConventions CallingConvention
1622 get { return callingConvention; }
1625 public override Type DeclaringType
1627 get { return arrayClass; }
1630 internal override MethodSignature MethodSignature
1634 if (methodSignature == null)
1636 methodSignature = MethodSignature.MakeFromBuilder(returnType, parameterTypes, new PackedCustomModifiers(), callingConvention, 0);
1638 return methodSignature;
1642 public override Module Module
1644 // like .NET, we return the module that GetArrayMethod was called on, not the module associated with the array type
1645 get { return module; }
1648 public override string Name
1650 get { return methodName; }
1653 internal override int ParameterCount
1655 get { return parameterTypes.Length; }
1658 public override ParameterInfo ReturnParameter
1660 get { throw new NotImplementedException(); }
1663 public override Type ReturnType
1665 get { return returnType; }
1668 internal override bool HasThis
1670 get { return (callingConvention & (CallingConventions.HasThis | CallingConventions.ExplicitThis)) == CallingConventions.HasThis; }